La première conversion utilisant 'en tant que' compile, mais la seconde utilisant le caractère 'De' ne le fait pas:
fn main() {
let a: u64 = 5;
let b = a as usize;
let b = usize::from(a);
}
En utilisant Rust 1.22.1, j'obtiens l'erreur suivante:
error[E0277]: the trait bound `usize: std::convert::From<u64>` is not satisfied
--> src/main.rs:4:13
|
4 | let b = usize::from(a);
| ^^^^^^^^^^^ the trait `std::convert::From<u64>` is not implemented for `usize`
|
= help: the following implementations were found:
<usize as std::convert::From<u8>>
= note: required by `std::convert::From::from`
Quand je remplace u64
par u8
, il n'y a plus d'erreur. D'après le message d'erreur, je comprends que le trait From
est implémenté uniquement pour u8
, mais pas pour les autres types d'entiers.
S'il y a une bonne raison à cela, alors pourquoi la conversion utilisant 'as' ne devrait-elle pas échouer non plus?
Les conversions as
sont fondamentalement différentes des conversions From
. Les conversions From
sont "simpleet safe" alors que les conversions as
sont purement "safe". Lorsqu’on considère les types numériques, les conversions From
n’existent que lorsque la sortie est garantie comme le identique _, c’est-à-dire qu’il n’ya aucune perte d’informations (pas de troncature ni de flou, ni de précision). as
castes, cependant, n'ont pas cette limitation.
Citant les docs,
La taille de [
usize
] est "le nombre d'octets nécessaires pour référencer un emplacement en mémoire. Par exemple, sur une cible 32 bits, il s'agit de 4 octets et sur une cible 64 bits, de 8 octets".
Étant donné que la taille dépend de l'architecture cible et ne peut pas être déterminée avant la compilation, rien ne garantit qu'une conversion From
entre un type numérique et usize
est possible. Cependant, une distribution as
fonctionnera toujours selon les règles listées ici .
Par exemple, sur un système 32 bits, usize
est équivalent à u32
. Etant donné qu'une usize
est inférieure à un u64
, il peut y avoir une perte d'informations (troncature) lors de la conversion d'un u64
en un usize
et par conséquent, une conversion From
ne peut pas exister. Cependant, il est toujours garanti que la taille de usize
sera d'au moins 8 bits et qu'une conversion de u8
à usize
From
existera toujours.
Comme déjà mentionné, la conversion d'une valeur de 64 bits en une usize
peut provoquer une troncature; vous risquez de perdre des données si une usize
est de 16 ou 32 bits.
Les conversions susceptibles d’être mises en échec sont couvertes par le trait instable TryFrom
:
#![feature(try_from)]
use std::convert::TryFrom;
fn main() {
let a: u64 = 5;
let b = a as usize;
let b = usize::try_from(a);
}
Voir également: