Skip to content

Commit dc53cfe

Browse files
committed
Add test cases and address review comments
1 parent 5d2a935 commit dc53cfe

File tree

5 files changed

+156
-19
lines changed

5 files changed

+156
-19
lines changed

compiler/rustc_infer/src/infer/error_reporting/mod.rs

+5-5
Original file line numberDiff line numberDiff line change
@@ -617,14 +617,14 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
617617
ref prior_arms,
618618
last_ty,
619619
scrut_hir_id,
620-
suggest_box,
620+
opt_suggest_box_span,
621621
arm_span,
622622
..
623623
}) => match source {
624624
hir::MatchSource::IfLetDesugar { .. } => {
625625
let msg = "`if let` arms have incompatible types";
626626
err.span_label(cause.span, msg);
627-
if let Some(ret_sp) = suggest_box {
627+
if let Some(ret_sp) = opt_suggest_box_span {
628628
self.suggest_boxing_for_return_impl_trait(
629629
err,
630630
ret_sp,
@@ -684,7 +684,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
684684
Applicability::MachineApplicable,
685685
);
686686
}
687-
if let Some(ret_sp) = suggest_box {
687+
if let Some(ret_sp) = opt_suggest_box_span {
688688
// Get return type span and point to it.
689689
self.suggest_boxing_for_return_impl_trait(
690690
err,
@@ -699,7 +699,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
699699
else_sp,
700700
outer,
701701
semicolon,
702-
suggest_box,
702+
opt_suggest_box_span,
703703
}) => {
704704
err.span_label(then, "expected because of this");
705705
if let Some(sp) = outer {
@@ -713,7 +713,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
713713
Applicability::MachineApplicable,
714714
);
715715
}
716-
if let Some(ret_sp) = suggest_box {
716+
if let Some(ret_sp) = opt_suggest_box_span {
717717
self.suggest_boxing_for_return_impl_trait(
718718
err,
719719
ret_sp,

compiler/rustc_middle/src/traits/mod.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -350,7 +350,7 @@ pub struct MatchExpressionArmCause<'tcx> {
350350
pub prior_arms: Vec<Span>,
351351
pub last_ty: Ty<'tcx>,
352352
pub scrut_hir_id: hir::HirId,
353-
pub suggest_box: Option<Span>,
353+
pub opt_suggest_box_span: Option<Span>,
354354
}
355355

356356
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
@@ -359,7 +359,7 @@ pub struct IfExpressionCause {
359359
pub else_sp: Span,
360360
pub outer: Option<Span>,
361361
pub semicolon: Option<Span>,
362-
pub suggest_box: Option<Span>,
362+
pub opt_suggest_box_span: Option<Span>,
363363
}
364364

365365
#[derive(Clone, Debug, PartialEq, Eq, Hash, Lift)]

compiler/rustc_typeck/src/check/_match.rs

+6-10
Original file line numberDiff line numberDiff line change
@@ -119,13 +119,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
119119
// When we have a `match` as a tail expression in a `fn` with a returned `impl Trait`
120120
// we check if the different arms would work with boxed trait objects instead and
121121
// provide a structured suggestion in that case.
122-
let suggest_box = match (
122+
let opt_suggest_box_span = match (
123123
orig_expected,
124-
self.body_id
125-
.owner
126-
.to_def_id()
127-
.as_local()
128-
.and_then(|id| self.ret_coercion_impl_trait.map(|ty| (id, ty))),
124+
self.ret_coercion_impl_trait.map(|ty| (self.body_id.owner, ty)),
129125
) {
130126
(Expectation::ExpectHasType(expected), Some((id, ty)))
131127
if self.in_tail_expr && self.can_coerce(arm_ty, expected) =>
@@ -181,7 +177,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
181177
&arm.body,
182178
then_ty,
183179
arm_ty,
184-
suggest_box,
180+
opt_suggest_box_span,
185181
);
186182
coercion.coerce(self, &cause, &arm.body, arm_ty);
187183
}
@@ -205,7 +201,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
205201
prior_arms: other_arms.clone(),
206202
last_ty: prior_arm_ty.unwrap(),
207203
scrut_hir_id: scrut.hir_id,
208-
suggest_box,
204+
opt_suggest_box_span,
209205
}),
210206
),
211207
};
@@ -330,7 +326,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
330326
else_expr: &'tcx hir::Expr<'tcx>,
331327
then_ty: Ty<'tcx>,
332328
else_ty: Ty<'tcx>,
333-
suggest_box: Option<Span>,
329+
opt_suggest_box_span: Option<Span>,
334330
) -> ObligationCause<'tcx> {
335331
let mut outer_sp = if self.tcx.sess.source_map().is_multiline(span) {
336332
// The `if`/`else` isn't in one line in the output, include some context to make it
@@ -421,7 +417,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
421417
else_sp: error_sp,
422418
outer: outer_sp,
423419
semicolon: remove_semicolon,
424-
suggest_box,
420+
opt_suggest_box_span,
425421
}),
426422
)
427423
}

