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

Extend E0308 description with dynamic dispatch example #70071

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 47 additions & 0 deletions src/librustc_error_codes/error_codes/E0308.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,50 @@ variable. It can occur for several cases, the most common of which is a
mismatch in the expected type that the compiler inferred for a variable's
initializing expression, and the actual type explicitly assigned to the
variable.

One possible scenario is that we have a trait and want to use multiple
implementors conditionally via dynamic dispatch. E. g.

```compile_fail,E0308
use std::{io, fs, env};

let arg = env::args().nth(1);

let mut input = if arg == "-" {
std::io::stdin()
} else {
fs::File::open(arg)?
// expected struct `std::io::Stdin`, found struct `std::fs::File
};
// - if and else have incompatible types

Ok::<(), io::Error>(())
```

In many cases, the trait methods use self by (mutable) reference. Thus we can
create a `dyn` reference, but we need two variables for the actual objects,
because as shown above, one variable can only hold one type of object. We must
still declare the variables outside of the `if` to make sure they live long
enough.

Note that this relies on the fact that while one needs to initialize a value to
use it, Rust is clever enough to allow unused values to stay uninitialized:

```no_run
use std::{io, fs, env};

let arg = env::args().nth(1).unwrap_or("-".into());

// We only declare, not initialize the values.
let (mut stdin, mut file);

// We need to ascribe the type here to select dynamic dispatch.
let input: &mut dyn io::Read = if arg == "-" {
stdin = std::io::stdin();
&mut stdin
} else {
file = fs::File::open(arg)?;
&mut file
};
Ok::<(), io::Error>(())
```
188 changes: 188 additions & 0 deletions src/test/ui/json-bom-plus-crlf-multifile.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,53 @@ variable. It can occur for several cases, the most common of which is a
mismatch in the expected type that the compiler inferred for a variable's
initializing expression, and the actual type explicitly assigned to the
variable.

One possible scenario is that we have a trait and want to use multiple
implementors conditionally via dynamic dispatch. E. g.

```compile_fail,E0308
use std::{io, fs, env};

let arg = env::args().nth(1);

let mut input = if arg == \"-\" {
std::io::stdin()
} else {
fs::File::open(arg)?
// expected struct `std::io::Stdin`, found struct `std::fs::File
};
// - if and else have incompatible types

Ok::<(), io::Error>(())
```

In many cases, the trait methods use self by (mutable) reference. Thus we can
create a `dyn` reference, but we need two variables for the actual objects,
because as shown above, one variable can only hold one type of object. We must
still declare the variables outside of the `if` to make sure they live long
enough.

Note that this relies on the fact that while one needs to initialize a value to
use it, Rust is clever enough to allow unused values to stay uninitialized:

```no_run
use std::{io, fs, env};

let arg = env::args().nth(1).unwrap_or(\"-\".into());

// We only declare, not initialize the values.
let (mut stdin, mut file);

// We need to ascribe the type here to select dynamic dispatch.
let input: &mut dyn io::Read = if arg == \"-\" {
stdin = std::io::stdin();
&mut stdin
} else {
file = fs::File::open(arg)?;
&mut file
};
Ok::<(), io::Error>(())
```
"},"level":"error","spans":[{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":621,"byte_end":622,"line_start":17,"line_end":17,"column_start":22,"column_end":23,"is_primary":true,"text":[{"text":" let s : String = 1; // Error in the middle of line.","highlight_start":22,"highlight_end":23}],"label":"expected struct `std::string::String`, found integer","suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":612,"byte_end":618,"line_start":17,"line_end":17,"column_start":13,"column_end":19,"is_primary":false,"text":[{"text":" let s : String = 1; // Error in the middle of line.","highlight_start":13,"highlight_end":19}],"label":"expected due to this","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"try using a conversion method","code":null,"level":"help","spans":[{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":621,"byte_end":622,"line_start":17,"line_end":17,"column_start":22,"column_end":23,"is_primary":true,"text":[{"text":" let s : String = 1; // Error in the middle of line.","highlight_start":22,"highlight_end":23}],"label":null,"suggested_replacement":"1.to_string()","suggestion_applicability":"MaybeIncorrect","expansion":null}],"children":[],"rendered":null}],"rendered":"$DIR/json-bom-plus-crlf-multifile-aux.rs:17:22: error[E0308]: mismatched types
"}
{"message":"mismatched types","code":{"code":"E0308","explanation":"Expected type did not match the received type.
Expand All @@ -38,6 +85,53 @@ variable. It can occur for several cases, the most common of which is a
mismatch in the expected type that the compiler inferred for a variable's
initializing expression, and the actual type explicitly assigned to the
variable.

One possible scenario is that we have a trait and want to use multiple
implementors conditionally via dynamic dispatch. E. g.

```compile_fail,E0308
use std::{io, fs, env};

