Examples where 2018 feature caused confusion?


#1

I’ve been thinking that it would be good to improve the hints/tips that the compiler offers to target the 2018 edition features directly. As a simple example, if one writes:

use foo::bar;

where foo is a global module, then the compiler should suggest use crate::foo::bar as a replacement.

On a more complex note, there have definitely been times when match default bindings can surprise people – e.g., you end up with a reference but don’t expect it. I have some thoughts about how to address that but it would be really helpful to have examples of code that didn’t compile where you had to scratch your head a bit. I assume there may be other features leading to surprises of this kind.

So I am starting this thread to request examples of code snippets where you think an improved error would’ve helped – ideally, with some notes on what you confused you specifically (if it is not obvious) or a suggestion you think would’ve helped.


#2

I’ve got this code snippet:

//#1
trait S {
    
}

trait R<T> where T: S + Send + Clone {
    
}

fn main() {
    let a : Box<dyn (S + Send)>;
}

the error is:

error: chained comparison operators require parentheses
  --> src/main.rs:10:16
   |
10 |     let a : Box<dyn (S + Send)>;
   |                ^^^^^^^^^^^^^^^^^
   |
   = help: use `::<...>` instead of `<...>` if you meant to specify type arguments
   = help: or use `(...)` if you meant to specify fn arguments

error: expected one of `(`, `)`, `::`, or `<`, found `+`
  --> src/main.rs:10:24
   |
10 |     let a : Box<dyn (S + Send)>;
   |         -              ^ expected one of `(`, `)`, `::`, or `<` here
   |         |
   |         while parsing the type for `a`

and

// #2
trait S {
    
}

trait R<T> where T: S + Send + Clone {
    
}

fn main() {
    let a : Box<(dyn S) + Send>;
}

the error is:

error[E0178]: expected a path on the left-hand side of `+`, not `(dyn S)`
  --> src/main.rs:10:17
   |
10 |     let a : Box<(dyn S) + Send>;
   |                 ^^^^^^^^^^^^^^ expected a path

error: aborting due to previous error

I think maybe one of these two is actually correct, but i’m not sure which one.


#3

+ has lower priority in dyn Trait as https://github.com/rust-lang/rust/pull/45294 stated.

#![feature(rust_2018_preview)]
trait S {
    
}

trait R<T> where T: S + Send + Clone {
    
}

fn main() {
    let a : Box<dyn S + Send>;
}

http://play.rust-lang.org/?gist=b56026ac345420f7656a340efd07260f&version=nightly&mode=debug&edition=2018


#4

(I’m on PTO this week, but here’s a note to remind myself: we should look at tweaking the error messages around a case like this:

fn foo(
    x: impl IntoIterator<Item = Display>
)

In particular, I think we should now suggest writing either dyn Display or impl Display. We opted not to make this a hard error but we can still change how we report Sized errors for dyn trait objects.


#5

Also a link to this thread Lived Experiences: Strange match ergonomics which I’ve not had time to read deeply but which obviously seems relevant =)


#6

impl IntoIterator<Item: Display> perhaps will be the most idiomatic suggestion.