This question already has answers here:
How to get a reference to a concrete type from a trait object?
(2 answers)
How do I pass Rc<RefCell<Box<MyStruct>>> to a function accepting Rc<RefCell<Box<dyn MyTrait>>>?
(1 answer)
Closed 1 year ago.
I've searched everywhere for this and found various answers for similar things but nothing specific yet.
Context: my networking subsystem is extendable with new message types. That rules out using an enum.
Is it valid to convert a Box<dyn Trait> to a Box<Concrete> using x_ptr as *const Box<Concrete> where x_ptr is an unsafe pointer to Trait?
If so what restrictions does it place on Concrete or Trait?
I looked at downcast() implementations for Any in the repo, and indeed it seems to just be casting between pointer types. So I assume what I am trying to do is indeed valid.
Full example below:
use std::rc::Rc;
trait A {
fn name(&self) -> &str;
}
struct B {
x: u32
}
impl B {
}
impl A for B {
fn name(&self) -> &str {
"hello"
}
}
fn main() {
let x: Rc<Box<dyn A>> = Rc::new(Box::new(B { x: 110 }));
println!("count after creating x = {}", Rc::strong_count(&x));
let x_ptr = Rc::into_raw(x.clone());
println!("count after creating x = {}", Rc::strong_count(&x));
let y = unsafe {
// Convert back to an `Rc` to prevent leak.
let x: Rc<Box<B>> = Rc::from_raw(x_ptr as *const Box<B>);
println!("{}", x.x);
println!("{}", x.name());
x
// Further calls to `Rc::from_raw(x_ptr)` would be memory-unsafe.
};
let z = y.clone();
println!("count after creating x = {}", Rc::strong_count(&x));
// The memory was freed when `x` went out of scope above, so `x_ptr` is now dangling!
}
Yields desired output of:
count after creating x = 1
count after creating x = 2
110
hello
count after creating x = 3
Related
Im building a data structure containing nodes, and each node might point to another.
The pointers between the nodes are implemented using Rc, something like this:
struct Node {
ptr: Rc<Node>
}
I would like to be able to change the pointer 'ptr' of a node to point to another node, by cloning another existing Rc.
let a: Rc<Node> = ...;
let mut b: Node = ...;
let b.ptr = a.clone();
My problem is, the compiler think I am trying to set the value of the node, namely changing the underlying shared object of b.ptr, where I realy want to replace the pointer:
reduce the refcount of the old value of b.ptr, increase the refcount of a, and change b.ptr to point to a.
I managed to do it with Cell<Rc>, but I seems too vebose and unnecessary.
How can I do that?
My problem is, the compiler think I am trying to set the value of the node, namely changing the underlying shared object of b.ptr
That's rather unlikely given the code you posted, and with code which is incomplete, separately broken, and without the error message, it's difficult to diagnose. Even Shepmaster has yet to achieve psychic powers letting him know information not provided.
Fixing the obviously missing or incorrect I get something like:
use std::rc::Rc;
struct Node {
ptr: Option<Rc<Node>>,
}
fn main() {
let a = Rc::new(Node { ptr: None });
let b = Node { ptr: None };
b.ptr = a.clone().into();
}
and the error message is completely clear:
error[E0594]: cannot assign to `b.ptr`, as `b` is not declared as mutable
--> src/main.rs:8:5
|
7 | let b = Node { ptr: None };
| - help: consider changing this to be mutable: `mut b`
8 | b.ptr = a.clone().into();
| ^^^^^ cannot assign
this is fixed by simply declaring b as mutable as the compiler suggests[0]:
use std::rc::Rc;
struct Node {
ptr: Option<Rc<Node>>,
}
fn main() {
let a = Rc::new(Node { ptr: None });
let mut b = Node { ptr: None };
b.ptr = a.clone().into();
}
[0]: not that it's always right, far from it, but in this case its suggestion is fine.
This question already has an answer here:
Why do I get an "overflow evaluating the requirement" error for a simple trait implementation?
(1 answer)
Closed 1 year ago.
While experimenting with the decorator design pattern in Rust, I came across what I believe may be a compiler error, but I am too new to the language to be confident.
I think that the following example code should not generate a recursive trait E0275 error.
A simple type that can be converted to an i64:
enum MyNumbers {
Zero,
One,
Two,
}
impl From<MyNumbers> for i64 {
fn from(n: MyNumbers) -> Self {
match n {
MyNumbers::Zero => 0,
MyNumbers::One => 1,
MyNumbers::Two => 2,
}
}
}
And here, a struct that might be used in a decorator:
struct MyWrapper<N> {
n: N,
}
MyWrapper<N> can be converted to an i64 if N can be converted to i64.
impl<N> From<MyWrapper<N>> for i64
where
N: Into<i64>,
{
fn from(wrapper: MyWrapper<N>) -> Self {
wrapper.n.into()
}
}
Playground
This works as I expect.
Now I want to be able to construct an i64 from MyWrapper without consuming it. I change my From trait implementations to operate on references:
impl From<&MyNumbers> for i64 {
fn from(n: &MyNumbers) -> Self {
match n {
MyNumbers::Zero => 0,
MyNumbers::One => 1,
MyNumbers::Two => 2,
}
}
}
impl<'a, N> From<&'a MyWrapper<N>> for i64
where
&'a N: Into<i64>,
{
fn from(wrapper: &'a MyWrapper<N>) -> Self {
(&wrapper.n).into()
}
}
Playground
But now...
error[E0275]: overflow evaluating the requirement `i64: From<&MyWrapper<_>>`
--> src/main.rs:34:13
|
34 | let i = i64::from(&w);
| ^^^^^^^^^
|
= help: consider adding a `#![recursion_limit="256"]` attribute to your crate (`playground`)
= note: required because of the requirements on the impl of `Into<i64>` for `&MyWrapper<_>`
= note: required because of the requirements on the impl of `From<&MyWrapper<MyWrapper<_>>>` for `i64`
= note: 126 redundant requirements hidden
= note: required because of the requirements on the impl of `From<&MyWrapper<MyWrapper<MyWrapper<MyWrapper<MyWrapper<MyWrapper<MyWrapper<MyWrapper<MyWrapper<MyWrapper<MyWrapper<MyWrapper<MyWrapper<MyWrapper<MyWrapper<MyWrapper<MyWrapper<MyWrapper<MyWrapper<MyWrapper<MyWrapper<MyWrapper<MyWrapper<MyWrapper<MyWrapper<MyWrapper<MyWrapper<MyWrapper<MyWrapper<MyWrapper<MyWrapper<MyWrapper<MyWrapper<MyWrapper<MyWrapper<MyWrapper<MyWrapper<MyWrapper<MyWrapper<MyWrapper<MyWrapper<MyWrapper<MyWrapper<MyWrapper<MyWrapper<MyWrapper<MyWrapper<MyWrapper<MyWrapper<MyWrapper<MyWrapper<MyWrapper<MyWrapper<MyWrapper<MyWrapper<MyWrapper<MyWrapper<MyWrapper<MyWrapper<MyWrapper<MyWrapper<MyWrapper<MyWrapper<MyWrapper<MyWrapper<_>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>` for `i64`
Why was this fine for owned types, but not references?
Also, this really confuses me -
No calls to i64::from() is fine - Playground
Call to different i64::from errors - but should not be evaluating my code!? Playground
fn main() {
i64::from(32i32);
}
Compiler bug. https://github.com/rust-lang/rust/issues/37748
As a workaround, I have had to resort to #[derive(Copy)] to prevent my types from being consumed at each level of the conversion. Perhaps From/Into is poorly suited to this pattern.... Until the language matures a little more.
This question already has answers here:
Why does iterating a vector of i32s give references to i32 (&i32)?
(2 answers)
What is an idiomatic way to collect an iterator of &T into a collection of Ts?
(2 answers)
Closed 1 year ago.
I am attempting to return a 2D array from a function with this prototype:
fn function1(rep1: usize, rep2: usize) -> (Vec<Vec<bool>>) {
There is this 2D vector struct in the function:
let mut array2d: Vec<Vec<bool>>;
I am using following itertools loop:
for perm in items.iter().permutations(items.len()).unique() {}
Each instance of perm is Vec<&bool> rather than Vec<bool> and so in every loop upon trying to push into array2d with array2d.push(perm); I get the following error:
note: expected struct `Vec<bool>` found struct `Vec<&bool>`
Initially I have attempted at modifying the return specifier to allow me to return 2D Vec of pointers but failed somehow at doing so. I'd be grateful if someone could show me how to dereference/cast vector of addresses as a vector of values and/or how to change return specifier so that I can return Vec<Vec<&bool>> rather than Vec<Vec<bool>>.
Full code snippet:
fn function1(rep1: usize, rep2: usize) -> (Vec<Vec<bool>>) {
let mut array2d: Vec<Vec<bool>>;
let mut items = vec![false; rep2];
for r in 0..(rep1 - 1){
items[r] = true;
}
for perm in items.iter().permutations(items.len()).unique() {
array2d.push(perm);
}
return array2d;
}
I'm trying to make a simple example involving a vector of structs to learn Rust. All examples of vectors in the Rust literature I've found only use vectors of integers.
I want to write a function aimed at filling a vector, allowing the possibility of the element to be inserted to be changed, I can't figure out what to do. I always got a compiler error[E0308]: mismatched types on
the push method, because elem is a reference to a Point. So
push() needs a Point structure because v is a vector of Point
but if I want to modify elem, I need to pass a (mutable?) reference
What is the right thing to do?
// structure used everywhere in Rust examples
#[derive(Debug)]
struct Point {
x: i16,
y: i16
}
fn add_element(v: &mut Vec<Point>, elem: &Point) {
// modify element
elem.x = 0;
// add element
v.push(elem);
}
// this example is meant to study a vector of structs
fn main() {
// declare 2 points. By default, live on the stack
let origin = Point {x:0, y:0};
println!("origin address\t: {:p}", &origin);
let mut p1 = Point {x:1, y:1};
println!("p1 address\t: {:p}", &p1);
// declare a new vector of structs. Allocation is made in the heap
// declare mutable because we'll add elements to vector
let mut v: Vec<Point> = Vec::new();
// add points
add_element(&mut v, &origin);
add_element(&mut v, &p1);
// change p1
p1.x = 2;
p1.y = 2;
}
Let's read the error messages together:
error[E0308]: mismatched types
--> src/main.rs:10:12
|
10 | v.push(elem);
| ^^^^ expected struct `Point`, found &Point
|
= note: expected type `Point`
= note: found type `&Point`
The code is attempting to store a reference to a Point in a Vec that is declared to hold entire Points. Since Rust is a statically- and strongly- typed language, the compiler tells you that you cannot do that. The fix is to accept a Point by value:
fn add_element(v: &mut Vec<Point>, elem: Point)
This leads to the next error:
error: cannot assign to immutable field `elem.x`
--> src/main.rs:9:5
|
9 | elem.x = 0;
| ^^^^^^^^^^
You cannot change members of elem because it is not marked as mutable. Mutability of a value is a property of the binding, so let's do that:
fn add_element(v: &mut Vec<Point>, mut elem: Point)
Then change the calling of that function to adapt:
fn main() {
let origin = Point { x: 0, y: 0 };
let p1 = Point { x: 1, y: 1 };
let mut v = Vec::new();
add_element(&mut v, origin);
add_element(&mut v, p1);
}
Note that neither origin nor p1 need to be mutable because this function doesn't modify either while it owns it. It transfers ownership to add_element, which chooses to make it mutable.
but if I want to modify elem, I need to pass a (mutable?) reference
As you can see, you can simply make the elem parameter mutable when transferring the entire value to the function. Since the function owns that value, it has full control over it, including choosing to make it mutable.
This question already has an answer here:
How do I create a heterogeneous collection of objects?
(1 answer)
Closed 5 years ago.
In the context of converting a infix expression to a postfix one, using the Shunting-yard algorithm. I want to use a vector to store the output, which would store both operator and numeric type data.
#[derive(Clone, Copy, Debug, PartialEq)]
pub enum Operator {
Add,
Sub,
Mul,
Div,
}
fn main() {
let mut output: Vec<String> = Vec::new(); // create an output vector
let a = 2;
let b = Operator::Add;
let c = 3;
output.push(a.to_string());
output.push(b.to_string());
output.push(c.to_string());
}
This above code of course doesn't compile, since the to_string() method is not defined for Operator. I see two ways to fix it:
Define a to_string() method
Create a vector to store references to numbers and Operator.
I think the second is the preferred choice, though I don't know if creating a vector of references will introduce lots of complexity.
There's no need to use references; just store the numbers and Operators directly in an enum:
enum Thing {
Op(Operator),
Number(i32),
}
fn main() {
let mut output: Vec<Thing> = Vec::new();
let a = 2;
let b = Operator::Add;
let c = 3;
output.push(Thing::Number(a));
output.push(Thing::Op(b));
output.push(Thing::Number(c));
}
And then match on them when taking them out.