Join GitHub today
GitHub is home to over 31 million developers working together to host and review code, manage projects, and build software together.
Sign upOpaque Data structs for FFI #1993
Conversation
This comment has been minimized.
This comment has been minimized.
|
Reading the RFC makes me think, could
|
kennytm
reviewed
May 6, 2017
|
|
||
| Finally, many trait parmaeters would be updated in the standard library to relax | ||
| their trait bounds from `?Sized` to `?DynSized` which should be a | ||
| backwards-compatible change. |
This comment has been minimized.
This comment has been minimized.
kennytm
May 6, 2017
Member
(nit: parmaeters ↦ parameters)
size_of_val is used indirectly whenever the type needs to manage allocation itself, so types like Box and Rc need to remain T: ?Sized.
Traits like Borrow and AsRef should be loosened to ?DynSized. UnsafeCell should also be relaxed to ?DynSized provided that it is safe to transmute an &mut Opaque to &UnsafeCell<Opaque>.
It may not be an easy change.
This comment has been minimized.
This comment has been minimized.
mystor
May 7, 2017
Author
This could fairly easily be implemented, and then trait bounds relaxed on various places where it is safe in a follow up. I agree that types like Rc shouldn't have their bound relaxed from T: ?Sized to T: ?DynSized.
I can look through the standard library and determine which bounds should be relaxed, adding that to the RFC if we want. Actually relaxing the bounds shouldn't be too hard.
This comment has been minimized.
This comment has been minimized.
What does it mean to create a trait object of an opaque type? Perhaps Strictly speaking, we cannot say that the type can be figured out at runtime, right? What about using Also, I generally don't know how I feel about this... it is definitely an important problem, and I like this solution's concept, but it seems to touch rather a lot of stuff across the language. That makes me nervous. I feel like there are possibly a lot of places where bounds would change and unexpected behavior might happen, like the point that @kennytm makes here. |
This comment has been minimized.
This comment has been minimized.
A reference to a trait, or a trait object // A trait like `Trait` with a method:
trait Trait {
fn method(&self);
}
// Is represented something like this (I haven't actually looked
// into Rust's exact VTable layout, so this might be wrong...)
struct TraitVTable {
size: usize,
align: usize,
methods: TraitVTableMethods,
}
struct TraitVTableMethods {
method: fn(this_ptr: *const u8),
}
struct &Trait {
data: *const u8,
vtable: *const TraitVTable,
}If you have an opaque type: struct Mine(Opaque);
impl Trait for Mine {
fn method(&self) { println!("Hello!"); }
}Would then be cast to a trait object by taking the pointer to the struct &Trait + ?DynSized {
data: *const u8,
vtable: *const TraitVTableMethods,
}That way it doesn't need a
We do know the type, and if we have a trait object of the opaque type it can be figured out at runtime, we just cannot know the layout of the type. That's what
That type is not safe to put behind a If we do land this type, it would be awesome to change the definition of
I agree that this is an unfortunately large change to the language, which is why I try to also mention the other, much smaller, options which don't involve introducing the This was designed such that no bounds would change without them being explicitly annotated, so no unexpected behavior should happen. If some behavior would change anywhere, that's a bug in the RFC's design. This RFC should be 100% backwards-compatible. The main reason why |
This comment has been minimized.
This comment has been minimized.
Nope, I think we would need both |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
|
@kennytm I do mention how this would be implemented under this RFC - It would be done by writing |
nrc
added
the
T-lang
label
May 11, 2017
aturon
self-assigned this
May 11, 2017
This comment has been minimized.
This comment has been minimized.
|
Ah, got it. So
Sorry, this is a typo. It should say "we cannot say that the size can be figured out at runtime"... that's why I proposed a name that does not include the word "sized".
Got it
Mostly, I am thinking of weird corner cases that might impact soundness or something... like what is the interaction with
Part of me wonders if there is a more formal way to define Opaqueness in the type system. i.e. is there any type theory exploring this issue which might show us where bugs might show up? (btw, I don't know that much about type theory, so I might be totally wrong). Also, I do want to underscore that I like the RFC in general... I just have vague uneasiness, too... |
This comment has been minimized.
This comment has been minimized.
|
So the first thing I want to point out is that Just like in rust today, you cannot have a value of type Another value is "made opaque" by including a field of an "opaque" data type as
You would not be able to implement a trait which requires passing around struct CStr(Opaque);
impl Deref for CStr {
type Target = [u8];
fn deref(&self) -> &[u8] {
unsafe {
slice::from_raw_parts(self as *const _ as *const u8, self.len())
}
}
}The reason why I want to support implementing inherit methods and traits on let x: &CStr = ...;
cstr_len(x);
// -- instead of --
x.len();
Values which are
You cannot write this expression, as
It would be a ZST, just like
This is what we're doing here. We're defining Opaqueness as being
My main comfort with this RFC is that it is very similar to code which we IMO the main risk here doesn't really come from its interactions with the type system, so |
kennytm
reviewed
May 12, 2017
| unsafe impl DynSized for MyStruct { | ||
| fn size_of_val(&self) -> usize { | ||
| somehow_determine_size() |
This comment has been minimized.
This comment has been minimized.
kennytm
May 12, 2017
Member
Allowing user to provide these functions means calling size_of_val(&x) may take unknown run time (e.g. the implementation for CStr would be O(n)), while the size_of_val(&x) of all existing types are O(1). Is this an acceptable trade-off to make?
This comment has been minimized.
This comment has been minimized.
Ericson2314
May 12, 2017
Contributor
It's a matter of taste I've wondered about myself, but since custom DSTs is a very much optional followup project (I do want them but opaque data is quite worthwhile on its own), I'm not inclined to think the resolution of this question blocks this RFC.
I suppose it wouldn't hurt to still mention that though :).
This comment has been minimized.
This comment has been minimized.
mystor
May 12, 2017
Author
I mostly mention the impl DynSized construct because it would be required in order to migrate CStr to using Opaque, rather than because it is something which I think is essential to the core of this RFC. I'd imagine that we would stabilize impl DynSized separately from the Opaque work, and mention as much in the RFC text.
aturon
added
the
S-waiting-on-shepherd
label
Jun 6, 2017
This comment has been minimized.
This comment has been minimized.
|
surprised to find that there is no definition of semantic of the |
This comment has been minimized.
This comment has been minimized.
|
@liigo what do you think is missing? There is an entire section of the rfc dedicated to describing the dynsized trait, and I tried my best to be thorough. |
This comment has been minimized.
This comment has been minimized.
|
@mystor Maybe there lacks a summary line of docs of |
mystor commentedMay 6, 2017
This RFC is an offshoot of (and hopes to supersede) #1861 as mentioned in this comment.
This is a rewrite of the original RFC with a focus on the simpler syntactically
Opaqueunsized struct, and tries to serve as a document exploring both the motivation for implementing this feature in rust today, as well as the different approaches for handling thesize_of_valandtype_of_valfeatures.I made the decision to focus the core text of the RFC on the
DynSizedapproach to thesize_of_valandtype_of_valproblem, as it is the solution to the problem which causes the largest change to the language, and needs the most exploration. The other solutions are mentioned in the Alternatives section, and are simpler in concept and implementation, so need less text discussing them. However, I have tried to keep the pieces of the RFC which discuss this separated, so that it is easy to tell which parts of the RFC are related to theDynSizedtrait, and which are related to theOpaquestruct.rendered