How do I access underlying object in gtk::glib::Value? - rust

I have produced a simple gtk GUI with glade. It merely has a spin button in an Application window. I am having trouble accessing the value of the spin button when using builder.connect_signals. My code is:
use gtk::prelude::*;
use gtk::glib;
use gtk::{Application, Builder, ApplicationWindow, SpinButton};
fn main() {
let app = Application::builder().build();
app.connect_activate(build_gui);
app.run();
}
fn build_gui(app: &Application){
let gl = include_str!("temp.glade");
let builder = Builder::from_string(gl);
let win: ApplicationWindow = builder.object("win").expect("Failed to get ApplicationWindow");
let spinner: SpinButton = builder.object("spin").expect("Failed to get ComboBoxText");
win.set_application(Some(app));
builder.connect_signals(|_builder, handler| {
match handler {
"test" => Box::new(test),
_ => Box::new(|_| {None})
}
});
win.show_all();
}
fn test(x: &[glib::Value]) -> Option<glib::Value> {
println!("Value is {:?}", x);
None
}
My glade file has added test as the handler to the value-changed signal.
If I replace the builder.connect_signals statement with:
spinner.connect_value_changed(|btn| {println!("value is {}", btn.value())});
it works as expected. But when run as above the test handler function prints:
Value is [(GtkSpinButton) ((GtkSpinButton*) 0x55e51d816320)] so I know a GtkSpinButton is in there somewhere but I do not know how to access it. If I try to print println!("Value is {:?}", x.value()); i get the error:
cargo build (in directory: /home/maindesktop/Documents/Projects/Rust/StockChart/src)
Compiling stock_chart v0.1.0 (/home/maindesktop/Documents/Projects/Rust/StockChart)
error[E0599]: the method `value` exists for reference `&[gtk::glib::Value]`, but its trait bounds were not satisfied
--> src/main.rs:32:30
|
32 | println!("Value is {:?}", x.value());
| ^^^^^ method cannot be called on `&[gtk::glib::Value]` due to unsatisfied trait bounds
|
= note: the following trait bounds were not satisfied:
`[gtk::glib::Value]: Sized`
which is required by `[gtk::glib::Value]: gtk::prelude::AdjustmentExt`
`[gtk::glib::Value]: IsA<Adjustment>`
which is required by `[gtk::glib::Value]: gtk::prelude::AdjustmentExt`
`[gtk::glib::Value]: Sized`
which is required by `[gtk::glib::Value]: gtk::prelude::CellRendererProgressExt`
`[gtk::glib::Value]: IsA<CellRendererProgress>`
which is required by `[gtk::glib::Value]: gtk::prelude::CellRendererProgressExt`
`[gtk::glib::Value]: Sized`
which is required by `[gtk::glib::Value]: gtk::prelude::LevelBarExt`
`[gtk::glib::Value]: IsA<gtk::LevelBar>`
which is required by `[gtk::glib::Value]: gtk::prelude::LevelBarExt`
`[gtk::glib::Value]: Sized`
which is required by `[gtk::glib::Value]: gtk::prelude::RangeExt`
`[gtk::glib::Value]: IsA<gtk::Range>`
which is required by `[gtk::glib::Value]: gtk::prelude::RangeExt`
`[gtk::glib::Value]: Sized`
which is required by `[gtk::glib::Value]: gtk::prelude::ScaleButtonExt`
`[gtk::glib::Value]: IsA<ScaleButton>`
which is required by `[gtk::glib::Value]: gtk::prelude::ScaleButtonExt`
`[gtk::glib::Value]: Sized`
which is required by `[gtk::glib::Value]: gtk::prelude::SpinButtonExt`
`[gtk::glib::Value]: IsA<gtk::SpinButton>`
which is required by `[gtk::glib::Value]: gtk::prelude::SpinButtonExt`
`[gtk::glib::Value]: Sized`
which is required by `[gtk::glib::Value]: gtk::prelude::TreeModelExt`
`[gtk::glib::Value]: IsA<TreeModel>`
which is required by `[gtk::glib::Value]: gtk::prelude::TreeModelExt`
`&[gtk::glib::Value]: IsA<Adjustment>`
which is required by `&[gtk::glib::Value]: gtk::prelude::AdjustmentExt`
`&[gtk::glib::Value]: IsA<CellRendererProgress>`
which is required by `&[gtk::glib::Value]: gtk::prelude::CellRendererProgressExt`
`&[gtk::glib::Value]: IsA<gtk::LevelBar>`
which is required by `&[gtk::glib::Value]: gtk::prelude::LevelBarExt`
`&[gtk::glib::Value]: IsA<gtk::Range>`
which is required by `&[gtk::glib::Value]: gtk::prelude::RangeExt`
`&[gtk::glib::Value]: IsA<ScaleButton>`
which is required by `&[gtk::glib::Value]: gtk::prelude::ScaleButtonExt`
`&[gtk::glib::Value]: IsA<gtk::SpinButton>`
which is required by `&[gtk::glib::Value]: gtk::prelude::SpinButtonExt`
`&[gtk::glib::Value]: IsA<TreeModel>`
which is required by `&[gtk::glib::Value]: gtk::prelude::TreeModelExt`
For more information about this error, try `rustc --explain E0599`.
error: could not compile `stock_chart` due to previous error
Compilation failed.
I have tried to cast x to SpinButtonExt and SpinButton but it won't let me. How do I get the SpinButton object from the glib::Value argument?

