I'm banging my head against this supposedly simple usage of Box whilst trying to create some FFI helper code.
The sample here seems to give an error of free(): invalid pointer when used with a struct that has a field.
pub struct Handle(usize);
impl Handle {
pub fn from<T>(obj: T) -> Self {
let boxed = Box::new(obj);
let mut ptr = Box::into_raw(boxed);
Self::from_ptr_mut(&mut ptr)
}
pub fn from_ptr_mut<T>(ptr: &mut T) -> Self {
Self(ptr as *mut T as usize)
}
pub fn to_box<T>(self) -> Box<T> {
let obj: *mut T = self.to_ptr_mut();
unsafe { Box::from_raw(obj) }
}
pub fn to_ptr_mut<T>(self) -> *mut T {
self.0 as *mut T
}
}
#[allow(dead_code)]
struct Crashes { value: u64 }
impl Drop for Crashes {
fn drop(&mut self) {
println!("Crashes dropped");
}
}
fn crashes() {
let t = Crashes { value: 12 };
let a = Handle::from(t);
let b = a.to_box::<Crashes>();
drop(b);
}
struct Works;
impl Drop for Works {
fn drop(&mut self) {
println!("Works dropped");
}
}
fn works() {
let t = Works;
let a = Handle::from(t);
let b = a.to_box::<Works>();
drop(b);
}
fn main() {
works();
crashes();
}
You can paste this into https://play.rust-lang.org/ and see how it throws aborts with the error free(): invalid pointer
The drop function seems to be called at the appropriate time, but the pointer seems to be somehow invalid
You end up creating a double pointer here:
impl Handle {
pub fn from<T>(obj: T) -> Self {
let boxed = Box::new(obj);
let mut ptr = Box::into_raw(boxed);
Self::from_ptr_mut(&mut ptr)
}
pub fn from_ptr_mut<T>(ptr: &mut T) -> Self {
Self(ptr as *mut T as usize)
}
...
}
Box::into_raw returns a pointer, but then you take a mutable reference to that pointer, and store that address as a usize. You should just be using the *mut T as returned by Box::into_raw.
The reason that the non-working code with the double pointer compiles is that your from<T> and your from_ptr_mut<T> can take entirely different T parameters. If we consider the type T passed to from<T> to be a concrete type, then in this case you're calling from_ptr_mut<U> (where U is *mut T) with an argument of type &mut *mut T.
It should look like so:
impl Handle {
pub fn from<T>(obj: T) -> Self {
let boxed = Box::new(obj);
let ptr = Box::into_raw(boxed);
Self::from_ptr_mut(ptr)
}
pub fn from_ptr_mut<T>(ptr: *mut T) -> Self {
Self(ptr as usize)
}
...
}
Working example in the playground.
Even though we are in the realm of unsafe you can have the compiler do some of the work for you by making the parameter T be bound to your Handle struct. This way you will be statically prevented from loading a different type than was stored.
Playground example where Handle includes a PhantomData.
In this second example you don't have to tell the compiler which item you're retrieving a la a.to_box::<Crashes>(), which is good because you can't introduce undefined behavior by specifying the wrong type.
Related
I'm trying to call SomeClass().call, but am running into compiler errors.
Specifically, running tests for
const std = #import("std");
test "doing a thing" {
{
const calc_result = SomeClass().call(.{});
try std.testing.expectEqual(calc_result, 42);
}
}
fn SomeClass() type {
return struct {
fn call(context: .{}) u32 {
_ = context;
return 42;
}
};
}
results in the error message
src/test.zig:12:17: error: expected type 'type', found '#TypeOf(.{})'
fn call(context: .{}) u32 {
^~~~~~~
referenced by:
test.doing a thing: src/test.zig:5:40
remaining reference traces hidden; use '-freference-trace' to see all reference traces
How do I call a generic type method that takes an empty context?
What you're doing is equivalent to fn foo(value: 0) void {}. Which is obviously wrong. A function definition cannot have values.
You need to define the type of the context:
const std = #import("std");
const Context = struct {
};
fn SomeClass() type {
return struct {
fn call(context: Context) u32 {
_ = context;
return 42;
}
};
}
test "doing a thing" {
{
const calc_result = SomeClass().call(.{});
try std.testing.expectEqual(calc_result, 42);
}
}
Or, use anytype:
fn call(context: anytype) u32 { ... }
I have a requirement to read the memory occupied by an object based on some events. Is there's a simple method that I can use from the standard library ? I need to access the memory usage of the following object which contains nested structs.
HashMap<String, HashMap<AppIdentifier, HashMap<String, u64>>>
I recommend you create a trait with a method that returns the size of self's transitively-owned allocations:
trait AllocatedSize {
fn allocated_size(&self) -> usize;
}
And then implement that for everything involved:
impl AllocatedSize for u64 {
fn allocated_size(&self) -> usize {
0
}
}
impl AllocatedSize for String {
fn allocated_size(&self) -> usize {
self.capacity()
}
}
impl AllocatedSize for AppIdentifier {
fn allocated_size(&self) -> usize {
todo!()
}
}
impl<K: AllocatedSize, V: AllocatedSize> AllocatedSize for HashMap<K, V> {
fn allocated_size(&self) -> usize {
// every element in the map directly owns its key and its value
const ELEMENT_SIZE: usize = std::mem::size_of::<K>() + std::mem::size_of::<V>();
// directly owned allocation
// NB: self.capacity() may be an underestimate, see its docs
// NB: also ignores control bytes, see hashbrown implementation
let directly_owned = self.capacity() * ELEMENT_SIZE;
// transitively owned allocations
let transitively_owned = self
.iter()
.map(|(key, val)| key.allocated_size() + val.allocated_size())
.sum();
directly_owned + transitively_owned
}
}
What's missing from my attempt at a heapless linked list?
My goal is to get the below code to generate the sequence [1, 2, 3] on the stack and then print those values out on separate lines without using Box or anything else requiring the heap or std or malloc.
I've skimmed through https://rust-unofficial.github.io/too-many-lists but all the "good" lists seem to depend on Rc, Box, etc.
The heapless crate is neat but requires knowing the size of a list beforehand.
My Google-fu isn't strong enough to find much help. Any pointers would be much appreciated. But here's what I'm thinking:
struct Node<'a, T> {
value: T,
next: Option<&'a Node<'a, T>>
}
struct List<'a, T> {
head: Option<&'a Node<'a, T>>,
tail: Option<&'a Node<'a, T>>
}
impl<'a, T> List<'a, T> {
fn new() -> Self {
Self {
head: None,
tail: None
}
}
fn push(self, value: T) ->Self {
unimplemented!(); // What's missing here?
}
}
struct Iter<'a, T> {
next: Option<&'a Node<'a, T>>
}
impl<'a, T> Iterator for Iter<'a, T> {
type Item = &'a T;
fn next(&mut self) -> Option<&'a T> {
match self.next.take() {
Some(next) => {
self.next = next.next;
Some(&next.value)
},
None => None
}
}
}
impl<'a, T> IntoIterator for List<'a, T> {
type Item = &'a T;
type IntoIter = Iter<'a, T>;
fn into_iter(self) -> Self::IntoIter {
Iter {
next: self.head
}
}
}
fn main() {
let list = List::new();
let list = list.push(1);
let list = list.push(2);
let list = list.push(3);
for item in list {
println!("{}", item);
}
}
As you can see I'm stuck trying to implement List.push.
Allocating things on the stack without knowing their size (or at the very least an upper bound of their size) is squaring the circle and will not work. You can let the compiler figure out the size for you, but that is pretty much it. The reason for this is simple: Stack allocations may not fail and the compiler has to make sure everything fits in.
If you want to go ahead and stick with the push(T) signature, just taking a value Matt Thomas' answer is the way to go.
Here is my take on the issue, which avoids building nested types:
struct Node<'a, T> {
value: T,
next: Option<&'a Node<'a, T>>,
}
impl<'a, T> Node<'a, T> {
pub fn new(value: T, next: Option<&'a Self>) -> Self {
Node { value, next }
}
pub fn iter(&'a self) -> Iter<'a, T> {
Iter {
current: Some(self),
}
}
}
struct Iter<'a, T> {
current: Option<&'a Node<'a, T>>,
}
impl<'a, T> Iterator for Iter<'a, T> {
type Item = &'a T;
fn next(&mut self) -> Option<&'a T> {
match self.current {
Some(Node { value, next }) => {
self.current = *next;
Some(value)
}
None => None,
}
}
}
fn main() {
// Allocation of the Nodes directly on the stack,
// not inside a push method. <= Solves lifetime issues
// Reversed order solves mutability issues.
let three = Node::new(3, None);
let two = Node::new(2, Some(&three));
let one = Node::new(1, Some(&two));
for item in one.iter() {
println!("{}", item)
}
}
Here's a heapless stack that accomplishes the goals stated in the OP:
https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=fb26b12270bd0a523a693276ec36014f
#[derive(Debug)]
struct Cons<T, U>(T, U);
#[derive(Debug)]
struct MyOption<T>(Option<T>);
trait Push<T>: Sized {
fn push(self, value: T) -> Cons<Self, T>;
}
impl<T, U> Push<U> for Cons<T, U> {
fn push(self, value: U) -> Cons<Self, U> {
Cons(self, value)
}
}
impl<T> Push<T> for T {
fn push(self, value: T) -> Cons<Self, Self> {
Cons(self, value)
}
}
impl<T: Iterator<Item = U>, U> Cons<T, MyOption<U>> {
fn next(&mut self) -> Option<U> {
match (self.1).0.take() {
Some(u) => Some(u),
None => self.0.next()
}
}
}
impl<T> Iterator for Cons<MyOption<T>, MyOption<T>> {
type Item = T;
fn next(&mut self) -> Option<Self::Item> {
match (self.1).0.take() {
Some(t) => Some(t),
None => (self.0).0.take()
}
}
}
impl<T: Iterator<Item = U>, U> Iterator for Cons<Cons<T, MyOption<U>>, MyOption<U>> {
type Item = U;
fn next(&mut self) -> Option<Self::Item> {
match (self.1).0.take() {
Some(u) => Some(u),
None => self.0.next()
}
}
}
impl<T> Iterator for MyOption<T> {
type Item = T;
fn next(&mut self) -> Option<Self::Item> {
self.0.take()
}
}
fn create_stack() -> impl Iterator<Item = i32> + core::fmt::Debug {
MyOption(Some(0))
.push(MyOption(Some(1)))
.push(MyOption(Some(2)))
.push(MyOption(Some(3)))
.push(MyOption(Some(4)))
}
fn main() {
let stack = create_stack();
println!("Here's the stack:");
println!("{:?}", stack);
println!("Here are the items in reverse order");
for item in stack {
println!("{}", item);
}
}
Output:
Here's the stack:
Cons(Cons(Cons(Cons(MyOption(Some(0)), MyOption(Some(1))), MyOption(Some(2))), MyOption(Some(3))), MyOption(Some(4)))
Here are the items in reverse order
4
3
2
1
0
Caveats
You can't do stack = stack.push(...) in a loop (because stack.push(...) returns a different type)
I didn't think at all about Drop behavior. I guess it would be recursive and blow up for large stacks
This can create huge structs. Try not to move them around too much
Is there a way to create an Iterator that doesn't require the Cons structs to hold Option types? And a way that can be iterated more than once? Maybe
I suspect that every one of those impl functions is duplicated for every element in the resulting stack (since each element is of a different type and all the functions are generic)
Every call to .push() can potentially copy self (not as in the Copy trait, but as in Rust could do a memcpy behind the scenes as part of the ownership move to keep things tidy on the stack)
I'm about to give a trait as argument to store it through a contructor method called new.
The trait for a struct type is given as argument here:
renderer.rs
use super::shapes::Shape;
pub struct Renderer;
impl Renderer{
pub fn set_shape<T : Shape>(&self, shape: T) -> T::Builder{
T::Builder::new(shape)
}
}
then the contructor of the Builder specified by the associated type will be called
shapebuilder.rs
use super::shapes::Shape;
use super::shapes::Rectangle;
pub trait ShapeBuilder{
fn new<T:Shape>(shape: T) -> Self;
}
pub struct RectangleBuilder{
shape: Shape<Builder=RectangleBuilder>
}
impl ShapeBuilder for RectangleBuilder{
fn new<T:Shape>(shape: T) -> Self{
RectangleBuilder{
shape: shape as Rectangle
}
}
}
at this point I already want to point out the compiler output
compiler_output
error[E0277]: the trait bound `shapes::Shape<Builder=shapebuilder::RectangleBuilder> + 'static: std::marker::Sized` is not satisfied
--> shapes.rs:14:6
|
14 | impl Shape for Rectangle{
| ^^^^^
|
= note: `shapes::Shape<Builder=shapebuilder::RectangleBuilder> + 'static` does not have a constant size known at compile-time
= note: required because it appears within the type `shapebuilder::RectangleBuilder`
= note: required by `shapes::Shape`
error: aborting due to previous error
I found similar questions here on SO which told something about Boxing. I tried to Box every parameter type to solve the issue. Boxed it like this shape: Box<T>. No success. Do I need to box at all? I understand the issue that the compiler is not able to resolve the size of a trait since the specific/concrete struct types can have different sizes depending on their field/properties. Still I'm not able to find a solution. Hope it's trivial.
NOT involed modules (my opinion) listed for completeness
shapes.rs
use super::shapebuilder::ShapeBuilder;
use super::shapebuilder::RectangleBuilder;
pub trait Shape{
type Builder: ShapeBuilder;
}
#[derive(Clone, Copy)]
pub struct Rectangle{
pub height: usize,
pub width: usize,
}
impl Shape for Rectangle{
type Builder = RectangleBuilder;
}
lib.rs
pub mod renderer;
mod shapes;
mod shapebuilder;
Well, the compiler is not really pointing at the source of the error. The problem is here:
pub struct RectangleBuilder {
shape: Shape<Builder=RectangleBuilder>
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ this is an unsized type!
}
Shape is a trait, and using it as a type yields an unsized type. We could box it to fix this error:
pub struct RectangleBuilder {
shape: Box<Shape<Builder=RectangleBuilder>>
}
But then, what do we do about the cast here?
impl ShapeBuilder for RectangleBuilder {
fn new<T: Shape>(shape: T) -> Self {
RectangleBuilder {
shape: shape as Rectangle
// ^^^^^^^^^^^^^^^^^^ can't cast a generic type!
}
}
}
If RectangleBuilder will indeed be ready to accept any Shape whose Builder is RectangleBuilder, then let's remove the cast and add the appropriate constraints where necessary.
pub mod renderer {
use super::shapes::Shape;
use super::shapebuilder::ShapeBuilder;
pub struct Renderer;
impl Renderer {
pub fn set_shape<T: Shape + 'static>(&self, shape: T) -> T::Builder {
T::Builder::new(shape)
}
}
}
mod shapes {
use super::shapebuilder::ShapeBuilder;
use super::shapebuilder::RectangleBuilder;
pub trait Shape {
type Builder: ShapeBuilder;
}
#[derive(Clone, Copy)]
pub struct Rectangle {
pub height: usize,
pub width: usize,
}
impl Shape for Rectangle {
type Builder = RectangleBuilder;
}
}
mod shapebuilder {
use super::shapes::Shape;
pub trait ShapeBuilder: Sized {
fn new<T: Shape<Builder=Self> + 'static>(shape: T) -> Self;
}
pub struct RectangleBuilder {
shape: Box<Shape<Builder=RectangleBuilder> + 'static>,
}
impl ShapeBuilder for RectangleBuilder {
fn new<T: Shape<Builder=Self> + 'static>(shape: T) -> Self {
RectangleBuilder {
shape: Box::new(shape)
}
}
}
}
The 'static bound puts a limit on the references that can be stored in a particular Shape instance. 'static means that the implementations cannot contain references, unless they have the 'static lifetime.
However, if you'll need to use Rectangle's fields in RectangleBuilder, then RectangleBuilder should only accept Rectangles, rather than any shape. We can use associated types again to express this.
pub mod renderer {
use super::shapes::Shape;
use super::shapebuilder::ShapeBuilder;
pub struct Renderer;
impl Renderer {
pub fn set_shape<T: Shape>(&self, shape: T) -> T::Builder {
T::Builder::new(shape)
}
}
}
mod shapes {
use super::shapebuilder::ShapeBuilder;
use super::shapebuilder::RectangleBuilder;
pub trait Shape {
type Builder: ShapeBuilder<Shape=Self>;
}
#[derive(Clone, Copy)]
pub struct Rectangle {
pub height: usize,
pub width: usize,
}
impl Shape for Rectangle {
type Builder = RectangleBuilder;
}
}
mod shapebuilder {
use super::shapes::Shape;
use super::shapes::Rectangle;
pub trait ShapeBuilder: Sized {
type Shape: Shape + ?Sized;
fn new(shape: Self::Shape) -> Self;
}
pub struct RectangleBuilder {
shape: Rectangle,
}
impl ShapeBuilder for RectangleBuilder {
type Shape = Rectangle;
fn new(shape: Self::Shape) -> Self {
RectangleBuilder {
shape: shape
}
}
}
}
In ShapeBuilder, we've added a Shape associated type that specifies what type of Shape each ShapeBuilder will operate on. ShapeBuilder::new now uses this associated type, instead of a type parameter, to specify the type of its operand. Note that the + ?Sized bound is needed because otherwise there's an implicit + Sized bound, and Rust complains that Shape doesn't imply Sized. Another way to fix this is to add : Sized to Shape's definition.
pub trait Shape: Sized {
type Builder: ShapeBuilder<Shape=Self>;
}
While researching XCTAssert methods by pressing command+click, it looks like they underlying method is a function that has a type (a generic type referred to as T, that conforms to the Equatable protocol). Am I saying this correctly, and if so how do functions comform to protocols? Are functions types?
public func XCTAssertEqual<T : Equatable>(_ expression1: #autoclosure () throws -> ArraySlice<T>, _ expression2: #autoclosure () throws -> ArraySlice<T>, _ message: #autoclosure () -> String = default, file: StaticString = #file, line: UInt = #line)
This line is the most confusing which I'm trying to explain above:
func XCTAssertEqual<T : Equatable>`
Every function has a specific function type, made up of the parameter types and the return type of the function.
typealias FooType = (Int, String)->String
func foo(i: Int, s: String)->String {
return s + "_\(i)"
}
func bar(foo0: FooType)->String {
return foo0(100, "alpha")
}
print(bar(foo)) // alpha_100
let f:FooType = { i, s in
return s + "_\(i)"
}
print(f(200, "beta")) // beta_200
an appendix, especially for Brandon :-)
let farr:[()->Int] = [{return 1}, {return 2}, {return 3}]
for f in farr {
print(f())
/*
1
2
3
*/
}
appendix 2, for Brandon
func f1()->Int {
return 1
}
func f2()->Int {
return 2
}
let farr2:[()->Int] = [f1, f2]
for f in farr2 {
print(f())
/*
1
2
*/
}
app 3 :-)
let farr2 = [f1, f2]
for f in farr2 {
print(f())
/*
1
2
*/
}
from apple docs
Every function in Swift has a type, consisting of the function’s
parameter types and return type. You can use this type like any other
type in Swift, which makes it easy to pass functions as parameters to
other functions, and to return functions from functions. Functions can
also be written within other functions to encapsulate useful
functionality within a nested function scope.