Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cannot coerce dyn AsRef #61977

Open
clarfonthey opened this issue Jun 19, 2019 · 4 comments
Open

Cannot coerce dyn AsRef #61977

clarfonthey opened this issue Jun 19, 2019 · 4 comments
Labels
A-coercions Area: implicit and explicit `expr as Type` coercions A-diagnostics Area: Messages for errors, warnings, and lints C-bug Category: This is a bug. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. T-lang Relevant to the language team, which will review and decide on the PR/issue.

Comments

@clarfonthey
Copy link
Contributor

clarfonthey commented Jun 19, 2019

Really weird example:

use std::path::Path;
fn main() {
    let boxed_path: Box<Path> = Path::new("test").to_path_buf().into_boxed_path();
    let as_ref_works: &Path = boxed_path.as_ref();
    //let lots_of_question_marks: Box<dyn AsRef<Path>> = boxed_path;
}

Uncommenting the last line gives:

error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
 --> src/main.rs:5:56
  |
5 |     let lots_of_question_marks: Box<dyn AsRef<Path>> = boxed_path;
  |                                                        ^^^^^^^^^^ borrow the `Path` instead
  |
  = help: within `std::path::Path`, the trait `std::marker::Sized` is not implemented for `[u8]`
  = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
  = note: required because it appears within the type `std::path::Path`
  = note: required for the cast to the object type `dyn std::convert::AsRef<std::path::Path>`

error: aborting due to previous error

I genuinely don't know what's going on here, but this seems to be a bug in both coercion and diagnostics.

This is on the latest nightly.

@jonas-schievink jonas-schievink added A-coercions Area: implicit and explicit `expr as Type` coercions A-diagnostics Area: Messages for errors, warnings, and lints C-bug Category: This is a bug. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. T-lang Relevant to the language team, which will review and decide on the PR/issue. labels Jun 19, 2019
@clarfonthey
Copy link
Contributor Author

clarfonthey commented Jun 19, 2019

Larger code example to show context:

let temp_dir: Box<dyn AsRef<Path>> = match matches.value_of_os("cache-dir") {
    Some(c) => Path::new(c).to_path_buf().into_boxed_path(),
    None => Box::new(TempDir::new("temp")?)
};

This is code that parses a clap argument and either a) uses the argument verbatim or b) loads a TempDir and uses that instead. In this case, it makes sense to use dyn AsRef<Path> because I want the TempDir to be destroyed at the end of execution, while also allowing a simple path to be used instead. I could store both a &Path and a TempDir but I figured I'd try my hand at this code to make things a bit easier.

Turns out that it isn't much easier, if the compiler breaks.

@kryptan
Copy link
Contributor

kryptan commented Mar 24, 2020

The issue here is that you cannot put unsized objects behind dyn Trait. For example the following fails to compile with the same error:

let _: &dyn std::fmt::Debug = "a";

It is not clear to me what is the reason for this.

@clarfonthey
Copy link
Contributor Author

clarfonthey commented Mar 26, 2020

I believe that it's a strict limitation on the size of fat pointers. Unsized types require extra information to encode what their size is, and ditto for polymorphism. To get around it, you have to take a reference to the reference to the unsized type, which would be a thin pointer, and that can have the polymorphic info attached.

That in particular makes a lot of sense from an implementation perspective, but it's very, very confusing from a user perspective. I'm not 100% sure what to do about it.

Perhaps discussion of this may be good to add to rfcs#2580.

@QuineDot
Copy link

See also #88141

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-coercions Area: implicit and explicit `expr as Type` coercions A-diagnostics Area: Messages for errors, warnings, and lints C-bug Category: This is a bug. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. T-lang Relevant to the language team, which will review and decide on the PR/issue.
Projects
None yet
Development

No branches or pull requests

4 participants