Bienvenidos sean a este post, hoy hablaremos sobre un metodo muy particular.
Este metodo es util pero no es recomendable su uso, esto es debido a que nos permite utilizar en nuestro codigo aquellos elementos que la seguridad de memoria no pueden ser verificados por los tipos del sistema, y tenemos dos formas de usarlo:
- Declarar la existencia de contratos que el compilador no puede chequear
- Declarar que un programador ha comprobado que estos contratos se han respetado
Estos tambien se los conocen como superpoderes unsafe dado que nos permiten hacer cosas que el compilador no permitiria dado que no siempre tendremos toda la informacion necesaria para compilar un codigo y el lenguaje es mas de:
Es preferible rechazar un codigo valido antes que aceptar codigos invalidos
El tinchicus
Por eso gracias a esta instruccion podemos correr ciertas instrucciones y asegurarle al compilador que lo haga sin problemas que esta todo bien, este alter ego de nuestro lenguaje nos permite hacer varias cosas:
- Desreferenciar un apuntador raw
- Llamar a una funcion o metodo inseguro
- Acceder o modificar una variable estatica mutable
- Implementar un trait inseguro
Es importante aclarar que esta instruccion no desactiva al chequeador de borrow o alguno de los chequeos de seguridad, por lo tanto solo nos ayudara a omitir a algunos de los casos que mencionamos anteriormente pero el resto seguiran siendo chequeados, pasemos a ver algunas formas de sintaxis de esta instruccion:
- unsafe fn, le decimos al compilador que esta funcion cumple con el contrato
- unsafe trait, le decimos al compilador que este trait cumple con el contrato
- unsafe {}, le decimos al compilador que el bloque esta chequeado y respeta el contrato
- unsafe impl, le decimos al compilador que el impl del trait esta chequeado y respeta el contrato
Algunas de estas sintaxis las veremos mas adelante cuando hablemos sobre trait o impl, para verlo en accion vamos a intentarlo con un ejemplo.
En realidad vamos a ver como hubiera sido un ejemplo para averiguar cual es el tipo de datos de un generico, este codigo es para versiones de rust anteriores a la 1.38 dado que no tenia una funcion estable de type_name, veamos el codigo:
main.rs
#![feature(core_intrinsics)]
fn mostrar_tipo<T>(_: &T)
{
let nombre = unsafe {std::intrinsics::type_name::<T>()};
println!("{}", nombre);
}
fn main()
{
mostrar_tipo(&3.14f32);
mostrar_tipo(&1i32);
mostrar_tipo(&1.555);
mostrar_tipo(&(vec!(1,3,5)));
}
Lo primero que veremos en este codigo es un bloque que comienza con el numeral (#) lo cual informa que es una declaracion y entre los corchetes ira el atributo, cuando es #! significa que sera para un atributo interno en cambio cuando es # solamente significa que sera un atributo externo, en este caso le informamos que utilice a la libreria intrinsics para lo siguiente, despues tenemos una funcion llamada mostrar_tipo la cual manipula un tipo generico para poder manejar varios tipos, fue explicado en el post anterior, la unica diferencia es que utilizamos a unsafe con un bloque para utilizar a la funcion type_name donde le pasaremos el valor que recibimos en el argumento, por ultimo mostraremos el valor que se almaceno en la variable, despues en el main haremos cuatro llamados con distintos tipos de valores, nos devolvera algo semejante a esto:
tinchicus@dbn001vrt:~/lenguajes/rust/generico$ cargo run
Finished dev [unoptimized + debuginfo] target(s) in 0.01s
Running `target/debug/generico`
f32
i32
f64
std::vec::Vec<i32>
tinchicus@dbn001vrt:~/lenguajes/rust/generico$
Pero como dijimos esto aplica a versiones de rust anteriores a la 1.38 dado que ahora al momento de compilarlo les devolvera un error porque se encuentra implementado de forma estable y se debe usar como vimos en el post anterior, para resumir el metodo unsafe nos servira para cuando necesitemos hacer ciertas cosas de las cuales sabemos que el compilador no podra ejecutarlas ya sea porque las instrucciones no se encuentran definidas en la parte estable o bien por algunas de las circunstancias que hablamos anteriormente, no se preocupen porque la implementaremos con algunos casos mas adelante.
En resumen, hoy hemos visto a unsafe, que es, como trabaja, como nos permite crear un alter ego para la forma que trabaja Rust o el compilador, tambien hemos visto que nos permite omitir, despues un pequeño ejemplo de como se debia implementar antiguamente a type_name y en este caso entra en accion nuestro amigo unsafe, espero les haya sido de utilidad sigueme en tumblr, Twitter o Facebook para recibir una notificacion cada vez que subo un nuevo post en este blog, nos vemos en el proximo post.


Donación
Es para mantenimento del sitio, gracias!
$1.50
