How to handle "multiple applicable items in scope" error? - rust

I'm using the fltk-rs crate and running into the "multiple applicable items in scope" error.
fltk = "0.10.14"
use fltk::{table::*};
pub struct AssetViewer {
pub table: Table,
}
impl AssetViewer {
pub fn new(x: i32, y: i32, width: i32, height: i32) -> Self {
let mut av = AssetViewer {
table: Table::new(x,y,width-50,height,""),
};
av.table.set_rows(5);
av.table.set_cols(5);
av
}
pub fn load_file_images(&mut self, asset_paths: Vec<String>){
self.table.clear(); //<- throws multiple applicable items in scope
}
}
Gives error:
error[E0034]: multiple applicable items in scope
--> src\main.rs:18:20
|
18 | self.table.clear(); //<- throws multiple applicable items in scope
| ^^^^^ multiple `clear` found
|
= note: candidate #1 is defined in an impl of the trait `fltk::TableExt` for the type `fltk::table::Table`
= note: candidate #2 is defined in an impl of the trait `fltk::GroupExt` for the type `fltk::table::Table`
I would like to specify that I'm referencing the TableExt trait, not the GroupExt trait. How would I do this?

TLDR: Use fully qualified function name:
fltk::GroupExt::clear(&mut self.table)
Consider this simplified example:
struct Bar;
trait Foo1 {
fn foo(&self) {}
}
trait Foo2 {
fn foo(&self) {}
}
impl Foo1 for Bar {}
impl Foo2 for Bar {}
fn main() {
let a = Bar;
a.foo()
}
It will fail to compile with the following error message:
error[E0034]: multiple applicable items in scope
--> src/main.rs:16:7
|
16 | a.foo()
| ^^^ multiple `foo` found
|
Compiler will also suggest a solution:
help: disambiguate the associated function for candidate #1
|
16 | Foo1::foo(&a)
|

The compiler in this instance recommends the correct fix. The error message (as of 1.48.0) contains these help annotations:
help: disambiguate the associated function for candidate #1
|
18 | fltk::TableExt::clear(&mut self.table);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
help: disambiguate the associated function for candidate #2
|
18 | fltk::GroupExt::clear(&mut self.table);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
The full error message actually shows 5 candidates and 5 help annotations.
As an aside, another syntax for disambiguating methods is:
<Table as fltk::TableExt>::clear(&mut self.table);
Though its more verbose than the recommended syntax and its only needed in situations where the method doesn't take self and therefore can't deduce Table.

Related

Best Practices Wrapping Non-Object-Safe Traits

I have a trait Foo. This has a method which takes a generic type implementing Bar and is therefore not object safe:
trait Bar {}
trait Foo {
fn foofunc<B: Bar>(&self, b: B);
}
I want to make the trait Foo object safe. I gather the usual way to do this is to wrap it in a new, object-safe, trait (see here). Something along the lines of:
trait FooObjectSafe<B>
where B: Bar,
{
fn foofunc(&self, b: B);
}
impl<B, F> FooObjectSafe<B> for F
where B: Bar,
F: Foo,
{
fn foofunc(&self, b: B) {
Foo::foofunc(self, b)
}
}
This seems very limiting however. If there is a function use_foo which takes a generic type implementing Foo, then it cannot be used with FooObjectSafe without changing its signature (I don't want to do this as in practise these functions come from different modules and are very divorced from one another):
struct BarImpl;
impl Bar for BarImpl {}
struct FooImpl;
impl Foo for FooImpl {
fn foofunc<B: Bar>(&self, b: B) {}
}
fn main() {
let foos = [
Box::new(FooImpl{}) as Box<dyn FooObjectSafe<BarImpl>>,
Box::new(FooImpl{})
];
use_foo(foos[0]);
}
results in the error
error[E0277]: the trait bound `Box<dyn FooObjectSafe<BarImpl>>: Foo` is not satisfied
--> src/main.rs:43:13
|
43 | use_foo(foos[0]);
| ------- ^^^^^^^ the trait `Foo` is not implemented for `Box<dyn FooObjectSafe<BarImpl>>`
| |
| required by a bound introduced by this call
|
= help: the trait `Foo` is implemented for `FooImpl`
note: required by a bound in `use_foo`
--> src/main.rs:9:14
|
8 | fn use_foo<F>(foo: F)
| ------- required by a bound in this
9 | where F: Foo,
| ^^^ required by this bound in `use_foo`
For more information about this error, try `rustc --explain E0277`.
error: could not compile `playground` due to previous error
Is there a better way to do this? I suspect I'm making some architectural faux pas here, but what exactly?
Playground

BorshDeserialize gives try_from_slice error

I was exploring the "BorshDeserialize" option in Rust. and noticed the following issues when using trait bounds. Any help is appreciated
Sample code
use borsh::{BorshDeserialize, BorshSerialize};
use solana_program::pubkey::Pubkey;
use std::mem;
#[derive(BorshSerialize, BorshDeserialize, PartialEq, Debug)]
struct SampleData<'a> {
accounts: (&'a Pubkey, &'a Pubkey),
data: String,
timestamp: u64,
owner: &'a Pubkey,
}
fn main() {
println!(
"Size of SampleData is {} bytes",
mem::size_of::<SampleData>()
);
let _pub_key = Pubkey::default();
let _a = SampleData {
accounts: (&_pub_key, &_pub_key),
data: "ABCDE".to_string(),
timestamp: 1643116047,
owner: &_pub_key,
};
let _encoded_a = _a.try_to_vec().unwrap();
println!("{:?}", _encoded_a);
let _decoded_a = SampleData::try_from_slice(&_encoded_a).unwrap();
println!("decoded_a: {:?}", _decoded_a);
}
Error message
error[E0599]: the function or associated item try_from_slice exists
for struct SampleData<'_>, but its trait bounds were not satisfied
--> src/main.rs:27:34 | 6 | struct SampleData<'a> { | --------------------- | | | function or associated item try_from_slice not found for this | doesn't satisfy
SampleData<'_>: BorshDeserialize ... 27 | let _decoded_a =
SampleData::try_from_slice(&_encoded_a).unwrap(); |
^^^^^^^^^^^^^^ function or associated item cannot be called on
SampleData<'_> due to unsatisfied trait bounds | note: the
following trait bounds were not satisfied because of the requirements
of the implementation of BorshDeserialize for _:
(&Pubkey, &Pubkey): BorshDeserialize
&Pubkey: BorshDeserialize --> src/main.rs:5:26 | 5 | #[derive(BorshSerialize, BorshDeserialize, PartialEq, Debug)] | ^^^^^^^^^^^^^^^^ 6 | struct SampleData<'a> { |
^^^^^^^^^^^^^^ = help: items from traits can only be used if the
trait is implemented and in scope = note: the following trait
defines an item try_from_slice, perhaps you need to implement it:
candidate #1: BorshDeserialize = note: this error originates in the derive macro BorshDeserialize (in Nightly builds,
run with -Z macro-backtrace for more info)
For more information about this error, try rustc --explain E0599.
error: could not compile seralize due to previous error
The problem is that SampleData contains references, which isn't supported in normal Borsh deserialization. Borsh creates a new instance of your type based on a slice, but it won't be able to create references.
If you want to stick with Borsh, you should change the type to:
#[derive(BorshSerialize, BorshDeserialize, PartialEq, Debug)]
struct SampleData {
accounts: (Pubkey, Pubkey),
data: String,
timestamp: u64,
owner: Pubkey,
}

