Не столь тривиальные приведения типов
От Nikita Bishonen • 1 minute read •
Не столь тривиальные приведения типов
В Rust существует интересный lint под названием trivial_casts, который оказывается не таким уж тривиальным.
It may be possible that this will become a warning in the future
поэтому давайте рассмотрим несколько примеров кода, где я буду сравнивать:
- Тривиальные приведения типов
- Определения типов переменных
- Неявное приведение типа
Я не буду добавлять никаких комментариев, кроме вывода компилятора, чтобы вы могли увидеть разницу самостоятельно и решить, когда и как использовать приведение типов в коде Rust. Я только скажу, что trivial_cast_supertype_with_shadowing похоже является хорошим примером того, как trivial_casts могут стать не столь тривиальными даже в небольшом примере (представьте, что может произойти в более длинной цепочке вызовов и преобразований/приведений типов).
#![allow(dead_code)]
#![warn(trivial_casts)]
trait Polygon {}
trait TwoSidedPolygon: Polygon {}
struct Square([u32; 8]);
impl Polygon for Square {}
impl TwoSidedPolygon for Square {}
struct Triangle([u32; 6]);
impl Polygon for Triangle {}
#[cfg(test)]
mod tests {
use crate::{Polygon, Square, Triangle, TwoSidedPolygon};
#[test]
fn explicit_definition_supertype() {
let square = Square([2; 8]);
let square: &dyn Polygon = □
process(square);
// process2(square); the size for values of type `dyn Polygon` cannot be known at compilation time
// process3(square); the trait bound `dyn Polygon: TwoSidedPolygon` is not satisfied
// process_square(square); expected &Square, found &(dyn Polygon + 'static)
}
#[test]
fn explicit_definition_subtype() {
let square = Square([2; 8]);
let square: &dyn TwoSidedPolygon = □
process(square);
// process2(square); the size for values of type `dyn Polygon` cannot be known at compilation time
process3(square);
// process_square(square); expected &Square, found &(dyn TwoSidedPolygon + 'static)
}
#[test]
fn trivial_cast_supertype() {
let square = Square([2; 8]);
let square = &square as &dyn Polygon; // trivial cast: `&Square` as `&dyn Polygon`
process(square);
// process2(square); the size for values of type `dyn Polygon` cannot be known at compilation time
// process3(square); the trait bound `dyn Polygon: TwoSidedPolygon` is not satisfied
// process_square(square); expected &Square, found &dyn Polygon
}
#[test]
fn trivial_cast_subtype() {
let square = Square([2; 8]);
let square = &square as &dyn TwoSidedPolygon; // trivial cast: `&Square` as `&dyn TwoSidedPolygon`
process(square);
// process2(square); the size for values of type `dyn Polygon` cannot be known at compilation time
process3(square);
// process_square(square); expected &Square, found &(dyn TwoSidedPolygon + 'static)
}
#[test]
fn trivial_cast_struct_type() {
let square = Square([2; 8]);
let square = &square as □ // trivial cast: `&Square` as `&Square`
process(square);
process2(square);
process3(square);
process_square(square);
}
#[test]
fn auto_coercion() {
let square = Square([2; 8]);
let polygon = □
process(polygon);
process2(polygon);
process3(polygon);
process_square(polygon);
}
#[test]
fn shadowed_auto_coercion() {
let square = Square([2; 8]);
let square = Triangle([3; 6]);
let square = □
process(square);
process2(square);
// process3(square); the trait bound `Triangle: TwoSidedPolygon` is not satisfied
// process_square(square); expected &Square, found &Triangle
process_triangle(square);
}
#[test]
fn trivial_cast_supertype_with_shadowing() {
let square = Square([2; 8]);
let square = Triangle([3; 6]);
let square = &square as &dyn Polygon; // trivial cast: `&Square` as `&Square`
process(square);
// process2(square); the size for values of type `dyn Polygon` cannot be known at compilation time
// process3(square); the trait bound `dyn Polygon: TwoSidedPolygon` is not satisfied
// process_square(square); expected &Square, found &dyn Polygon
}
fn process_square(_square: &Square) {}
fn process_triangle(_triangle: &Triangle) {}
fn process(_polygon: &(impl Polygon + ?Sized)) {}
fn process2(_polygon: &impl Polygon) {}
fn process3(_polygon: &(impl TwoSidedPolygon + ?Sized)) {}
}
Комментарии
Вы можете оставить комментарий к этому блог-посту, публично ответив на него с помощью аккаунта Mastodon или другого аккаунта ActivityPub/Fediverse. Известные неприватные ответы отображены ниже.