Casts Não Tão Triviais

Por Nikita Bishonen1 minute read



Casts Não Tão Triviais

Existe um lint interessante em Rust chamado trivial_casts, que na verdade não é tão trivial.

It may be possible that this will become a warning in the future

então vamos explorar alguns exemplos de código onde vou comparar:

  1. Casts triviais
  2. Definições de tipos de variáveis
  3. Coerção implícita

Não vou adicionar nenhum comentário, exceto as saídas do compilador, para que você possa ver as diferenças por conta própria e decidir quando e como usar casts de tipos no código Rust. Apenas direi que trivial_cast_supertype_with_shadowing parece ser um bom exemplo de como trivial_casts podem se tornar não tão triviais mesmo em um exemplo pequeno (imagina o que pode fazer em uma cadeia maior de chamadas e transformações/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)) {}
}

Comentários

Pode comentar neste artigo respondendo publicamente a este post usando uma conta Mastodon ou outra conta ActivityPub/Fediverse. Respostas não privadas conhecidas são exibidas abaixo.

Abrir Artigo