src/test/ui/point-to-type-err-cause-on-impl-trait-return.rs

+35
Original file line numberDiff line numberDiff line change
@@ -63,4 +63,39 @@ fn dog() -> impl std::fmt::Display {
6363
}
6464
}
6565

66+
fn hat() -> dyn std::fmt::Display { //~ ERROR return type cannot have an unboxed trait object
67+
match 13 {
68+
0 => {
69+
return 0i32;
70+
}
71+
_ => {
72+
1u32
73+
}
74+
}
75+
}
76+
77+
fn pug() -> dyn std::fmt::Display { //~ ERROR return type cannot have an unboxed trait object
78+
match 13 {
79+
0 => 0i32,
80+
1 => 1u32, //~ ERROR `match` arms have incompatible types
81+
_ => 2u32,
82+
}
83+
}
84+
85+
fn man() -> dyn std::fmt::Display { //~ ERROR return type cannot have an unboxed trait object
86+
if false {
87+
0i32
88+
} else {
89+
1u32 //~ ERROR `if` and `else` have incompatible types
90+
}
91+
}
92+
93+
fn apt() -> impl std::fmt::Display {
94+
if let Some(42) = Some(42) {
95+
0i32
96+
} else {
97+
1u32 //~ ERROR `if` and `else` have incompatible types
98+
}
99+
}
100+
66101
fn main() {}

src/test/ui/point-to-type-err-cause-on-impl-trait-return.stderr

+108-2
Original file line numberDiff line numberDiff line change
@@ -207,6 +207,112 @@ LL | 0 => Box::new(0i32),
207207
LL | 1 => Box::new(1u32),
208208
|
209209

