This question already has answers here:
Why does "can't leak private type" only apply to structs and not enums?
(1 answer)
Can I create private enum constructors?
(1 answer)
Closed 2 years ago.
In Learning Rust With Entirely Too Many Linked Lists, they show that a pub enum can't hold a private struct:
struct Node {
elem: i32,
next: List,
}
pub enum List {
Empty,
More(Box<Node>),
}
error[E0446]: private type `Node` in public interface
--> src/lib.rs:8:10
|
8 | More(Box<Node>),
| ^^^^^^^^^ can't leak private type
They also show that you can have a pub struct hold a private enum
pub struct List {
head: Link,
}
enum Link {
Empty,
More(Box<Node>),
}
Why is this?
Related
This question already has answers here:
Store a collection of heterogeneous types with generic type parameters in Rust
(1 answer)
How do I create a heterogeneous collection of objects?
(1 answer)
What is the cited problem with using generic type parameters in trait objects?
(2 answers)
Closed 2 years ago.
I am trying to push an object which implements a trait with a trait parameter into a Vec:
trait IRequest {}
trait IRequestHandler<T>
where
T: IRequest,
{
fn handle(&self, request: T);
}
pub struct CreateTodoRequest();
impl IRequest for CreateTodoRequest {}
pub struct CreateTodoRequestHandler();
impl IRequestHandler<CreateTodoRequest> for CreateTodoRequestHandler {
fn handle(&self, request: CreateTodoRequest) {}
}
fn main() {
let request = CreateTodoRequest {};
let handler = CreateTodoRequestHandler();
let mut handlers: Vec<&dyn IRequestHandler<dyn IRequest>> = Vec::new();
handlers.push(&handler);
}
I get an error:
error[E0277]: the trait bound `CreateTodoRequestHandler: IRequestHandler<dyn IRequest>` is not satisfied
--> src/main.rs:25:19
|
25 | handlers.push(&handler);
| ^^^^^^^^ the trait `IRequestHandler<dyn IRequest>` is not implemented for `CreateTodoRequestHandler`
|
= help: the following implementations were found:
<CreateTodoRequestHandler as IRequestHandler<CreateTodoRequest>>
= note: required for the cast to the object type `dyn IRequestHandler<dyn IRequest>`
When I had IRequestHandler without a parameter, I could cast it and push into the Vec. The problem only appears when the trait has a parameter.
Is it possible to cast an object to a trait with a parameter that it implements?
This question already has answers here:
Why does refactoring by extracting a method trigger a borrow checker error?
(2 answers)
Passing mutable self reference to method of owned object
(2 answers)
How to use struct self in member method closure
(4 answers)
How can I modify self in a closure called from a member function?
(1 answer)
Closed 3 years ago.
I have the structs Foo and Bar. Foo contains an array of Bar and a private method to operate on Bar:
pub struct Bar;
pub struct Foo {
bars: [Bar; 10],
}
impl Foo {
pub fn process_all(&mut self) {
for bar in self.bars.iter_mut() {
self.process_single(bar);
}
}
fn process_single(&mut self, bar: &mut Bar) {
// ...
}
}
This won't work because both self and one of its contained bars can't be borrowed at the same time.
error[E0499]: cannot borrow `*self` as mutable more than once at a time
One way of solving this in my case is an Option. I then have the ability to take ownership of the array in the function and then later giving it back to the struct after the process is done:
pub struct Bar;
pub struct Foo {
bars: Option<[Bar; 10]>,
}
impl Foo {
pub fn process_all(&mut self) {
let bars = self.bars.take().unwrap();
for bar in bars {
self.process_single(bar);
}
self.bars = Some(bars);
}
fn process_single(&mut self, bar: &mut Bar) {
// ...
}
}
This feels very hacky; is there a better way?
This question already has answers here:
Implementing Index trait to return a value that is not a reference
(2 answers)
How do I specify lifetime parameters in an associated type?
(3 answers)
Closed 3 years ago.
I would like indexing of my type to return a structure bounded with lifetime. The structure needs to contain a reference to the original type to be able to run some methods on it, like foo[index].bar().
When I try a simple approach
impl<'a> Index<usize> for Foo {
type Output = FooIndex<'a>;
fn index(&self, index: usize) -> &Self::Output {
FooIndex {
index,
foo: &self,
}
}
}
I get the following
error[E0207]: the lifetime parameter 'a is not constrained by the impl trait, self type, or predicates
Is there any way how to do it?
This question already has answers here:
Is it possible for one struct to extend an existing struct, keeping all the fields?
(5 answers)
Closed 3 years ago.
I'm trying to add new member variables to a struct in an impl block.
I'm using protoc-rust to procedurally generate Rust code from protocol buffers. In particular, it generates structs and methods for the messages defined in the protos. I need to add new members to these structs to initialize some WebAssembly::Instances off of a bytes object in the struct
The struct:
pub struct Module {
// message fields
pub module_name: ::std::string::String,
pub init_script: ::std::string::String,
pub JS_boiler_plate: ::std::string::String,
pub functions: ::protobuf::RepeatedField<Function>,
pub meta_data: ::std::string::String,
pub packager: ::std::string::String,
pub pure_wasm: bool,
pub wasm_binary: ::std::vec::Vec<u8>,
// special fields
pub unknown_fields: ::protobuf::UnknownFields,
pub cached_size: ::protobuf::CachedSize,
}
What I want to do:
impl RPC_Module::Module {
self.wasm_instance: WebAssembly::Instance;
pub fn init(&mut self) -> Result<(), &'static str> {
// Init the instance based off of wasm_binary
let self.wasm_instance = WebAssembly::Instance::new()
}
}
What I get:
Compiling wRPC v0.1.0 (/Users/swarfield/Code/wRPC-Core/w-rpc-core)
error: expected one of `async`, `const`, `crate`, `default`, `existential`, `extern`, `fn`, `pub`, `type`, `unsafe`, or `}`, found `let`
--> src/protos/mod.rs:12:5
|
11 | impl RPC_Module::Module {
| - expected one of 11 possible tokens here
12 | let self.wasm_instance: WebAssembly::Instance;
| ^^^ unexpected token
I'm trying to add new member variables to a struct in an impl block.
Rust does not allow that.
What you can do is define another struct:
struct ModuleInstance {
wasm_instance: WebAssembly::Instance,
module: RPC_Module::Module
}
.. and return it from your init function.
This question already has answers here:
Deriving a trait results in unexpected compiler error, but the manual implementation works
(2 answers)
Closed 5 years ago.
Given the following struct Foo<T> that derives Default:
#[derive(Default)]
struct Foo<T> {
bar: Option<T>,
}
Why does this compile
fn create<T>() -> Foo<T> {
Foo {
bar: Option::default(),
}
}
but this doesn't?
fn create_alt<T>() -> Foo<T> {
Foo::default()
}
In my mind they are both doing the exact same thing--it shouldn't matter if T implements Default (which is what the compiler wants me to specify) because Option<T> implements Default.
Here is a link to the Rust Playground with this example.
This is a known issue, and it's hard to fix. Issue #26925
In short, #[derive] uses incorrect bounds: it assumes that in order to implement Default for Foo<T>, T must be Default, when in reality Option<T>: Default is sufficient.
The problem with fixing it is that it's possible to have struct members of private types, and using #[derive] on a public generic struct that has private members could partially expose that private interface. For example,
trait MyTrait {}
struct MyType<T> {}
impl<T> Default for MyType<T> where T: MyTrait {}
#[derive(Default)]
pub struct PubType<T> {
member: MyType<T>,
}
If #[derive(Default)] does the right thing, you effectively have this impl block for a public type that exposes a private trait:
impl Default for PubType<T>
where T: MyTrait
{ ... }
Probably the best way to get around this right now is to avoid using #[derive] in this case and write the impl yourself.