rust - Do I need any of the *variantType markers? -
i'm trying interact type-unsafe c library in type-safe way rust. c interface deals void pointers. specifically, there write , read function takes such void pointer parameter , obvious things (write given data place else or read place given buffer). kind of data is, agreed upon earlier py bassing integer value open function
1 = float 2 = int32_t 4 = int16_t etc... i represent opened output stream (where user can call write on) parameterized rust struct one:
pub struct outputstream<t> { c_stream: *mut () } impl<t: valuetype> outputstream<t> { pub fn write(&mut self, data: &[t]) -> result<(),someerrortype> { unsafe { ... } } } where valuetype trait wrote supported value types in way nobody else can implement (private base trait trick). so, t not mentioned anywhere within struct. seems case contravarianttype marker. don't understand these type markers. visiting wikipedia page on variance not help. don't see connection between variance , how applies rust's type parameters. , don't know kind of marker prevent.
so questions are: need 1 of these markers outputstream? if so, 1 , why? prevent using it? same goes inputstream provides read method instead of write method.
in general, variance determines subtyping relationship between parameterized types regard parameters:
covariance: t <: u => f[t] <: f[u] contravariance: t <: u => f[u] <: f[t] invariance: t <: u => neither of above bivariance: t <: u => both of above your type is naturally contravariant: methods consume values of type t, not produce them; so-called consumer type. however, subtyping in rust limited; far know, types allow subtyping relationship of kind references (for example, can pass &'static str &'a str variable because 'static lifetime greater or equal other lifetime, &'static str subtype of &'a str 'a).
so, if understand correctly, need variance annotation. if t parameter can reference, use contravarianttype, this:
fn push_something_to(os: outputstream<&'static str>) { ... } let s: outputstream<&'a str> = ...; // , 'a less 'static push_something_to(s); // safe because &'static str valid &'a str but couldn't this:
let s: outputstream<int> = ...; push_something_to(s); // oops, push_something_to expects stream of &'static str with invarianttype both forbidden.
however, there seems deep misunderstanding on side, because neither code in documentation on variance markers, nor own code not work in current rust me:
use std::ptr; use std::mem; struct s<t> { x: *const () } fn get<t>(s: &s<t>, v: t) { unsafe { let x: fn(t) = mem::transmute(s.x); x(v) } } fn main() { let s: s<int> = s { x: ptr::null() }; get::<box<int>>(&s, box 1); } according documentation, should compile due parameterized types being bivariant default, doesn't: acts if parameter invariant.
and own example:
#![allow(dead_code)] type f<t> = fn(t); fn test_1<'a>(f: f<&'a str>) -> f<&'static str> { f } struct s<t> { _m: std::kinds::marker::contravarianttype<t> } fn test_2<'a>(s: s<&'a str>) -> s<&'static str> { s } fn main() {} as far understand, program should compile, doesn't:
<anon>:9:5: 9:6 error: mismatched types: expected `s<&'static str>` found `s<&'a str>` (lifetime mismatch) <anon>:9 s ^ <anon>:8:47: 10:2 note: lifetime 'a defined on block @ 8:46... <anon>:8 fn test<'a>(s: s<&'a str>) -> s<&'static str> { <anon>:9 s <anon>:10 } note: ...does not outlive static lifetime if remove s , test_2, compiles fine, demonstrating function types indeed contravariant regard argument types.
i don't know what's happening , looks deserves question.
Comments
Post a Comment