Skip to content

Commit bf29323

Browse files
author
Andre Bogus
committed
Extend E0308 description with dynamic dispatch example
1 parent 57e1da5 commit bf29323

File tree

3 files changed

+423
-0
lines changed

3 files changed

+423
-0
lines changed

src/librustc_error_codes/error_codes/E0308.md

+47
Original file line numberDiff line numberDiff line change
@@ -17,3 +17,50 @@ variable. It can occur for several cases, the most common of which is a
1717
mismatch in the expected type that the compiler inferred for a variable's
1818
initializing expression, and the actual type explicitly assigned to the
1919
variable.
20+
21+
One possible scenario is that we have a trait and want to use multiple
22+
implementors conditionally via dynamic dispatch. E. g.
23+
24+
```compile_fail,E0308
25+
use std::{io, fs, env};
26+
27+
let arg = env::args().nth(1);
28+
29+
let mut input = if arg == "-" {
30+
std::io::stdin()
31+
} else {
32+
fs::File::open(arg)?
33+
// expected struct `std::io::Stdin`, found struct `std::fs::File
34+
};
35+
// - if and else have incompatible types
36+
37+
Ok::<(), io::Error>(())
38+
```
39+
40+
In many cases, the trait methods use self by (mutable) reference. Thus we can
41+
create a `dyn` reference, but we need two variables for the actual objects,
42+
because as shown above, one variable can only hold one type of object. We must
43+
still declare the variables outside of the `if` to make sure they live long
44+
enough.
45+
46+
Note that this relies on the fact that while one needs to initialize a value to
47+
use it, Rust is clever enough to allow unused values to stay uninitialized:
48+
49+
```no_run
50+
use std::{io, fs, env};
51+
52+
let arg = env::args().nth(1).unwrap_or("-".into());
53+
54+
// We only declare, not initialize the values.
55+
let (mut stdin, mut file);
56+
57+
// We need to ascribe the type here to select dynamic dispatch.
58+
let input: &mut dyn io::Read = if arg == "-" {
59+
stdin = std::io::stdin();
60+
&mut stdin
61+
} else {
62+
file = fs::File::open(arg)?;
63+
&mut file
64+
};
65+
Ok::<(), io::Error>(())
66+
```

src/test/ui/json-bom-plus-crlf-multifile.stderr

+188
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,53 @@ variable. It can occur for several cases, the most common of which is a
1717
mismatch in the expected type that the compiler inferred for a variable's
1818
initializing expression, and the actual type explicitly assigned to the
1919
variable.
20+
21+
One possible scenario is that we have a trait and want to use multiple
22+
implementors conditionally via dynamic dispatch. E. g.
23+
24+
```compile_fail,E0308
25+
use std::{io, fs, env};
26+
27+
let arg = env::args().nth(1);
28+
29+
let mut input = if arg == \"-\" {
30+
std::io::stdin()
31+
} else {
32+
fs::File::open(arg)?
33+
// expected struct `std::io::Stdin`, found struct `std::fs::File
34+
};
35+
// - if and else have incompatible types
36+
37+
Ok::<(), io::Error>(())
38+
```
39+
40+
In many cases, the trait methods use self by (mutable) reference. Thus we can
41+
create a `dyn` reference, but we need two variables for the actual objects,
42+
because as shown above, one variable can only hold one type of object. We must
43+
still declare the variables outside of the `if` to make sure they live long
44+
enough.
45+
46+
Note that this relies on the fact that while one needs to initialize a value to
47+
use it, Rust is clever enough to allow unused values to stay uninitialized:
48+
49+
```no_run
50+
use std::{io, fs, env};
51+
52+
let arg = env::args().nth(1).unwrap_or(\"-\".into());
53+
54+
// We only declare, not initialize the values.
55+
let (mut stdin, mut file);
56+
57+
// We need to ascribe the type here to select dynamic dispatch.
58+
let input: &mut dyn io::Read = if arg == \"-\" {
59+
stdin = std::io::stdin();
60+
&mut stdin
61+
} else {
62+
file = fs::File::open(arg)?;
63+
&mut file
64+
};
65+
Ok::<(), io::Error>(())
66+
```
2067
"},"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
2168
"}
2269
{"message":"mismatched types","code":{"code":"E0308","explanation":"Expected type did not match the received type.
@@ -38,6 +85,53 @@ variable. It can occur for several cases, the most common of which is a
3885
mismatch in the expected type that the compiler inferred for a variable's
3986
initializing expression, and the actual type explicitly assigned to the
4087
variable.
88+
89+
One possible scenario is that we have a trait and want to use multiple
90+
implementors conditionally via dynamic dispatch. E. g.
91+
92+
```compile_fail,E0308
93+
use std::{io, fs, env};
94+
95+
let arg = env::args().nth(1);
96+
97+
let mut input = if arg == \"-\" {
98+
std::io::stdin()
99+
} else {
100+
fs::File::open(arg)?
101+
// expected struct `std::io::Stdin`, found struct `std::fs::File
102+
};
103+
// - if and else have incompatible types
104+
105+
Ok::<(), io::Error>(())
106+
```
107+
108+
In many cases, the trait methods use self by (mutable) reference. Thus we can
109+
create a `dyn` reference, but we need two variables for the actual objects,
110+
because as shown above, one variable can only hold one type of object. We must
111+
still declare the variables outside of the `if` to make sure they live long
112+
enough.
113+
114+
Note that this relies on the fact that while one needs to initialize a value to
115+
use it, Rust is clever enough to allow unused values to stay uninitialized:
116+
117+
```no_run
118+
use std::{io, fs, env};
119+
120+
let arg = env::args().nth(1).unwrap_or(\"-\".into());
121+
122+
// We only declare, not initialize the values.
123+
let (mut stdin, mut file);
124+
125+
// We need to ascribe the type here to select dynamic dispatch.
126+
let input: &mut dyn io::Read = if arg == \"-\" {
127+
stdin = std::io::stdin();
128+
&mut stdin
129+
} else {
130+
file = fs::File::open(arg)?;
131+
&mut file
132+
};
133+
Ok::<(), io::Error>(())
134+
```
41135
"},"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
42136
"}
43137
{"message":"mismatched types","code":{"code":"E0308","explanation":"Expected type did not match the received type.
@@ -59,6 +153,53 @@ variable. It can occur for several cases, the most common of which is a
59153
mismatch in the expected type that the compiler inferred for a variable's
60154
initializing expression, and the actual type explicitly assigned to the
61155
variable.
156+
157+
One possible scenario is that we have a trait and want to use multiple
158+
implementors conditionally via dynamic dispatch. E. g.
159+
160+
```compile_fail,E0308
161+
use std::{io, fs, env};
162+
163+
let arg = env::args().nth(1);
164+
165+
let mut input = if arg == \"-\" {
166+
std::io::stdin()
167+
} else {
168+
fs::File::open(arg)?
169+
// expected struct `std::io::Stdin`, found struct `std::fs::File
170+
};
171+
// - if and else have incompatible types
172+
173+
Ok::<(), io::Error>(())
174+
```
175+
176+
In many cases, the trait methods use self by (mutable) reference. Thus we can
177+
create a `dyn` reference, but we need two variables for the actual objects,
178+
because as shown above, one variable can only hold one type of object. We must
179+
still declare the variables outside of the `if` to make sure they live long
180+
enough.
181+
182+
Note that this relies on the fact that while one needs to initialize a value to
183+
use it, Rust is clever enough to allow unused values to stay uninitialized:
184+
185+
```no_run
186+
use std::{io, fs, env};
187+
188+
let arg = env::args().nth(1).unwrap_or(\"-\".into());
189+
190+
// We only declare, not initialize the values.
191+
let (mut stdin, mut file);
192+
193+
// We need to ascribe the type here to select dynamic dispatch.
194+
let input: &mut dyn io::Read = if arg == \"-\" {
195+
stdin = std::io::stdin();
196+
&mut stdin
197+
} else {
198+
file = fs::File::open(arg)?;
199+
&mut file
200+
};
201+
Ok::<(), io::Error>(())
202+
```
62203
"},"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
63204
"}
64205
{"message":"mismatched types","code":{"code":"E0308","explanation":"Expected type did not match the received type.
@@ -80,6 +221,53 @@ variable. It can occur for several cases, the most common of which is a
80221
mismatch in the expected type that the compiler inferred for a variable's
81222
initializing expression, and the actual type explicitly assigned to the
82223
variable.
224+
225+
One possible scenario is that we have a trait and want to use multiple
226+
implementors conditionally via dynamic dispatch. E. g.
227+
228+
```compile_fail,E0308
229+
use std::{io, fs, env};
230+
231+
let arg = env::args().nth(1);
232+
233+
let mut input = if arg == \"-\" {
234+
std::io::stdin()
235+
} else {
236+
fs::File::open(arg)?
237+
// expected struct `std::io::Stdin`, found struct `std::fs::File
238+
};
239+
// - if and else have incompatible types
240+
241+
Ok::<(), io::Error>(())
242+
```
243+
244+
In many cases, the trait methods use self by (mutable) reference. Thus we can
245+
create a `dyn` reference, but we need two variables for the actual objects,
246+
because as shown above, one variable can only hold one type of object. We must
247+
still declare the variables outside of the `if` to make sure they live long
248+
enough.
249+
250+
Note that this relies on the fact that while one needs to initialize a value to
251+
use it, Rust is clever enough to allow unused values to stay uninitialized:
252+
253+
```no_run
254+
use std::{io, fs, env};
255+
256+
let arg = env::args().nth(1).unwrap_or(\"-\".into());
257+
258+
// We only declare, not initialize the values.
259+
let (mut stdin, mut file);
260+
261+
// We need to ascribe the type here to select dynamic dispatch.
262+
let input: &mut dyn io::Read = if arg == \"-\" {
263+
stdin = std::io::stdin();
264+
&mut stdin
265+
} else {
266+
file = fs::File::open(arg)?;
267+
&mut file
268+
};
269+
Ok::<(), io::Error>(())
270+
```
83271
"},"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
84272
"}
85273
{"message":"aborting due to 4 previous errors","code":null,"level":"error","spans":[],"children":[],"rendered":"error: aborting due to 4 previous errors

0 commit comments

Comments
 (0)