let arg = env::args().nth(1);

let mut input = if arg == \"-\" {
std::io::stdin()
} else {
fs::File::open(arg)?
// expected struct `std::io::Stdin`, found struct `std::fs::File
};
// - if and else have incompatible types

Ok::<(), io::Error>(())
```

In many cases, the trait methods use self by (mutable) reference. Thus we can
create a `dyn` reference, but we need two variables for the actual objects,
because as shown above, one variable can only hold one type of object. We must
still declare the variables outside of the `if` to make sure they live long
enough.

Note that this relies on the fact that while one needs to initialize a value to
use it, Rust is clever enough to allow unused values to stay uninitialized:

```no_run
use std::{io, fs, env};

let arg = env::args().nth(1).unwrap_or(\"-\".into());

// We only declare, not initialize the values.
let (mut stdin, mut file);

// We need to ascribe the type here to select dynamic dispatch.
let input: &mut dyn io::Read = if arg == \"-\" {
stdin = std::io::stdin();
&mut stdin
} else {
file = fs::File::open(arg)?;
&mut file
};
Ok::<(), io::Error>(())
```
"},"level":"error","spans":[{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":681,"byte_end":682,"line_start":19,"line_end":19,"column_start":22,"column_end":23,"is_primary":true,"text":[{"text":" let s : String = 1","highlight_start":22,"highlight_end":23}],"label":"expected struct `std::string::String`, found integer","suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":672,"byte_end":678,"line_start":19,"line_end":19,"column_start":13,"column_end":19,"is_primary":false,"text":[{"text":" let s : String = 1","highlight_start":13,"highlight_end":19}],"label":"expected due to this","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"try using a conversion method","code":null,"level":"help","spans":[{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":681,"byte_end":682,"line_start":19,"line_end":19,"column_start":22,"column_end":23,"is_primary":true,"text":[{"text":" let s : String = 1","highlight_start":22,"highlight_end":23}],"label":null,"suggested_replacement":"1.to_string()","suggestion_applicability":"MaybeIncorrect","expansion":null}],"children":[],"rendered":null}],"rendered":"$DIR/json-bom-plus-crlf-multifile-aux.rs:19:22: error[E0308]: mismatched types
"}
{"message":"mismatched types","code":{"code":"E0308","explanation":"Expected type did not match the received type.
Expand All @@ -59,6 +153,53 @@ variable. It can occur for several cases, the most common of which is a
mismatch in the expected type that the compiler inferred for a variable's
initializing expression, and the actual type explicitly assigned to the
variable.

One possible scenario is that we have a trait and want to use multiple
implementors conditionally via dynamic dispatch. E. g.

```compile_fail,E0308
use std::{io, fs, env};

let arg = env::args().nth(1);

let mut input = if arg == \"-\" {
std::io::stdin()
} else {
fs::File::open(arg)?
// expected struct `std::io::Stdin`, found struct `std::fs::File
};
// - if and else have incompatible types

Ok::<(), io::Error>(())
```

In many cases, the trait methods use self by (mutable) reference. Thus we can
create a `dyn` reference, but we need two variables for the actual objects,
because as shown above, one variable can only hold one type of object. We must
still declare the variables outside of the `if` to make sure they live long
enough.

Note that this relies on the fact that while one needs to initialize a value to
use it, Rust is clever enough to allow unused values to stay uninitialized:

```no_run
use std::{io, fs, env};