210-
error: aborting due to 8 previous errors
210+
error[E0308]: `if` and `else` have incompatible types
211+
--> $DIR/point-to-type-err-cause-on-impl-trait-return.rs:97:9
212+
|
213+
LL | / if let Some(42) = Some(42) {
214+
LL | | 0i32
215+
| | ---- expected because of this
216+
LL | | } else {
217+
LL | | 1u32
218+
| | ^^^^ expected `i32`, found `u32`
219+
LL | | }
220+
| |_____- `if` and `else` have incompatible types
221+
|
222+
help: you could change the return type to be a boxed trait object
223+
|
224+
LL | fn apt() -> Box<dyn std::fmt::Display> {
225+
| ^^^^^^^ ^
226+
help: if you change the return type to expect trait objects, box the returned expressions
227+
|
228+
LL | Box::new(0i32)
229+
LL | } else {
230+
LL | Box::new(1u32)
231+
|
232+
233+
error[E0746]: return type cannot have an unboxed trait object
234+
--> $DIR/point-to-type-err-cause-on-impl-trait-return.rs:66:13
235+
|
236+
LL | fn hat() -> dyn std::fmt::Display {
237+
| ^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
238+
|
239+
= note: for information on trait objects, see <https://doc.rust-lang.org/book/ch17-02-trait-objects.html#using-trait-objects-that-allow-for-values-of-different-types>
240+
= note: if all the returned values were of the same type you could use `impl std::fmt::Display` as the return type
241+
= note: for information on `impl Trait`, see <https://doc.rust-lang.org/book/ch10-02-traits.html#returning-types-that-implement-traits>
242+
= note: you can create a new `enum` with a variant for each returned type
243+
help: return a boxed trait object instead
244+
|
245+
LL | fn hat() -> Box<dyn std::fmt::Display> {
246+
LL | match 13 {
247+
LL | 0 => {
248+
LL | return Box::new(0i32);
249+
LL | }
250+
LL | _ => {
251+
...
252+
253+
error[E0308]: `match` arms have incompatible types
254+
--> $DIR/point-to-type-err-cause-on-impl-trait-return.rs:80:14
255+
|
256+
LL | / match 13 {
257+
LL | | 0 => 0i32,
258+
| | ---- this is found to be of type `i32`
259+
LL | | 1 => 1u32,
260+
| | ^^^^ expected `i32`, found `u32`
261+
LL | | _ => 2u32,
262+
LL | | }
263+
| |_____- `match` arms have incompatible types
264+
265+
error[E0746]: return type cannot have an unboxed trait object
266+
--> $DIR/point-to-type-err-cause-on-impl-trait-return.rs:77:13
267+
|
268+
LL | fn pug() -> dyn std::fmt::Display {
269+
| ^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
270+
|
271+
= note: for information on trait objects, see <https://doc.rust-lang.org/book/ch17-02-trait-objects.html#using-trait-objects-that-allow-for-values-of-different-types>
272+
= note: if all the returned values were of the same type you could use `impl std::fmt::Display` as the return type
273+
= note: for information on `impl Trait`, see <https://doc.rust-lang.org/book/ch10-02-traits.html#returning-types-that-implement-traits>
274+
= note: you can create a new `enum` with a variant for each returned type
275+
help: return a boxed trait object instead
276+
|
277+
LL | fn pug() -> Box<dyn std::fmt::Display> {
278+
LL | match 13 {
279+
LL | 0 => Box::new(0i32),
280+
LL | 1 => Box::new(1u32),
281+
LL | _ => Box::new(2u32),
282+
|
283+
284+
error[E0308]: `if` and `else` have incompatible types
285+
--> $DIR/point-to-type-err-cause-on-impl-trait-return.rs:89:9
286+
|
287+
LL | / if false {
288+
LL | | 0i32
289+
| | ---- expected because of this
290+
LL | | } else {
291+
LL | | 1u32
292+
| | ^^^^ expected `i32`, found `u32`
293+
LL | | }
294+
| |_____- `if` and `else` have incompatible types
295+
296+
error[E0746]: return type cannot have an unboxed trait object
297+
--> $DIR/point-to-type-err-cause-on-impl-trait-return.rs:85:13
298+
|
299+
LL | fn man() -> dyn std::fmt::Display {
300+
| ^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
301+
|
302+
= note: for information on trait objects, see <https://doc.rust-lang.org/book/ch17-02-trait-objects.html#using-trait-objects-that-allow-for-values-of-different-types>
303+
= note: if all the returned values were of the same type you could use `impl std::fmt::Display` as the return type
304+
= note: for information on `impl Trait`, see <https://doc.rust-lang.org/book/ch10-02-traits.html#returning-types-that-implement-traits>
305+
= note: you can create a new `enum` with a variant for each returned type
306+
help: return a boxed trait object instead
307+
|
308+
LL | fn man() -> Box<dyn std::fmt::Display> {
309+
LL | if false {
310+
LL | Box::new(0i32)
311+
LL | } else {
312+
LL | Box::new(1u32)
313+
|
314+
315+
error: aborting due to 14 previous errors
211316

212-
For more information about this error, try `rustc --explain E0308`.
317+
Some errors have detailed explanations: E0308, E0746.
318+
For more information about an error, try `rustc --explain E0308`.

0 commit comments

Comments
 (0)