Error when trying to implement a function declared in a supertrait

I'm trying to implement a trait that has a supertrait, like so:
trait A {
fn do_a(&self);
}
trait B: A {
fn do_b(&self);
}
struct S {}
impl B for S {
fn do_a(&self) {}
fn do_b(&self) {}
}
When I run cargo build I get these compiler errors:
error[E0407]: method `do_a` is not a member of trait `B`
--> src/example.rs:12:5
|
12 | fn do_a(&self) {}
| ^^^^^^^^^^^^^^^^^ not a member of trait `B`
error[E0277]: the trait bound `example::S: example::A` is not satisfied
--> src/example.rs:11:6
|
5 | trait B: A {
| - required by this bound in `example::B`
...
11 | impl B for S {
| ^ the trait `example::A` is not implemented for `example::S`
I keep re-reading about supertraits, but I'm having trouble understanding this error.
The first error seems to contradict what trait B: A is telling the program to do.
The second error seems to contradict that the implementation of do_a(&self) {} satisfies A.
What am I missing here? Is my mental model wrong, or is my code missing some necessary boilerplate, or both?
I believe that the syntax is more about bounding the type (e.g. a type T that implements B must necessarily implement A) than inheritance in the object-oriented sense. If you write out the impls separately it compiles fine:
trait A {
fn do_a(&self);
}
trait B: A {
fn do_b(&self);
}
struct S {}
impl A for S {
fn do_a(&self) {}
}
impl B for S {
fn do_b(&self) {}
}
Playground
N.B. that if you remove the impl for A the code no longer compiles, the constraint that an impl of B must also impl A is no longer satisfied.

Function overloading trick - compiler cannot choose which function to call

Rust has no function overloading: you cannot define multiple functions with the same name but with different arguments.
However, I discovered the following trick which makes it look like there is function overloading. Notice how in main() I can call example.apply(...) with different types:
struct Example;
trait Apply<T, R> {
fn apply(&self, value: T) -> R;
}
impl Apply<i32, i32> for Example {
fn apply(&self, value: i32) -> i32 {
value * 2
}
}
impl Apply<&str, String> for Example {
fn apply(&self, value: &str) -> String {
format!("Hello, {}", value)
}
}
fn main() {
let example = Example;
// Looks like function overloading!
let one = example.apply(12);
let two = example.apply("World");
println!("{}", one);
println!("{}", two);
}
Now I would like to make two different versions of the Apply trait: one for values which are Copy and one for values which are not Copy:
struct Example;
struct NotCopy(i32);
// For types which are Copy
trait ApplyCopy<T: Copy, R> {
fn apply(&self, value: T) -> R;
}
// For types which are not Copy
trait ApplyRef<T, R> {
fn apply(&self, value: &T) -> R;
}
impl ApplyCopy<i32, i32> for Example {
fn apply(&self, value: i32) -> i32 {
value * 2
}
}
impl ApplyRef<NotCopy, String> for Example {
fn apply(&self, value: &NotCopy) -> String {
format!("NotCopy({})", value.0)
}
}
However, when I try to use this I get errors:
fn main() {
let example = Example;
let one = example.apply(12); // Error: multiple `apply` found
let two = example.apply(&NotCopy(34)); // Error: multiple `apply` found
println!("{}", one);
println!("{}", two);
}
One of the error messages:
error[E0034]: multiple applicable items in scope
--> src/main.rs:30:23
|
30 | let one = example.apply(12); // Error: multiple `apply` found
| ^^^^^ multiple `apply` found
|
note: candidate #1 is defined in an impl of the trait `ApplyCopy` for the type `Example`
--> src/main.rs:16:5
|
16 | fn apply(&self, value: i32) -> i32 {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
note: candidate #2 is defined in an impl of the trait `ApplyRef` for the type `Example`
--> src/main.rs:22:5
|
22 | fn apply(&self, value: &NotCopy) -> String {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
help: disambiguate the associated function for candidate #1
|
30 | let one = ApplyCopy::apply(&example, 12); // Error: multiple `apply` found
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
help: disambiguate the associated function for candidate #2
|
30 | let one = ApplyRef::apply(&example, 12); // Error: multiple `apply` found
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
The compiler complains that it does not know which apply function to call. I expected it to be able to make a choice: an i32 is not a reference and is Copy, so the apply of trait ApplyCopy is the only one that can be called, and &NotCopy(34) is a reference and since NotCopy is not Copy, only the apply of ApplyRef can be called.
Is this a limitation of the Rust compiler or am I missing something?
Is this a limitation of the Rust compiler or am I missing something?
While there is compiler magic & special casing around them, at a fundamental level a reference is still a proper type, so any T could be an &Q under the covers, and reference types can implement traits.
While NotCopy is not Copy, &NotCopy is Copy. So &NotCopy matches both cases.

Is there a way to tell the compiler that nobody will implement a trait for a reference to a generic type?

Here is toy code that demonstrates the problem:
trait Foo {}
trait Boo<T> {
fn f() -> T;
}
impl<T> Boo<T> for i32
where
T: Foo,
{
fn f() -> T {
unimplemented!();
}
}
impl<'a, T> Boo<&'a T> for i32
where
T: Foo,
{
fn f() -> T {
unimplemented!();
}
}
I want to have two generic implementations of trait Boo, but it doesn't compile:
error[E0119]: conflicting implementations of trait `Boo<&_>` for type `i32`:
--> src/main.rs:16:1
|
7 | / impl<T> Boo<T> for i32
8 | | where
9 | | T: Foo,
10 | | {
... |
13 | | }
14 | | }
| |_- first implementation here
15 |
16 | / impl<'a, T> Boo<&'a T> for i32
17 | | where
18 | | T: Foo,
19 | | {
... |
22 | | }
23 | | }
| |_^ conflicting implementation for `i32`
|
= note: downstream crates may implement trait `Foo` for type `&_`
I do not plan to make this part of functionality to other crates. I tried:
moving this code to binary crate that obviously can not be used from other crates
moving this to a private mod
marking the trait as pub(crate)
all with no success.
Is there anyway to give the compiler a hint that it should not care that anybody will implement Foo for any reference?
Maybe my toy example is not the best, so here is the real code.
It's used for integration with the C part of my program, so it's a little
complicated.
impl<T: MyTrait> MyFrom<Option<T>> for *mut c_void {
fn my_from(x: Option<T>) -> Self {
match x {
Some(x) => <T>::alloc_heap_for(x),
None => ptr::null_mut(),
}
}
}
impl<'a, T: MyTrait> MyFrom<Option<&'a T>> for *mut c_void {
fn my_from(x: Option<&'a T>) -> Self {
match x {
Some(x) => x as *const T as *mut c_void,
None => ptr::null_mut(),
}
}
}
The conflict here doesn't have anything to do with the reference-ness of the latter implementation. The issue is that, in the first implementation, T can be any type, including reference types. Suppose you make the following function call:
let x: i32 = 10;
let result: &u8 = x.f();
At this point, the type resolver needs to figure out what function is being called. It finds a conflicting implementation:
impl Boo<&u8> for i32 via Boo<T> (T == &u8),
impl Boo<&u8> for i32 via Boo<&T> (T == u8),
You'd have exactly the same issue if you used a concrete type in the latter implementation:
// This will fail to compile
impl<T> Boo<T> for i32 { ... }
impl Boo<String> for i32 { ... }
This conflict means that the compiler can't allow these two implementations to coexist.
The specific thing you're looking to do here is called "specialization"; it refers to a proposal for a set of rules that says that overlapping implementations like this are allowed to exist if one of them is unambiguously more "specific" than the other, in which case the compiler will pick the more specific implementation. This is tracked as RFC #1210.

Resources