let arg = env::args().nth(1).unwrap_or(\"-\".into());

// We only declare, not initialize the values.
let (mut stdin, mut file);

// We need to ascribe the type here to select dynamic dispatch.
let input: &mut dyn io::Read = if arg == \"-\" {
stdin = std::io::stdin();
&mut stdin
} else {
file = fs::File::open(arg)?;
&mut file
};
Ok::<(), io::Error>(())
```
"},"level":"error","spans":[{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":745,"byte_end":746,"line_start":23,"line_end":23,"column_start":1,"column_end":2,"is_primary":true,"text":[{"text":"1; // Error after the newline.","highlight_start":1,"highlight_end":2}],"label":"expected struct `std::string::String`, found integer","suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":735,"byte_end":741,"line_start":22,"line_end":22,"column_start":13,"column_end":19,"is_primary":false,"text":[{"text":" let s : String =","highlight_start":13,"highlight_end":19}],"label":"expected due to this","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"try using a conversion method","code":null,"level":"help","spans":[{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":745,"byte_end":746,"line_start":23,"line_end":23,"column_start":1,"column_end":2,"is_primary":true,"text":[{"text":"1; // Error after the newline.","highlight_start":1,"highlight_end":2}],"label":null,"suggested_replacement":"1.to_string()","suggestion_applicability":"MaybeIncorrect","expansion":null}],"children":[],"rendered":null}],"rendered":"$DIR/json-bom-plus-crlf-multifile-aux.rs:23:1: error[E0308]: mismatched types
"}
{"message":"mismatched types","code":{"code":"E0308","explanation":"Expected type did not match the received type.
Expand All @@ -80,6 +221,53 @@ variable. It can occur for several cases, the most common of which is a
mismatch in the expected type that the compiler inferred for a variable's
initializing expression, and the actual type explicitly assigned to the
variable.

One possible scenario is that we have a trait and want to use multiple
implementors conditionally via dynamic dispatch. E. g.

```compile_fail,E0308
use std::{io, fs, env};

let arg = env::args().nth(1);

let mut input = if arg == \"-\" {
std::io::stdin()
} else {
fs::File::open(arg)?
// expected struct `std::io::Stdin`, found struct `std::fs::File
};
// - if and else have incompatible types

Ok::<(), io::Error>(())
```

In many cases, the trait methods use self by (mutable) reference. Thus we can
create a `dyn` reference, but we need two variables for the actual objects,
because as shown above, one variable can only hold one type of object. We must
still declare the variables outside of the `if` to make sure they live long
enough.

Note that this relies on the fact that while one needs to initialize a value to
use it, Rust is clever enough to allow unused values to stay uninitialized:

```no_run
use std::{io, fs, env};

let arg = env::args().nth(1).unwrap_or(\"-\".into());

// We only declare, not initialize the values.
let (mut stdin, mut file);

// We need to ascribe the type here to select dynamic dispatch.
let input: &mut dyn io::Read = if arg == \"-\" {
stdin = std::io::stdin();
&mut stdin
} else {
file = fs::File::open(arg)?;
&mut file
};
Ok::<(), io::Error>(())
```
"},"level":"error","spans":[{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":801,"byte_end":809,"line_start":25,"line_end":26,"column_start":22,"column_end":6,"is_primary":true,"text":[{"text":" let s : String = (","highlight_start":22,"highlight_end":23},{"text":" ); // Error spanning the newline.","highlight_start":1,"highlight_end":6}],"label":"expected struct `std::string::String`, found `()`","suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":792,"byte_end":798,"line_start":25,"line_end":25,"column_start":13,"column_end":19,"is_primary":false,"text":[{"text":" let s : String = (","highlight_start":13,"highlight_end":19}],"label":"expected due to this","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[],"rendered":"$DIR/json-bom-plus-crlf-multifile-aux.rs:25:22: error[E0308]: mismatched types
"}
{"message":"aborting due to 4 previous errors","code":null,"level":"error","spans":[],"children":[],"rendered":"error: aborting due to 4 previous errors
Expand Down
Loading