Jamzy01
Jamzy01

Reputation: 327

Rust trait method with default implementation self type is not what is expected

So I have this FileSystem trait in rust

pub trait FileSystem: Debug + Send + Sync

And in that trait I have this method here with a default implementation:

fn location_with_sub_path(&self, sub_path: &[&str]) -> FileSystemLocation {
    FileSystemLocation::new(
        Arc::new(self),
        sub_path
            .into_iter()
            .map(|sub_path_component| sub_path_component.to_string())
            .collect()
    )
}

But as you can see here, this method gives an error

error[E0277]: the trait bound `&Self: FileSystem` is not satisfied
  --> src\file_system_location\file_system\mod.rs:52:13
   |
52 |             Arc::new(self),
   |             ^^^^^^^^^^^^^^ the trait `FileSystem` is not implemented for `&Self`
   |
   = help: the following other types implement trait `FileSystem`:
             LocalFileSystem
             VirtualFileSystem
   = note: required for the cast from `Arc<&Self>` to `Arc<(dyn FileSystem + 'static)>`

The error states that the self type does not implement FileSystem. FileSystemLocation's constructor takes an Arc<dyn FileSystem>, in other words an arc with any object that implements FileSystem within.

pub fn new(file_system: Arc<dyn FileSystem>, sub_path: Vec<String>) -> Self {
    Self {
        file_system,
        sub_path,
    }
}

But considering that my default implementation for the FileSystem trait is for obvious reasons, only ever going to exist on data types that implement FileSystem, I am unsure why rust cannot assume this and compile the code as usual.

I have learnt to realize that almost all of the time, the rust compiler is correct, but clearly I am missing something as I am unsure why this won't compile.

Here is a minimal reproducible example of the issue I am facing: https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=6efc6a1619c6effa37af7991c2a8cc29

Upvotes: 0

Views: 452

Answers (1)

BallpointBen
BallpointBen

Reputation: 13750

I think the error message might be a bit misleading — almost surely you want an Arc<Self> and not an Arc<&Self>? When passing &self, if clone doesn't exist on Self then self.clone() just clones the reference through its Copy implementation. What you probably want is to pass either arc_self: Arc<Self> as the first argument to location_with_sub_path and then Arc::clone(&arc_self), or pass self instead of &self and make sure it can be cloned.

Upvotes: 0

Related Questions