4. Types and Traits¶
4.1. Types¶
Syntax
TypeSpecification
::=ImplTraitTypeSpecification
|TraitObjectTypeSpecification
|TypeSpecificationWithoutBounds
TypeSpecificationList
::=TypeSpecification
(,TypeSpecification
)* ,?TypeSpecificationWithoutBounds
::=ArrayTypeSpecification
|FunctionPointerTypeSpecification
|ImplTraitTypeSpecificationOneBound
|InferredType
|MacroInvocation
|NeverType
|ParenthesizedTypeSpecification
|QualifiedTypePath
|RawPointerTypeSpecification
|ReferenceTypeSpecification
|SliceTypeSpecification
|TraitObjectTypeSpecificationOneBound
|TupleTypeSpecification
|TypePath
TypeAscription
::= :TypeSpecification
Legality Rules
4.1:1 A type defines a set of values and a set of operations that act on those values.
4.1:2 A local type is a type that is defined in the current crate.
4.2. Type Classification¶
Note
The contents of this section are informational.
Legality Rules
4.2:1 Types are organized in the following categories:
4.2:2 Scalar types
4.2:5 Numeric types
4.2:6 Floating-point type
4.2:7 Integer type
4.2:8 Sequence types
4.2:9 Array types
4.2:10 Slice types
4.2:12 Tuple types
4.2:13 Abstract data types
4.2:14 Enum types
4.2:15 Struct types
4.2:16 Union types
4.2:17 Function types
4.2:18 Closure types
4.2:19 Function item types
4.2:20 Indirection types
4.2:21 Function pointer types
4.2:22 Raw pointer types
4.2:23 Reference types
4.2:24 Trait types
4.2:25 Impl trait types
4.2:26 Trait object types
4.2:27 Other types
4.2:28 Inferred types
4.2:29 Never type
4.2:30 Parenthesized types
4.3. Scalar Types¶
4.3.1. Bool Type¶
Legality Rules
4.3.1:1
Bool
is a type whose values denote the truth values of
logic and Boolean algebra.
4.3.1:2
Type bool
appears in the language prelude under the name
bool
.
4.3.1:3
Boolean value false
has bit pattern 0x00
. Boolean value
true
has bit pattern 0x01
.
4.3.1:4
The following operations are defined on type bool
:
4.3.1:5 Logical not
4.3.1:6 |
a |
!a |
4.3.1:7 |
|
|
4.3.1:8 |
|
|
4.3.1:9 Logical and
4.3.1:10 |
a |
b |
a & b |
4.3.1:11 |
|
|
|
4.3.1:12 |
|
|
|
4.3.1:13 |
|
|
|
4.3.1:14 |
|
|
|
4.3.1:15 Logical or
4.3.1:16 |
a |
b |
a | b |
4.3.1:17 |
|
|
|
4.3.1:18 |
|
|
|
4.3.1:19 |
|
|
|
4.3.1:20 |
|
|
|
4.3.1:21 Logical exclusive or (xor)
4.3.1:22 |
a |
b |
a ^ b |
4.3.1:23 |
|
|
|
4.3.1:24 |
|
|
|
4.3.1:25 |
|
|
|
4.3.1:26 |
|
|
|
4.3.1:27 Equality
4.3.1:28 |
a |
b |
a == b |
4.3.1:29 |
|
|
|
4.3.1:30 |
|
|
|
4.3.1:31 |
|
|
|
4.3.1:32 |
|
|
|
4.3.1:33 Greater than
4.3.1:34 |
a |
b |
a > b |
4.3.1:35 |
|
|
|
4.3.1:36 |
|
|
|
4.3.1:37 |
|
|
|
4.3.1:38 |
|
|
|
4.3.1:39
Operation a != b
is equivalent to !(a == b)
.
4.3.1:40
Operation a >= b
is equivalent to a == b | a > b
.
4.3.1:41
Operation a < b
is equivalent to !(a >= b)
.
4.3.1:42
Operation a <= b
is equivalent to a == b | a < b
.
Undefined Behavior
4.3.1:43
It is a validity invariant for a value of type bool
to have
a bit pattern of 0x00
and 0x01
.
4.3.2. Char Type¶
Legality Rules
4.3.2:1
Char
is a type whose values are represented as a 32-bit
unsigned word in the 0x000 - 0xD7FF or the 0xE000 - 0x10FFFF inclusive ranges
of Unicode.
Undefined Behavior
4.3.2:2
It is a validity invariant for a value of type char
to be
inside the 0x000 - 0xD7FF or the 0xE000 - 0x10FFFF inclusive ranges of
Unicode.
4.3.3. Numeric Types¶
4.3.3.1. Floating Point Types¶
Legality Rules
4.3.3.1:1
Type f32
is equivalent to the IEEE 754-2008 binary32 type.
4.3.3.1:2
Type f64
is equivalent to the IEEE 754-2008 binary64 type.
4.3.3.2. Integer Types¶
Legality Rules
4.3.3.2:1 Unsigned integer types define the following inclusive ranges over the domain of whole numbers:
4.3.3.2:2 |
Type |
Minimum |
Maximum |
4.3.3.2:3 |
0 |
28 - 1 |
|
4.3.3.2:4 |
0 |
216 - 1 |
|
4.3.3.2:5 |
0 |
232 - 1 |
|
4.3.3.2:6 |
0 |
264 - 1 |
|
4.3.3.2:7 |
0 |
2128 - 1 |
4.3.3.2:8
Type usize
has the same number of bits as the platform’s
pointer type, and is at least 16-bits wide.
4.3.3.2:9 Signed integer types define the following inclusive ranges over the domain of whole numbers:
4.3.3.2:10 |
Type |
Minimum |
Maximum |
4.3.3.2:11 |
- (27) |
27 - 1 |
|
4.3.3.2:12 |
- (215) |
215 - 1 |
|
4.3.3.2:13 |
- (231) |
231 - 1 |
|
4.3.3.2:14 |
- (263) |
263 - 1 |
|
4.3.3.2:15 |
- (2127) |
2127 - 1 |
4.3.3.2:16
Type isize
has the same number of bits as the platform’s
pointer type, and is at least 16-bits wide.
4.4. Sequence Types¶
4.4.1. Array Types¶
Syntax
ArrayTypeSpecification
::= [ElementType
;SizeOperand
]ElementType
::=TypeSpecification
Legality Rules
4.4.1:1 An array type is a sequence type that represents a fixed sequence of elements.
4.4.1:2 The element type shall be a fixed sized type.
4.4.1:3 The size operand shall be a constant expression.
4.4.1:4
The type of the size operand is type usize
.
Examples
4.4.1:5 An array type in the context of a let statement:
let array: [i32; 3] = [1, 2, 3];
4.4.2. Slice Types¶
Syntax
SliceTypeSpecification
::= [ElementType
]
Legality Rules
4.4.2:1 A slice type is a sequence type that provides a view into a sequence of elements.
4.4.2:2 The element type shall be a fixed sized type.
4.4.2:3 A slice type is a dynamically sized type.
Examples
4.4.2:4 A slice type in the context of a let statement:
let array: [i32; 3] = [1, 2, 3];
let slice: &[i32] = &array[0..1];
4.4.3. Str Type¶
Legality Rules
4.4.3:1
Str
is a sequence type that represents a slice of 8-bit unsigned
bytes.
4.4.3:2
Type str
is a dynamically sized type.
4.4.3:3
A value of type str
shall denote a valid UTF-8 sequence of
characters.
Undefined Behavior
4.4.3:4
It is a safety invariant for a value of type str
to denote
a valid UTF-8 sequence of characters.
4.4.4. Tuple Types¶
Syntax
TupleTypeSpecification
::= (TupleFieldList
? )TupleFieldList
::=TupleField
(,TupleField
)* ,?TupleField
::=TypeSpecification
Legality Rules
4.4.4:1 A tuple type is a sequence type that represents a heterogeneous list of other types.
4.4.4:2
If the type of a tuple field is a dynamically-sized type, then
the tuple field shall be the last tuple field in the
TupleFieldList
.
Examples
()
(char,)
(i32, f64, Vec<String>)
4.5. Abstract Data Types¶
4.5.1. Enum Types¶
Syntax
EnumDeclaration
::= enumName
GenericParameterList
?WhereClause
? {EnumVariantList
? }EnumVariantList
::=EnumVariant
(,EnumVariant
)* ,?EnumVariant
::=OuterAttributeOrDoc
*VisibilityModifier
?Name
EnumVariantKind
?EnumVariantKind
::=DiscriminantInitializer
|RecordStructFieldList
|TupleStructFieldList
DiscriminantInitializer
::= =Expression
Legality Rules
4.5.1:1 An enum type is an abstract data type that contains enum variants.
4.5.1:2 A zero-variant enum type has no values.
4.5.1:3 An enum variant is a construct that declares one of the possible variations of an enum.
4.5.1:4
The name of an enum variant shall be unique within the related
EnumDeclaration
.
B.176:1 A discriminant is an opaque integer that identifies an enum variant.
4.5.1:6
A discriminant initializer shall be specified only when all enum
variants appear without an EnumVariantKind
.
4.5.1:7 The type of the expression of a discriminant initializer shall be either:
4.5.1:8 The type of the primitive representation specified by attribute
repr
, or
4.5.1:10 The value of the expression of a discriminant initializer shall be a constant expression.
4.5.1:11 The value of a discriminant of an enum variant is determined as follows:
4.5.1:12 If the enum variant contains a discriminant initializer, then the value is the value of its expression.
4.5.1:13 Otherwise, if the enum variant is the first enum variant in the
EnumVariantList
, then the value is zero.4.5.1:14 Otherwise the value is one greater than the value of the discriminant of the previous enum variant.
4.5.1:15 It is a static error if two enum variants have discriminants with the same value.
4.5.1:16 It is a static error if the value of a discriminant exceeds the maximum value of the type of the expression of a discriminant initializer.
Undefined Behavior
4.5.1:17 It is a validity invariant for a value of an enum type to have a discriminant specified by the enum type.
Examples
enum ZeroVariantEnumType {}
enum Animal {
Cat,
Dog(String),
Otter { name: String, weight: f64, age: u8 }
}
enum Discriminants {
First, // The discriminant is 0.
Second, // The discriminant is 1.
Third = 12, // The discriminant is 12.
Fourth, // The discriminant is 13.
Fifth = 34, // The discriminant is 34.
Sixth // The discriminant is 35.
}
4.5.2. Struct Types¶
Syntax
StructDeclaration
::=RecordStructDeclaration
|TupleStructDeclaration
|UnitStructDeclaration
RecordStructDeclaration
::= structName
GenericParameterList
?WhereClause
?RecordStructFieldList
RecordStructFieldList
::= { (RecordStructField
(,RecordStructField
)* ,?)? }RecordStructField
::=OuterAttributeOrDoc
*VisibilityModifier
?Name
TypeAscription
TupleStructDeclaration
::= structName
GenericParameterList
?TupleStructFieldList
WhereClause
? ;TupleStructFieldList
::= ( (TupleStructField
(,TupleStructField
)* ,?)? )TupleStructField
::=OuterAttributeOrDoc
*VisibilityModifier
?TypeSpecification
UnitStructDeclaration
::= structName
GenericParameterList
?WhereClause
? ;
Legality Rules
4.5.2:1 A struct type is an abstract data type that is a product of other types.
4.5.2:2
The name of a record struct field shall be unique within the
related RecordStructDeclaration
.
4.5.2:3
If the type of a record struct field is a dynamically sized type,
then the record struct field shall be the last record struct field in
the RecordStructFieldList
.
4.5.2:4
If the type of a tuple struct field is a dynamically sized type,
then the tuple struct field shall be the last tuple struct field in
the TupleStructFieldList
.
Examples
struct UnitStruct;
struct AnimalRecordStruct {
name: String,
weight: f64,
age: u8
}
struct AnimalTupleStruct (
String,
f64,
u8
);
4.5.3. Union Types¶
Syntax
UnionDeclaration
::= unionName
GenericParameterList
?WhereClause
?RecordStructFieldList
Legality Rules
4.5.3:1 A union type is an abstract data type that is a sum of other types.
4.5.3:2 A union without any union fields is rejected, but may still be consumed by macros.
4.5.3:3
The name of a union field shall be unique within the related
RecordStructDeclaration
.
4.5.3:4 The type of a union field shall be either:
4.5.3:5 A copy type, or
4.5.3:6 A mutable reference type, or
4.5.3:7
core::mem::ManuallyDrop
, or4.5.3:8 A tuple type whose tuple fields‘ types are all valid union field types, or
4.5.3:9 An array type whose element type is a valid union field types.
Examples
union LeafNode {
int: i32,
float: f32,
double: f64
}
4.6. Function Types¶
4.6.1. Closure Types¶
Legality Rules
4.6.1:1 A closure type is a unique anonymous function type that encapsulates all capture targets of a closure expression.
4.6.1:2
A closure type implements the core::ops::FnOnce
trait.
4.6.1:3
A closure type that does not move out its capture targets
implements the core::ops::FnMut
trait.
4.6.1:4
A closure type that does not move out or mutate its capture targets
implements the core::ops::Fn
trait.
4.6.1:5 A closure type that does not encapsulate capture targets is coercible to a function pointer type.
4.6.1:6
A closure type implicitly implements the core::marker::Copy
trait if all the types of the values of the
capturing environment implement the core::marker::Copy
trait.
4.6.1:7
A closure type implicitly implements the core::clone::Clone
trait if all the types of the values of the
capturing environment implement the core::clone::Clone
trait.
4.6.1:8
A closure type implicitly implements the core::marker::Send
trait if all the types of the values of the
capturing environment implement the core::marker::Send
trait.
4.6.1:9
A closure type implicitly implements the core::marker::Sync
trait if all the types of the values of the capturing
environment implement the core::marker::Send
trait.
4.6.2. Function Item Types¶
Legality Rules
4.6.2:1 A function item type is a unique anonymous function type that identifies a function.
4.6.2:2 An external function item type is a function item type where the related function is an external function.
4.6.2:3 An unsafe function item type is a function item type where the related function is an unsafe function.
4.6.2:4 A function item type is coercible to a function pointer type.
4.6.2:5
A function item type implements the core::clone::Clone
trait,
the core::marker::Copy
trait, the core::ops::Fn
trait,
the core::ops::FnMut
trait, the core::ops::FnOnce
trait,
the core::marker::Send
trait, and the core::marker::Sync
trait.
4.7. Indirection Types¶
4.7.1. Function Pointer Types¶
Syntax
FunctionPointerTypeSpecification
::=ForGenericParameterList
?FunctionPointerTypeQualifierList
fn (FunctionPointerTypeParameterList
? )ReturnTypeWithoutBounds
?FunctionPointerTypeQualifierList
::= unsafe?AbiSpecification
?FunctionPointerTypeParameterList
::=FunctionPointerTypeParameter
(,FunctionPointerTypeParameter
)* (,VariadicPart
| ,?)VariadicPart
::=OuterAttributeOrDoc
* ...FunctionPointerTypeParameter
::=OuterAttributeOrDoc
* (IdentifierOrUnderscore
:)?TypeSpecification
Legality Rules
4.7.1:1 A function pointer type is an indirection type that refers to a function.
4.7.1:2
An unsafe function pointer type is a function pointer type subject to
keyword unsafe
.
4.7.1:3 A variadic part indicates the presence of C-like optional parameters.
4.7.1:4
A variadic part shall be specified only when the ABI of the
function pointer type is either extern "C"
or extern "cdecl"
.
4.7.1:5 The return type of a function pointer type is determined as follows:
4.7.1:6 If the function pointer type specifies a
ReturnTypeWithoutBounds
, then the return type is the specifiedReturnTypeWithoutBounds
.4.7.1:7 Otherwise the return type is the unit type.
Undefined Behavior
4.7.1:8
It is a validity invariant for a value of a function pointer type
to be not null
.
Examples
unsafe extern "C" fn (value: i32, ...) -> f64
4.7.2. Raw Pointer Types¶
Syntax
RawPointerTypeSpecification
::= * (const | mut)TypeSpecificationWithoutBounds
Legality Rules
4.7.2:1 A raw pointer type is an indirection type without validity guarantees.
4.7.2:2
A mutable raw pointer type is a raw pointer type subject to
keyword mut
.
4.7.2:3
An immutable raw pointer type is a raw pointer type subject to
keyword const
.
4.7.2:4 Comparing two values of raw pointer types compares the addresses of the values.
4.7.2:5 Comparing a value of a raw pointer type to a value of a dynamically sized type compares the data being pointed to.
Examples
*const i128
*mut bool
4.7.3. Reference Types¶
Syntax
ReferenceTypeSpecification
::= &LifetimeIndication
? mut?TypeSpecificationWithoutBounds
Legality Rules
4.7.3:1 A reference type is an indirection type with ownership.
4.7.3:2
A shared reference type is a reference type not subject to
keyword mut
.
4.7.3:3 A shared reference type prevents the direct mutation of a referenced value.
4.7.3:4
A shared reference type implements the core::marker::Copy
trait. Copying a shared reference performs a shallow copy.
4.7.3:5 Releasing a shared reference has no effect on the value it refers to.
4.7.3:6
A mutable reference type is a reference type subject to keyword
mut
.
4.7.3:7 A mutable reference type allows the direct mutation of a referenced value.
4.7.3:8
A mutable reference type does not implement the copy::marker::Copy
trait.
Undefined Behavior
4.7.3:9
It is validity invariant for a value of a reference type to be
not null
.
Examples
&i16
&'a mut f32
4.8. Trait Types¶
4.8.1. Impl Trait Types¶
Syntax
ImplTraitTypeSpecification
::= implTypeBoundList
ImplTraitTypeSpecificationOneBound
::= implTraitBound
Legality Rules
4.8.1:1 An impl trait type is a type that implements a trait, where the type is known at compile time.
4.8.1:2 An impl trait type shall appear only within a function parameter or the return type of a function.
4.8.1:3 An anonymous return type is an impl trait type ascribed to a function return type.
4.8.1:4 An anonymous return type behaves as if it contained all declared type parameters of the return type‘s function and its parent trait or implementation.
4.8.1:5 An anonymous return type derived from an async function behaves as if it contained all declared type parameters and lifetime parameters of the return type‘s function and its parent trait or implementation.
4.8.1:6 An impl trait type shall not contain opt-out trait bounds.
Examples
fn anonymous_type_parameter
(arg: impl Copy + Send + Sync) { ... }
fn anonymous_return_type () -> impl MyTrait { ... }
4.8.2. Trait Object Types¶
Syntax
TraitObjectTypeSpecification
::= dynTypeBoundList
TraitObjectTypeSpecificationOneBound
::= dynTraitBound
Legality Rules
4.8.2:1 A trait object type is a type that implements a trait, where the type is not known at compile time.
4.8.2:2 The principal trait of trait object type is the first trait bound.
4.8.2:3 The principal trait shall denote an object safe trait.
4.8.2:4 All non-principal trait trait bounds shall denote auto traits.
4.8.2:5 A trait object type shall not contain opt-out trait bounds.
4.8.2:6 A trait object type shall contain at most one lifetime bound.
4.8.2:7 A trait object type is a dynamically sized type. A trait object type permits late binding of methods. A method invoked via a trait object type involves dynamic dispatching.
Examples
dyn MyTrait
dyn MyTrait + Send
dyn MyTrait + 'static + Copy
4.9. Other Types¶
4.9.1. Inferred Types¶
Syntax
InferredType
::=
_
Legality Rules
4.9.1:1 An inferred type is a placeholder for a type deduced by type inference.
4.9.1:2 An inferred type shall not appear in the following positions:
4.9.1:3 Within the
InitializationType
of aTypeAliasDeclaration
,4.9.1:4 Within the
ReturnType
of aFunctionDeclaration
,4.9.1:5 Within the
TypeAscription
of aConstantDeclaration
, aConstantParameter
, aFunctionParameterPattern
, aRecordStructField
, aStaticDeclaration
, or aTypedSelf
,4.9.1:6 Within the
TypeSpecification
of aFunctionParameter
, anImplementingType
, aTupleStructField
, aTypeBoundPredicate
, or aTypeParameter
.
4.9.1:7 An inferred type forces a tool to deduce a type, if possible.
Examples
let values: Vec<_> = (0 .. 10).collect();
4.9.2. Type Parameters¶
Legality Rules
4.9.2:1 A type parameter type is a placeholder type of a type parameter to be substituted by generic substitution.
Examples
fn type_parameter<T>(parameter: T) {}
4.9.3. Never Type¶
Syntax
NeverType
::=
!
Legality Rules
4.9.3:1 The never type is a type that represents the result of a computation that never completes.
4.9.3:2 The never type has no values.
Undefined Behavior
4.9.3:3 It is validity invariant to not have a value of the never type.
Examples
let never_completes: ! = panic!();
4.9.4. Parenthesized Types¶
Syntax
ParenthesizedTypeSpecification
::= (TypeSpecification
)
Legality Rules
4.9.4:1 A parenthesized type is a type that disambiguates the interpretation of lexical elements.
Examples
&'a (dyn MyTrait + Send)
4.10. Type Aliases¶
Syntax
TypeAliasDeclaration
::= typeName
GenericParameterList
? (:TypeBoundList
)?WhereClause
? (=InitializationType
WhereClause
?)? ;InitializationType
::=TypeSpecification
Legality Rules
4.10:1 A type alias is an item that defines a name for a type.
4.10:2
A type alias shall not have a TypeBoundList
unless it is an
associated item.
4.10:3 The last where clause is rejected, but may still be consumed by macros.
Examples
type Point = (f64, f64);
4.11. Representation¶
4.11.1. Type Layout¶
Legality Rules
4.11.1:1 All values have an alignment and a size.
4.11.1:2
A dynamically sized type is a type that does not implement the core::marker::Sized
trait.
4.11.1:3 A fat pointer type is an indirection type whose contained type specification is a dynamically sized type.
4.11.1:4
The alignment of a value specifies which addresses are valid for
storing the value. Alignment is measured in bytes, is at least one,
and always a power of two. A value of alignment N
is stored at an
address that is a multiple of N
.
4.11.1:5
The size of a type is the offset in bytes between successive elements
in array type [T, N]
where T
is the type of the value,
including any padding for alignment. Size is a multiple of the
alignment.
4.11.1:6 The size of scalar types is as follows:
4.11.1:7 |
Type |
Size |
4.11.1:8 |
1 |
|
4.11.1:9 |
1 |
|
4.11.1:10 |
2 |
|
4.11.1:11 |
4 |
|
4.11.1:12 |
8 |
|
4.11.1:13 |
16 |
|
4.11.1:14 |
4 |
|
4.11.1:15 |
8 |
|
4.11.1:16 |
4 |
4.11.1:17
Types usize
and isize
have size big enough to contain every
address on the target platform.
4.11.1:18
For type str
, the layout is that of slice type
[u8]
.
4.11.1:19
For array type [T; N]
where T
is the element type and N
is size operand, the alignment is that of T
, and the size is
calculated as core::mem::size_of::<T>() * N
.
4.11.1:20 For a slice type, the layout is that of the array type it slices.
4.11.1:21 For a tuple type, the layout is tool-defined. For a unit tuple, the size is zero and the alignment is one.
4.11.1:22 For a closure type, the layout is tool-defined.
4.11.1:23
For a thin pointer, the size and alignment are those of type
usize
.
4.11.1:24 For a function pointer type, the size and alignment are those of a thin pointer.
4.11.1:25
For a fat pointer type, the size and alignment are tool-defined, but
are at least those of a thin pointer.
For a fat pointer type whose contained type is that of a slice or trait object type the size is that of two times the size of type usize
and the alignment is that of type usize
.
4.11.1:26 For a trait object type, the layout is the same as the value being coerced into the trait object type at runtime.
4.11.1:27
For a struct type, the memory layout is undefined, unless the
struct type is subject to attribute repr
.
4.11.1:28
For a union type, the memory layout is undefined, unless the
union type is subject to attribute repr
. All union fields
share a common storage.
4.11.1:29 The size of a recursive type shall be finite.
4.11.2. Type Representation¶
Legality Rules
4.11.2:1 Type representation specifies the layout of fields of abstract data types. Type representation changes the bit padding between fields of abstract data types as well as their order, but does not change the layout of the fields themselves.
4.11.2:2 Type representation is classified into:
4.11.2:3 C representation,
4.11.2:4 Default representation,
4.11.2:5 Primitive representation,
4.11.2:6 Transparent representation.
4.11.2:7 C representation lays out a type such that the type is interoperable with the C language.
4.11.2:8 Default representation makes no guarantees about the layout.
4.11.2:9 Primitive representation is the type representation of individual integer types. Primitive representation applies only to an enum type that is not a zero-variant enum type. It is possible to combine C representation and primitive representation.
4.11.2:10 Transparent representation applies only to an enum type with a single enum variant or a struct type where the struct type or enum variant has a single field of non-zero size and any number of fields of size zero and alignment one.
4.11.2:11 Types subject to transparent representation have the same type representation as the type of their field with non-zero size.
4.11.2:12
Type representation may be specified using attribute repr
. An
enum type, a struct type, or a union type that is not subject to
attribute repr
has default representation.
4.11.2:13
Type representation may be specified using attribute repr
and
modified further using attribute repr
‘s Alignment
representation modifiers. A representation modifier shall apply only
to a struct type or a union type subject to C representation or
default representation.
4.11.2.1. Enum Type Representation¶
Legality Rules
4.11.2.1:1 Zero-variant enum types shall not be subject to C representation.
4.11.2.1:2 The size and alignment of an enum type without fields subject to C representation, default representation, or primitive representation are those of its discriminant.
4.11.2.1:3 The discriminant type of an enum type with C representation is the corresponding c signed int type for the target platform’s C ABI.
4.11.2.1:4 The discriminant type of an enum type with default representation is tool-defined.
4.11.2.1:5 The discriminant type of an enum type with primitive representation is the integer type specified by the primitive representation.
4.11.2.1:6 It is a static error if the discriminant type cannot hold all the discriminant values of an enum type.
4.11.2.1:7 An enum type subject to transparent representation shall have a single enum variant with
4.11.2.1:10 An enum type subject to C representation or primitive representation has the same type representation as a union type with C representation that is laid out as follows:
4.11.2.1:11 Each enum variant corresponds to a struct whose struct type is subject to C representation and laid out as follows:
4.11.2.1:12 The type of the first field of the struct type is the discriminant type of the enum type.
4.11.2.1:13 The remaining fields of the struct type are the fields of the enum variant, in the same declarative order.
4.11.2.1:14 An enum type subject to transparent representation has the same type representation as the single field of non-zero size of its enum variant if one is present, otherwise the enum type has size zero and alignment one.
4.11.2.2. Struct Type Representation¶
Legality Rules
4.11.2.2:1 The alignment of a struct type subject to C representation is the alignment of the most-aligned field in it.
4.11.2.2:2 The size of a struct type subject to C representation is determined as follows:
4.11.2.2:3 Initialize a current offset to zero.
4.11.2.2:4 For each field of the struct type in declarative order:
4.11.2.2:6 If the current offset is not a multiple of the field's alignment, add byte padding to the current offset until it is a multiple of the alignment. The offset of the field is the current offset.
4.11.2.2:7 Increase the current offset by the size of the field.
4.11.2.2:8 Proceed with the next field.
4.11.2.2:9 Round up the current offset to the nearest multiple of the struct type's alignment.
4.11.2.2:10 The size of the struct type is the current offset.
4.11.2.2:11 A struct type subject to transparent representation shall have:
4.11.2.2:14 A struct type subject to transparent representation has the same type representation as the single field of non-zero size if one is present, otherwise the struct type has size zero and alignment one.
4.11.2.3. Union Type Representation¶
Legality Rules
4.11.2.3:1 The size of a union type subject to C representation is the maximum of the sizes of all its fields, rounded up to alignment of the union type.
4.11.2.3:2 The alignment of a union type subject to C representation is the maximum of the alignments of all of its fields.
4.12. Type Model¶
4.12.1. Recursive Types¶
Legality Rules
4.12.1:1 A recursive type is a type whose contained types refer back to the containing type, either directly or by referring to another type which refers back to the original recursive type.
4.12.1:2 A type that is not an abstract data type shall not be recursive.
Examples
enum List<T> {
Nil,
Cons(T, Box<List<T>>)
}
4.12.2. Type Unification¶
Legality Rules
4.12.2:1 Type unification is the process by which type inference propagates known types across the type inference root and assigns concrete types to type variables, as well as a general mechanism to check for compatibility between two types during method resolution.
4.12.2:2 A type is said to unify with another type when the domains, ranges, and structures of both types are compatible according to the rules detailed below.
4.12.2:3 Two types that unify are said to be unifiable types.
4.12.2:4
Type unification is a symmetric operation. If type A
unifies
with type B
, then B
also unifies with A
and such
type unification results in the same observable effects.
4.12.2:5 If one of the two types is a type variable, type unification proceeds as follows:
4.12.2:6 If either type is a global type variable, the global type variable is assigned the type of the other unification operand.
4.12.2:7 Otherwise, if either type is a diverging type variable, the diverging type variable is assigned the type of the other unification operand.
4.12.2:8 Otherwise, if one type
T
is an integer type variable, behavior depends on the other typeU
:4.12.2:9 If
U
is an integer type or an integer type variable, the integer type variableT
is assigned typeU
.4.12.2:10 Otherwise, type unification fails.
4.12.2:11 Otherwise, if one type
T
is a floating-point type variable, behavior depends on the other typeU
:4.12.2:12 If
U
is a floating-point type or an floating-point type variable, the floating-point type variableT
is assigned typeU
.4.12.2:13 Otherwise, type unification fails.
4.12.2:14 Otherwise, neither type is a type variable, and the rules below are in effect.
4.12.2:15 A scalar type is unifiable only with itself.
4.12.2:16 The never type is unifiable with any other type.
4.12.2:17 An array type is unifiable only with another array type when
4.12.2:18 The element types of both array types are unifiable, and
4.12.2:19 The sizes of both array types are the same.
4.12.2:20 A slice type is unifiable only with another slice type when the element types of both slice types are unifiable.
4.12.2:21
Type str
is unifiable only with itself.
4.12.2:22 A tuple type is unifiable only with another tuple type when:
4.12.2:23 The arity of both tuple types is the same, and
4.12.2:24 The types of the corresponding tuple fields are unifiable.
4.12.2:25 An abstract data type is unifiable only with another abstract data type when:
4.12.2:26 The two abstract data types are the same type, and
4.12.2:27 The corresponding generic substitutions are unifiable.
4.12.2:28 A closure type is unifiable only with another closure type when:
4.12.2:29 The two closure types are the same closure, and
4.12.2:30 The corresponding generic substitutions are unifiable.
4.12.2:31 A function item type is unifiable only with another function item type when:
4.12.2:32 The two function item types are the same function, and
4.12.2:33 The corresponding generic substitutions are unifiable.
4.12.2:34 A function pointer type is unifiable only with another function pointer type when:
4.12.2:36 The unsafety is the same, and
4.12.2:37 The ABI is the same, and
4.12.2:38 The number of function parameters is the same, and
4.12.2:39 The types of the corresponding function parameters are unifiable, and
4.12.2:40 The presence of a variadic part is the same, and
4.12.2:41 The return types are unifiable.
4.12.2:42 A raw pointer type is unifiable only with another raw pointer type when:
4.12.2:43 The mutability is the same, and
4.12.2:44 The target types are unifiable.
4.12.2:45 A reference type is unifiable only with another reference type when:
4.12.2:46 The mutability is the same, and
4.12.2:47 The target types are unifiable.
4.12.2:48 An anonymous return type is unifiable with another type when:
4.12.2:50 The other type implements all traits specified by the anonymous return type.
4.12.2:51 An impl trait type is unifiable only with itself.
4.12.2:52 A trait object type is unifiable only with another trait object type when:
4.12.2:55 A type alias is unifiable with another type when the aliased type is unifiable with the other type.
4.12.3. Type Coercion¶
Legality Rules
4.12.3:1 Type coercion is an implicit operation that changes the type of a value. Any implicit conversion allowed by type coercion can be made explicit using a type cast expression.
4.12.3:2 A type coercion takes place at a coercion site or within a coercion-propagating expression.
4.12.3:3 The following constructs constitute a coercion site:
4.12.3:4 The argument operands of a call expression or a method call expression.
4.12.3:5 A constant declaration.
4.12.3:6 A field of an abstract data type.
4.12.3:7 A function result.
4.12.3:8 A let statement with an explicit type specification.
4.12.3:9 A static declaration.
4.12.3:10 The following expressions constitute a coercion-propagating expression:
4.12.3:11 Each operand of an array expression.
4.12.3:12 The tail expression of a block expression.
4.12.3:13 The operand of a parenthesized expression.
4.12.3:14 Each operand of a tuple expression.
4.12.3:15 Type coercion from a source type to a target type is allowed to occur when:
4.12.3:17 The source type
T
coerces to intermediate typeW
, and intermediate typeW
coerces to target typeU
.4.12.3:18 The source type is
&T
and the target type is*const T
.4.12.3:19 The source type is
&T
and the target type is&U
, whereT
implements thecore::ops::Deref<Target = U>
trait.4.12.3:20 The source type is
&mut T
and the target type is&T
.4.12.3:21 The source type is
&mut T
and the target type is*mut T
.4.12.3:22 The source type is
&mut T
and the target type is&U
, whereT
implements thecore::ops::Deref<Target = U>
trait.4.12.3:23 The source type is
&mut T
and the target type is&mut U
, whereT
implements thecore::ops::DerefMut<Target = U>
trait.4.12.3:24 The source type is
*mut T
and the target type is*const T
.4.12.3:25 The source type is
type_constructor(T)
and the target type istype_constructor(U)
, wheretype_constructor
is one of&W
,&mut W
,*const W
, or*mut W
, andU
can be obtained fromT
using unsized coercion.4.12.3:26 The source type is a function item type, the target type is a function pointer type and the source’s function signature is a subtype of the target’s function signature.
4.12.3:27 The source type is a non-capturing closure type, the target type is a function pointer type and the source’s function signature is a subtype of the target’s function signature.
4.12.3:28 The source type is the never type and the target type is any type.
4.12.3:29 The source type is a trait object type and the target type is a trait object type with the same trait bounds and additional auto traits.
4.12.3:30 An unsized coercion is a type coercion that converts a sized type into an unsized type. Unsized coercion from a source type to a target type is allowed to occur when:
4.12.3:31 The source type is array type
[T; N]
and the target type is slice type[T]
.4.12.3:32 The source type is
T
and the target type isdyn U
, whereT
implementsU + core::marker::Sized
, andU
is object safe.4.12.3:33 The source type is
S<..., T, ...> {
...
last_field: X
}
4.12.3:34 where
4.12.3:35
S
is a struct type,4.12.3:36
T
implementscore::marker::Unsize<U>
,4.12.3:37
last_field
is a struct field ofS
,4.12.3:38 The type of
last_field
involvesT
and if the type oflast_field
isW<T>
, thenW<T>
implementscore::marker::Unsize<W<U>>
,4.12.3:39
T
is not part of any other struct field ofS
.
4.12.3:40
and the target type
is S<..., U, ...>
.
4.12.3:41 Least upper bound coercion is a multi-type coercion that is used in the following scenarios:
4.12.3:42 To find the common type of multiple if expression branches.
4.12.3:43 To find the common type of multiple if let expression branches.
4.12.3:44 To find the common type for multiple match expression match arms.
4.12.3:45 To find the common type of array expression operands.
4.12.3:46 To find the return type of a closure expression with multiple return expressions.
4.12.3:47 To find the return type of a function with multiple return expressions.
4.12.3:48
Least upper bound coercion considers a set of source types T1
,
T2
, ...
, TN
and target type U
. The target type is
obtained as follows:
4.12.3:50 For each current source type
TC
in the inclusive rangeT1
toTN
4.12.3:51 If
TC
can be coerced toU
, then continue with the next source type.4.12.3:52 Otherwise, if
U
can be coerced toTC
, makeTC
the target typeU
.4.12.3:53 Otherwise, if
TC
andU
are non-capturing closure types, function item types, function pointer types, or a combination of those types, and a function pointer type exists that bothTC
andU
can coerce to, make that function pointer type be target typeU
.4.12.3:54 Otherwise, no coercion is performed.
4.12.3:55 Continue with the next source type.
4.12.4. Structural Equality¶
Legality Rules
4.12.4:1 A type is structurally equal when its values can be compared for equality by structure.
4.12.4:2 The following types are structurally equal:
4.12.4:3
Bool
,char
, function pointer types, integer types,str
, and raw pointer types.4.12.4:4 An abstract data type, if it implements the
core::cmp::Eq
andcore::cmp::PartialEq
traits using derive macroscore::cmp::Eq
andcore::cmp::PartialEq
.4.12.4:5 Array types and slice types, if the element type is structurally equal.
4.12.4:6 Reference types, if their inner type is structurally equal.
4.12.4:7 Tuple types, if the types of the tuple fields are structurally equal.
4.12.5. Interior Mutability¶
Legality Rules
4.12.5:1 Interior mutability is a property of types whose values can be modified through immutable references.
4.12.5:2
A type is subject to interior mutability when it contains a
core::cell::UnsafeCell
.
4.12.6. Type Inference¶
Legality Rules
4.12.6:1 Type inference is the process of automatically determining the type of expressions and patterns within a type inference root.
4.12.6:2 A type inference root is an expression whose inner expressions and patterns are subject to type inference independently of those found in other type inference roots.
4.12.6:3 The following expressions are considered type inference roots:
4.12.6:4 A constant argument.
4.12.6:5 The expression of a constant initializer.
4.12.6:6 The expression of a static initializer.
4.12.6:7 The expression of a discriminant initializer.
4.12.6:8 The expression of a constant parameter initializer.
4.12.6:9 The expression of a constant argument.
4.12.6:10 A function body.
4.12.6:11 The size operand of an array expression or an array type.
4.12.6:12 A type inference root imposes an expected type on its expression depending on the type inference root as follows:
4.12.6:13 The expected type of a constant argument is the type ascription of the constant parameter.
4.12.6:14 The expected type of the expression of a constant initializer is the type specified by the type ascription of the related constant.
4.12.6:15 The expected type of the expression of a static initializer is the type specified by the type ascription of the related static.
4.12.6:16 The expected type of the expression of a discriminant initializer is determined as follows:
4.12.6:17 If the enum type that contains the discriminant is subject to attribute
repr
that specifies a primitive representation, the expected type is the specified integer type.4.12.6:18 Otherwise, the expected type is
isize
.
4.12.6:19 The expected type of a function body is the return type of the function.
4.12.6:20 The expected type of a size operand of an array expression or an array type is
usize
.
4.12.6:21 A type variable is a placeholder used during type inference to stand in for an undetermined type of an expression or a pattern.
4.12.6:22 A global type variable is a type variable that can refer to any type.
4.12.6:23 An integer type variable is a type variable that can refer only to integer types.
4.12.6:24 A floating-point type variable is a type variable that can refer only to floating-point types.
4.12.6:25 A diverging type variable is a type variable that can refer to any type and originates from a diverging expression.
4.12.6:26 A lifetime variable is a placeholder used during type inference to stand in for an undetermined lifetime of a type.
4.12.6:27 The type inference algorithm uses type unification to propagate known types of expressions and patterns across the type inference root being inferred. In the rules detailed below, a static error occurs when type unification fails.
4.12.6:28 Performing type inference may introduce a requirement that some type must implement a trait, or that a type or lifetime must outlive some other lifetime. Such requirements are referred to as obligations and are detailed in the inference rules below.
4.12.6:29 If insufficient type information is available at the time an obligation is introduced, it may be deferred to be resolved later. Any time new type information is derived during type inference, the tool attempts to resolve all outstanding obligations and propagate any resulting type information via type unification.
4.12.6:30
When an associated type <Type as Trait>::Assoc
is referenced within a
type inference root (either explicitly within the source code, or via the
inferece rules below), an obligation requiring that Type
implements
Trait
is introduced.
4.12.6:31 Type inference for a type inference root proceeds as follows:
4.12.6:32 Recursively process all expressions and statements in the type inference root in program order.
4.12.6:33 For each statement, apply the statement inference rules outlined below.
4.12.6:34 For each expression, apply the expression inference rules outlined below.
4.12.6:35 If there are any remaining integer type variables that have not been unified with a concrete integer type, perform integer type fallback by unifying them with
i32
.4.12.6:36 If there are any remaining floating-point type variables that have not been unified with a concrete floating-point type, perform floating-point type fallback by unifying them with
f64
.4.12.6:37 If there are any remaining diverging type variables that have not been unified with a concrete type, unify them with the unit type.
4.12.6:38 If there are any remaining global type variables that have not been unified with a concrete type, raise a static error.
4.12.6:39 If there are any remaining obligations that do not hold or cannot be resolved with the available type information, raise a static error.
4.12.6:40 The type inference rules for statements are as follows:
4.12.6:41 Item statements are not subject to type inference.
4.12.6:42 Expression statements apply the expression inference rules outlined below to the related expression, with the expected type set to the unit type if the expression statement lacks the character 0x3B (semicolon), unset otherwise.
4.12.6:43 Let statements are inferred as follows:
4.12.6:44 If the let statement has a type ascription, unify that type with the type of the pattern.
4.12.6:45 If the let statement has a let initializer, apply the expression inference rules outlined below to the contained expression, with the expected type set to the type of the pattern.
4.12.6:46 If the let statement has a let initializer with a block expression, apply the expression inference rules outlined below to the contained block expression, with the expected type set to the never type.
4.12.6:47 Type inference of expressions may incorporate an expected type, derived from the context the expression appears in. If the expression is a coercion site or a coercion-propagating expression, the type derived via type inference may be coerced to the expected type. If no type coercion to the expected type is possible, or the expression is not a coercion site or a coercion-propagating expression, the inferred expression type is unified with the expected type.
4.12.6:48 The type inference rules for expressions are as follows:
4.12.6:49 An if expression is inferred by inferring its subject expression with an expected type of
bool
, then inferring its block expression with the expected type of the if expression. Then, if the if expression has an else expression, apply the inference rules below to it.4.12.6:50 An if let expression is inferred by inferring its subject let expression with the expected type set to the type of its pattern, then inferring its block expression with the expected type of the if-let expression. If the if let expression has an else expression, apply the inference rules below to it.
4.12.6:51 An else expression that is part of an if expression or if let expression is inferred as follows:
4.12.6:52 If the else expression has a block expression, infer the block expression with the expected type of the if expression or if let expression.
4.12.6:53 If the else expression has an if expression, infer that nested if expression with the expected type of the original if expression, then unify its type with the type of the original if expression or if let expression.
4.12.6:54 Otherwise, the else expression has an if let expression. Infer that nested if let expression with the expected type of the original if expression, then unify its type with the type of the original if expression or if let expression.
4.12.6:55 A match expression is inferred as follows:
4.12.6:56 Unify the types of the patterns of every match arm, then infer the subject expression with the expected type set to the type of the patterns.
4.12.6:57 Infer the operands of all match arm guards with expected type
bool
.4.12.6:58 Infer the match arm body of every match arm with the expected type of the match expression.
4.12.6:59 A for loop expression is inferred by unifying the type of its pattern with the type
<T as core::iter::IntoIterator>::Item
, whereT
is the type of the subject expression, and then inferring its loop body.4.12.6:60 A while let loop expression is inferred by unifying the type of its subject let expression with the type of its pattern, and then inferring its loop body.
4.12.6:61 An array expression using an array element constructor is inferred by attempting a least upper bound coercion from each element type to the expected type. If no such type coercion is possible, all element types are unified instead.
4.12.6:62 A negation expression is inferred as follows:
4.12.6:63 Determine the trait corresponding to the operator according to the following table:
4.12.6:64
Operator
Trait
4.12.6:65
!
4.12.6:66
-
4.12.6:67 Infer the type of the expression to be the associated type
<T as Trait>::Output
, whereT
is the type of the operand, andTrait
is the operator trait determined from the table above.
4.12.6:68 A bit expression or arithmetic expression is inferred as follows:
4.12.6:69 Determine the trait corresponding to the operator according to the following table:
4.12.6:70
Operator
Trait
4.12.6:71
+
4.12.6:72
-
4.12.6:73
*
4.12.6:74
/
4.12.6:75
%
4.12.6:76
&
4.12.6:77
|
4.12.6:78
^
4.12.6:79
<<
4.12.6:80
>>
4.12.6:81 If the expression is a shift left expression or a shift right expression, and the expected type is an integer type, unify the type of the left operand with the expected type.
4.12.6:82 If the expression is neither a shift left expression nor a shift right expression, and the expected type is a numeric type, unify the types of both operands with the expected type.
4.12.6:83 Infer the type of the expression to be the associated type
<L as Trait<R>>::Output
, whereL
is the type of the left operand,Trait
is the operator trait determined from the table above, andR
is the type of the right operand.
4.12.6:84 A compound assignment expression is inferred as follows:
4.12.6:85 Determine the trait corresponding to the operator according to the following table:
4.12.6:86
Operator
Trait
4.12.6:87
+=
4.12.6:88
-=
4.12.6:89
*=
4.12.6:90
/=
4.12.6:91
%=
4.12.6:92
&=
4.12.6:93
|=
4.12.6:94
^=
4.12.6:95
<<=
4.12.6:96
>>=
4.12.6:97 Introduce an obligation
L: $Trait<R>
, whereL
is the type of the assigned operand,Trait
is the operator trait determined from the table above, andR
is the type of the modifying operand.4.12.6:98 The type of the expression is the unit type.
4.12.6:99 A comparison expression is inferred by introducing an obligation
L: PartialEq<R>
, whereL
is the type of the left operand, andR
is the type of the right operand. The type of the expression isbool
.4.12.6:100 An assignment expression is inferred by unifying the type of its assignee operand with the type of its value operand.
4.12.6:101 A closure expression is inferred by deducing its signature from the surrounding context, unifying the deduced closure parameter types and return type with the user-written closure parameter patterns and type ascriptions and return type, and then inferring the closure body with the expected type set to the closure’s return type. The closure signature is deduced as follows:
4.12.6:102 If the expected type is a function pointer type, the closure signature is the signature of that function pointer type.
4.12.6:103 Otherwise, if there is a pending obligation requiring that the expected type implements
core::ops::FnOnce
or a trait that hascore::ops::FnOnce
as one of its supertraits, derive the closure signature from the parameters and return type of thecore::ops::FnOnce
bound or supertrait.4.12.6:104 Otherwise, the closure signature remains undeduced. No outside type information is provided and the parameter types and return type are subject to regular type inference.
4.12.6:105 Other expressions are inferred by applying the typing rules specified in the section for that expression.
4.12.6:106 If an expression is a diverging expression, its type is a new diverging type variable.
4.13. Traits¶
Syntax
TraitDeclaration
::= unsafe? traitName
GenericParameterList
? (:SupertraitList
?)?WhereClause
?TraitBody
SupertraitList
::=TypeBoundList
TraitBody
::= {InnerAttributeOrDoc
*AssociatedItem
* }
Legality Rules
4.13:1 A trait is an item that describes an interface a type can implement.
4.13:2 A trait body is a construct that encapsulates the associated items, inner attributes, and inner doc comments of a trait.
4.13:3
Within a trait, the type Self
acts as a placeholder for a
type implementing the trait, and behaves like a type parameter.
4.13:4 A local trait is a trait that is defined in the current crate.
B.384:1 A subtrait is a trait with a supertrait.
4.13:6 A supertrait is a transitive trait that a type must additionally implement.
4.13:7 A subtrait shall not be its own supertrait.
4.13:8 A trait of the form
trait T: Bound {}
4.13:9 is equivalent to a where clause of the following form:
trait T where Self: Bound {}
4.13:10 An auto trait is a trait that is implicitly and automatically implemented by a type when the types of its constituent fields implement the trait.
4.13:11 A type that has no fields implements all auto traits.
4.13:12
If determining whether a type T
implements an auto trait
would recursively depend on whether T
implements said auto trait, this
requirement is ignored and assumed to hold.
4.13:13 The following traits are auto traits:
4.13:14
core::marker::Send
4.13:15
core::marker::Sync
4.13:16
core::marker::Unpin
4.13:17
core::panic::UnwindSafe
4.13:18
core::panic::RefUnwindSafe
4.13:19 No other traits are auto traits.
Examples
trait Sequence<T> {
fn length(&self) -> u32;
fn element_at(&self, position: u32) -> T;
}
4.13:20 Shape is a supertrait of Circle.
trait Shape {
fn area(&self) -> f64;
}
4.13:21 Circle is a subtrait of Shape.
trait Circle: Shape {
fn radius(&self) -> f64;
}
4.13.1. Object Safety¶
Legality Rules
4.13.1:1 A trait is object safe when:
4.13.1:2 Its supertraits are object safe, and
4.13.1:3
core::marker::Sized
is not a supertrait, and4.13.1:4 It lacks associated constants, and
4.13.1:5 Its associated functions are object safe, and
4.13.1:6 Its associated type aliases specify a
core::marker::Sized
trait bound forSelf
in a type bound predicate.
4.13.1:7 An associated function is object safe when it is either an object safe dispatchable function or an object safe non-dispatchable function.
4.13.1:8 A dispatchable function is object safe when:
4.13.1:9 It lacks generic parameters, and
4.13.1:10 Is a method that does not use
Self
in its function signature except in the type of its self parameter or as the type of a type bound predicate, and4.13.1:11 It lacks type bound predicates with
Self
as the predicate’s type and traits as the predicate’s trait bounds other thancore::marker::Send
,core::marker::Sync
andcore::marker::Unpin
4.13.1:12
A function is object safe when it specifies a
core::marker::Sized
trait bound for Self
in a
type bound predicate.
4.14. Trait and Lifetime Bounds¶
Syntax
TypeBoundList
::=TypeBound
(+TypeBound
)* +?TypeBound
::=LifetimeIndication
|ParenthesizedTraitBound
|TraitBound
LifetimeIndication
::=Lifetime
| '_ | 'staticLifetimeIndicationList
::=LifetimeIndication
(+LifetimeIndication
)* +?ParenthesizedTraitBound
::= (TraitBound
)TraitBound
::= ??ForGenericParameterList
?TypePath
ForGenericParameterList
::= forGenericParameterList
Legality Rules
4.14:1 A bound imposes a constraint on a generic parameter by limiting the set of possible generic substitutions.
4.14:2 A bound does not impose a constraint on a generic parameter of a type alias unless it is an associated item.
4.14:3 A lifetime bound is a bound that imposes a constraint on the lifetimes of generic parameters.
4.14:4 A trait bound is a bound that imposes a constraint on the traits of generic parameters.
4.14:5
A ForGenericParameterList
shall not specify ConstantParameters
or
TypeParameters
.
4.14:6
A higher-ranked trait bound is a bound that specifies an infinite
list of bounds for all possible lifetimes specified by the
ForGenericParameterList
.
4.14:7
An opt-out trait bound is a trait bound with Punctuation
?
that nullifies an implicitly added trait bound.
4.14:8 An outlives bound is a trait bound which requires that a lifetime parameter or type outlives a lifetime parameter.
4.14:9
Outlives bound 'a: 'b
indicates that 'a
outlives 'b
.
4.14:10
Outlives bound T: 'a
indicates that all lifetime parameters of
T
outlive 'a
.
4.14:11 An implied bound is a bound that is not expressed in syntax, but is is the byproduct of relations between lifetime parameters and function parameters, between lifetime parameters and a return type, and between lifetime parameters and fields.
4.14:12
A reference of the form &'a T
, where 'a
is a
lifetime parameter and T
is a type, yields implied bound
T: 'a
.
4.14:13 If an outlives bound applies to the type of a field, then this bound also applies to the related abstract data type as an implied bound.
4.14:14 If an outlives bound applies to the type of a function parameter or to a return type, then this bound also applies to the related function as an implied bound.
Examples
fn draw<T: Shape>(shape: T) { ... }
4.14.1. Lifetimes¶
Syntax
Lifetime
::= 'NonKeywordIdentifier
AttributedLifetime
::=OuterAttributeOrDoc
*Lifetime
AttributedLifetimeList
::=AttributedLifetime
(,AttributedLifetime
)* ,?
Legality Rules
4.14.1:1 A lifetime specifies the expected longevity of a value.
4.14.1:2 A lifetime bound shall apply to types and other lifetimes.
Examples
&'a i32
&'static Shape
4.14.1:3 See Paragraph 4.12. for the declaration of Shape.
4.14.2. Subtyping and Variance¶
Legality Rules
4.14.2:1 Subtyping is a property of types, allowing one type to be used where another type is expected.
4.14.2:2 Variance is a property of lifetime parameters and type parameters that describes the circumstances under which a generic type is a subtype of an instantiation of itself with different generic arguments.
4.14.2:3 A type is its own subtype.
4.14.2:4
F<T>
is said to be
4.14.2:5 Covariant over
T
, whenT
being a subtype ofU
implies thatF<T>
is a subtype ofF<U>
, or4.14.2:6 Contravariant over
T
, whenT
being a subtype ofU
implies thatF<U>
is a subtype ofF<T>
, or4.14.2:7 Invariant over
T
.
4.14.2:8 Variance is determined as follows:
4.14.2:9 |
Type |
Variance in ‘a |
Variance in T |
4.14.2:10 |
|
||
4.14.2:11 |
|
||
4.14.2:12 |
|
||
4.14.2:13 |
|
||
4.14.2:14 |
|
||
4.14.2:15 |
|
||
4.14.2:16 |
|
||
4.14.2:17 |
|
||
4.14.2:18 |
|
||
4.14.2:19 |
|
||
4.14.2:20 |
|
||
4.14.2:21 |
|
4.14.2:22
A trait is invariant in all inputs, including the Self
parameter.
4.14.2:23 Lifetime parameters and type parameters are subject to variance.
4.14.2:24 The variance of a generic parameter of an abstract data type or a tuple type is determined as follows:
4.14.2:25 For each generic parameter
G
:4.14.2:26 Initialize variance
V
of the generic parameter toany
.4.14.2:27 For each field of the abstract data type or the tuple type:
4.14.2:31 It is a static error if variance
V
isany
.
4.14.2:32 Expressions and statements may impose subtyping requirements on their subexpressions. Such requirements are applied after type inference, on the inferred types of the respective expressions and patterns.
4.14.2:33 It is a static error if any subtyping requirements are not met.
4.14.2:34 The subtyping requirements for statements are as follows:
4.14.2:35 Item statements impose no additional subtyping requirements.
4.14.2:36 Let statements require that the type of the expression of the let initializer (if any) is a subtype of the type of the let statement‘s pattern.
4.14.2:37 Expression statements impose the subtyping requirements for the contained expression, as outlined below.
4.14.2:38 The subtyping requirements for expressions are as follows:
4.14.2:39 The requirements for any arithmetic expression, bit expression, comparison expression, compound assignment expression, index expression, or negation expression are the same requirements as for an explicit invocation of the corresponding operator trait method.
4.14.2:40 An assignment expression requires that the type of its value operand is a subtype of the type of its assignee operand.
4.14.2:41 A type cast expression requires that the type of its operand is a subtype of its target type.
4.14.2:42 A call expression or method call expression requires that the types of its argument operands are subtypes of the types of the corresponding parameter.
4.14.2:43 A return expression requires that the type of its operand is a subtype of the return type of the containing function or closure expression.
4.14.2:44 A break expression requires that its break type is a subtype of the type of the block expression or loop expression that the break expression breaks out of.
4.14.2:45 Other expressions do not impose any additional subtyping requirements.
4.14.2:46 Any type coercion resulting in a method invocation imposes the same subtyping requirements as an explicit invocation of that method would.
4.14.3. Lifetime Elision¶
Legality Rules
4.14.3:1 Lifetime elision is a set of rules that automatically insert lifetime parameters and/or lifetime arguments when they are elided in the source code.
4.14.3:2 A lifetime may be elided either implicitly or explicitly.
4.14.3:3
A lifetime is elided explicitly if it is the '_
lifetime.
4.14.3:4 A lifetime is elided implicitly if it is absent.
4.14.3:5 Lifetime elision rules are introduced by certain constructs and may be nested.
4.14.3:6 An elided lifetime is subject to the set of lifetime elision rules introduced by the innermost construct containing the elided lifetime.
4.14.3:7 It is a static error to elide a lifetime in a position where no lifetime elision rules are active.
4.14.3:8 Lifetimes cannot be implicitly elided within impl trait types. If no lifetime bound is present, the impl trait type is not considered to be bound by any lifetime.
4.14.3.1. Function Lifetime Elision¶
Legality Rules
4.14.3.1:1
Function lifetime elision is a form of lifetime elision that applies
to functions, function pointer type parameters, and paths
that resolve to one of the core::ops::Fn
, core::ops::FnMut
, and
core::ops::FnOnce
traits.
4.14.3.1:2 An input lifetime is one of the following lifetimes:
4.14.3.1:3 Any lifetime related to a function parameter.
4.14.3.1:4 Any lifetime related to a function pointer type parameter.
4.14.3.1:5 Any lifetime related to the function parameters of the
core::ops::Fn
,core::ops::FnMut
, andcore::ops::FnOnce
traits.
4.14.3.1:6
A self input lifetime is an input lifetime of a self parameter
that is a lifetime of a reference type whose referent is Self
.
4.14.3.1:7 Any lifetime related to an implementing type and an implemented trait of an implementation.
4.14.3.1:8 An output lifetime is one of the following lifetimes:
4.14.3.1:9 Any lifetime related to the return type of a function.
4.14.3.1:10 Any lifetime related to the return type of a function pointer type.
4.14.3.1:11 Any lifetime related to the return types of the
core::ops::Fn
,core::ops::FnMut
, andcore::ops::FnOnce
traits.
4.14.3.1:12 Lifetime elision proceeds as follows:
4.14.3.1:13 Each elided input lifetime is a distinct lifetime parameter in its related construct.
4.14.3.1:14 If a construct has exactly one input lifetime, then that lifetime is assigned to all elided output lifetimes.
4.14.3.1:15 If a function has a self parameter with exactly 1 self input lifetime, then the lifetime of the self input lifetime is assigned to all elided output lifetimes.
4.14.3.1:16 Otherwise this is a static error.
Examples
4.14.3.1:17
Given function f
of the form
fn f <'a, 'b, T: ToCStr>(&'a mut self, args: &'b [T]) -> &'a mut Command;
4.14.3.1:18 its lifetime elided form is
fn f <T: ToCStr>(&mut self, args: &[T]) -> &mut Command;
4.14.3.2. Static Lifetime Elision¶
Legality Rules
4.14.3.2:1 Static lifetime elision is a form of lifetime elision that applies to the type ascription of constants and statics.
4.14.3.2:2
An elided lifetime of a reference type or path in the
type specification of a constant or static is inferred to be the
'static'
lifetime.
4.14.3.2:3 The lifetime of an associated implementation constant shall not be elided.
4.14.3.2:4 The lifetime of an associated trait constant shall not be elided.
Examples
4.14.3.2:5
Given static S
of the form
static S: &[&usize] = &[];
4.14.3.2:6 its lifetime elided form is
static S: &'static [&'static usize] = &[];
4.14.3.3. Trait Object Lifetime Elision¶
Legality Rules
4.14.3.3:1 Trait object lifetime elision is a form of lifetime elision that applies to trait object types.
4.14.3.3:2 An elided lifetime of a trait object type is inferred as follows:
4.14.3.3:3 If the trait object type is used as the type specification of a reference type, then the lifetime of the reference type is the elided lifetime,
4.14.3.3:4 If the trait object type is used as a generic argument and
4.14.3.3:5 if the corresponding generic parameter has exactly one lifetime bound, then the lifetime of that bound is the elided lifetime,
4.14.3.3:6 Otherwise it is a static error to infer the lifetime bound.
4.14.3.3:7 If the trait of the trait object type has exactly one lifetime bound specified, then the lifetime of that bound is the inferred lifetime,
4.14.3.3:8 If the trait of the trait object type has no lifetime bounds specified, then the elided lifetime is the
'static
lifetime unless it is elided in expressions where it is instead inferred,4.14.3.3:9 Otherwise it is a static error to infer the lifetime bound.
Examples
4.14.3.3:10
Given type alias T
of the form
type T<'a> = &'a dyn Trait;
4.14.3.3:11 its lifetime elided form is
type T<'a> = &'a (dyn Trait + 'a);
4.14.3.4. Impl Header Lifetime Elision¶
Legality Rules
4.14.3.4:1 Impl header lifetime elision is a form of lifetime elision that applies to the implementing type and implemented trait (if any) of an implementation.
4.14.3.4:2 The impl header lifetime elision rules are as follows:
4.14.3.4:3 Every explicitly elided lifetime is replaced with a new lifetime parameter defined on the implementation.
4.14.3.4:4 An implicitly elided lifetime of a reference is also replaced with a new lifetime parameter defined on the implementation.
4.14.3.4:5 An implicitly elided lifetime in any other type is a static error.
Examples
4.14.3.4:6 Given an implementation of the form
impl Trait<&u8, Strukt<'_>> for &i32 {}
4.14.3.4:7 its lifetime elided form is
impl<'a, 'b, 'c> Trait<&'a u8, Strukt<'b>> for &'c i32 {}
4.14.3.4:8
where 'a
, 'b
, and 'c
are anonymous lifetime parameters that
cannot be named by user-written code.