Related

"this trait cannot be made into an object because it requires `Self: Sized`", except it has Sized

Here's the error message:
error[E0038]: the trait `room::RoomInterface` cannot be made into an object
--> src\permanent\registry\mod.rs:12:33
|
12 | pub fn load(id : String) -> Result<Box<dyn RoomInterface>, String>{
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `room::RoomInterface` cannot be made into an object
|
note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
--> src\permanent\rooms\mod.rs:36:31
|
36 | pub trait RoomInterface : Copy + Sized {
| ------------- ^^^^ ^^^^^ ...because it requires `Self: Sized`
| | |
| | ...because it requires `Self: Sized`
| this trait cannot be made into an object...
For more information about this error, try `rustc --explain E0038`.
It says that to use the trait as an object, it requires Sized. Except that Sized is right there, in the declaration of the trait! It literally points to the word "Sized" and tells me I need to have "Sized". What's going on?
The problem is opposite to what you think: The problem is that you require Self: Sized but only traits which do not require Self: Sized can be made into an object.
As the error message states you must remove both bounds for Copy and Sized for RoomInterface:
pub trait RoomInterface {
The article linked in the error message is a great resource, I recommend reading it:
https://doc.rust-lang.org/reference/items/traits.html#object-safety
Also this discussion might be interesting:
https://users.rust-lang.org/t/trait-objects-and-the-sized-trait/14410/2

How to implement Extend trait for generic

How do I implement the Extend trait for my type?
error[E0277]: the trait bound `std::vec::Vec<types::types::NotificationEvent>: std::iter::Extend<<impl futures::TryStream as futures::TryStream>::Ok>` is not satisfied
--> src/lib.rs:318:64
|
318 | let result: Result<Vec<NotificationEvent>, _> = stream.try_collect().await;
| ^^^^^^^^^^^ the trait `std::iter::Extend<<impl futures::TryStream as futures::TryStream>::Ok>` is not implemented for `std::vec::Vec<types::types::NotificationEvent>`
|
= help: the following implementations were found:
<std::vec::Vec<T> as std::iter::Extend<&'a T>>
<std::vec::Vec<T> as std::iter::Extend<T>>
Isn't the Extend trait already implemented for Vec?

Vec of objects implementing generic trait [duplicate]

This question already has answers here:
How can I have a collection of objects that differ by their associated type?
(3 answers)
Vector of objects belonging to a trait
(3 answers)
Closed 4 years ago.
I am building a command-line application. I have the following trait:
trait ValidatedCommand {
type Output;
fn run() -> Result<Self::Output, std::io::Error>;
}
and I have the following two implementations for it:
struct First;
impl ValidatedCommand for First {
type Output = i32;
fn run() -> Result<i32, std::io::Error> {
Ok(1)
}
}
impl First {
fn new() -> First {
First {}
}
}
struct Second;
impl ValidatedCommand for Second {
type Output = String;
fn run() -> Result<String, std::io::Error> {
Ok(String::from("hello"))
}
}
impl Second {
fn new() -> Second {
Second {}
}
}
Both structs implement the trait, one returning a String and the other an i32.
I'm trying to create a Vec of that trait, but I'm not sure how to go about it. I tried the following:
fn main() {
let commands: Vec<dyn ValidatedCommand> = vec![First::new(), Second::new()];
playground.
which errors with
error[E0191]: the value of the associated type `Output` (from the trait `ValidatedCommand`) must be specified
--> src/main.rs:33:23
|
2 | type Output;
| ------------ `Output` defined here
...
33 | let commands: Vec<dyn ValidatedCommand> = vec![First::new(), Second::new()];
| ^^^^^^^^^^^^^^^^^^^^ associated type `Output` must be specified
error[E0277]: the size for values of type `dyn ValidatedCommand` cannot be known at compilation time
--> src/main.rs:33:19
|
33 | let commands: Vec<dyn ValidatedCommand> = vec![First::new(), Second::new()];
| ^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
|
= help: the trait `std::marker::Sized` is not implemented for `dyn ValidatedCommand`
= note: to learn more, visit <https://doc.rust-lang.org/book/second-edition/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
= note: required by `std::vec::Vec`
error[E0038]: the trait `ValidatedCommand` cannot be made into an object
--> src/main.rs:33:19
|
33 | let commands: Vec<dyn ValidatedCommand> = vec![First::new(), Second::new()];
| ^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `ValidatedCommand` cannot be made into an object
|
= note: method `run` has no receiver
error[E0308]: mismatched types
--> src/main.rs:33:52
|
33 | let commands: Vec<dyn ValidatedCommand> = vec![First::new(), Second::new()];
| ^^^^^^^^^^^^ expected trait ValidatedCommand, found struct `First`
|
= note: expected type `dyn ValidatedCommand`
found type `First`
error[E0277]: the size for values of type `dyn ValidatedCommand` cannot be known at compilation time
--> src/main.rs:33:47
|
33 | let commands: Vec<dyn ValidatedCommand> = vec![First::new(), Second::new()];
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
|
= help: the trait `std::marker::Sized` is not implemented for `dyn ValidatedCommand`
= note: to learn more, visit <https://doc.rust-lang.org/book/second-edition/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
= note: required by `std::slice::<impl [T]>::into_vec`
= note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
error[E0277]: the size for values of type `dyn ValidatedCommand` cannot be known at compilation time
--> src/main.rs:33:47
|
33 | let commands: Vec<dyn ValidatedCommand> = vec![First::new(), Second::new()];
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
|
= help: the trait `std::marker::Sized` is not implemented for `dyn ValidatedCommand`
= note: to learn more, visit <https://doc.rust-lang.org/book/second-edition/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
= note: slice and array elements must have `Sized` type
= note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
error[E0038]: the trait `ValidatedCommand` cannot be made into an object
--> src/main.rs:33:47
|
33 | let commands: Vec<dyn ValidatedCommand> = vec![First::new(), Second::new()];
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `ValidatedCommand` cannot be made into an object
|
= note: method `run` has no receiver
= note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
error[E0277]: the size for values of type `dyn ValidatedCommand` cannot be known at compilation time
--> src/main.rs:33:47
|
33 | let commands: Vec<dyn ValidatedCommand> = vec![First::new(), Second::new()];
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
|
= help: the trait `std::marker::Sized` is not implemented for `dyn ValidatedCommand`
= note: to learn more, visit <https://doc.rust-lang.org/book/second-edition/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
= note: required by `std::vec::Vec`
= note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
error[E0038]: the trait `ValidatedCommand` cannot be made into an object
--> src/main.rs:33:47
|
33 | let commands: Vec<dyn ValidatedCommand> = vec![First::new(), Second::new()];
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `ValidatedCommand` cannot be made into an object
|
= note: method `run` has no receiver
= note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
I am thinking that maybe there is a way to make use of the associated type, but I have no idea how I might go about it.
Is there a way to get this vector creation to compile?

A trait with a Sized supertrait still has the error "std::marker::Sized is not satisfied" [duplicate]

This question already has answers here:
Vector of objects belonging to a trait
(3 answers)
Closed 4 years ago.
I have the following code:
use std::collections::HashMap;
trait T: Sized {}
struct A;
impl T for A {}
fn main() {
let h: HashMap<String, T>;
}
But the compiler complains:
error[E0277]: the trait bound `T: std::marker::Sized` is not satisfied
--> src\main.rs:10:12
|
10 | let h: HashMap<String, T>;
| ^^^^^^^^^^^^^^^^^^ `T` does not have a constant size known at compile-time
|
= help: the trait `std::marker::Sized` is not implemented for `T`
= note: required by `std::collections::HashMap`
error[E0038]: the trait `T` cannot be made into an object
--> src\main.rs:10:12
|
10 | let h: HashMap<String, T>;
| ^^^^^^^^^^^^^^^^^^ the trait `T` cannot be made into an object
|
= note: the trait cannot require that `Self : Sized`
I don't understand the error messages, because I've marked my trait T as Sized. Am I missing something?
because I've marked my trait T as Sized
No, you haven't. You've said that any type that implements T must be Sized. The trait itself is still unsized. You either need a trait object (e.g. Box<T>) or some kind of generic (which you cannot do in this context).

The trait bound is not satisfied in Rust

I'm trying to write a Tic Tac Toe game in Rust, but this function for changing a field doesn't work and I don't know what's wrong with it:
fn change_field(mut table: [char; 9], field: i32, player: char) -> bool {
if field > 0 && field < 10 {
if table[field - 1] == ' ' {
table[field - 1] = player;
return true;
} else {
println!("That field isn't empty!");
}
} else {
println!("That field doesn't exist!");
}
return false;
}
I'm getting these errors:
src/main.rs:16:12: 16:26 error: the trait bound `[char]: std::ops::Index<i32>` is not satisfied [E0277]
src/main.rs:16 if table[field-1] == ' ' {
^~~~~~~~~~~~~~
src/main.rs:16:12: 16:26 help: run `rustc --explain E0277` to see a detailed explanation
src/main.rs:16:12: 16:26 note: slice indices are of type `usize`
src/main.rs:17:13: 17:27 error: the trait bound `[char]: std::ops::Index<i32>` is not satisfied [E0277]
src/main.rs:17 table[field-1] = player;
^~~~~~~~~~~~~~
src/main.rs:17:13: 17:27 help: run `rustc --explain E0277` to see a detailed explanation
src/main.rs:17:13: 17:27 note: slice indices are of type `usize`
src/main.rs:17:13: 17:27 error: the trait bound `[char]: std::ops::IndexMut<i32>` is not satisfied [E0277]
src/main.rs:17 table[field-1] = player;
^~~~~~~~~~~~~~
In later versions of Rust, I get these errors:
error[E0277]: the trait bound `i32: std::slice::SliceIndex<[char]>` is not satisfied
--> src/main.rs:3:12
|
3 | if table[field - 1] == ' ' {
| ^^^^^^^^^^^^^^^^ slice indices are of type `usize` or ranges of `usize`
|
= help: the trait `std::slice::SliceIndex<[char]>` is not implemented for `i32`
= note: required because of the requirements on the impl of `std::ops::Index<i32>` for `[char]`
error[E0277]: the trait bound `i32: std::slice::SliceIndex<[char]>` is not satisfied
--> src/main.rs:4:13
|
4 | table[field - 1] = player;
| ^^^^^^^^^^^^^^^^ slice indices are of type `usize` or ranges of `usize`
|
= help: the trait `std::slice::SliceIndex<[char]>` is not implemented for `i32`
= note: required because of the requirements on the impl of `std::ops::Index<i32>` for `[char]`
This is my first project in Rust so I don't have much experience with it. I tried to change the field to u32 too.
The reason is given to you in the notes:
note: slice indices are of type `usize`
slice indices are of type `usize` or ranges of `usize`
You need to cast the i32 value to usize, for example:
table[(field - 1) as usize]
Alternatively, consider using usize as the type of the field variable, if it makes sense in your application.

Resources