Skip to content

Commit 1380026

Browse files
committed
Suggest boxing or borrowing unsized fields
1 parent 2185b0b commit 1380026

30 files changed

+424
-106
lines changed

src/librustc_middle/traits/mod.rs

+1
Original file line numberDiff line numberDiff line change
@@ -229,6 +229,7 @@ pub enum ObligationCauseCode<'tcx> {
229229
/// Types of fields (other than the last, except for packed structs) in a struct must be sized.
230230
FieldSized {
231231
adt_kind: AdtKind,
232+
span: Span,
232233
last: bool,
233234
},
234235

src/librustc_middle/traits/structural_impls.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -156,7 +156,9 @@ impl<'a, 'tcx> Lift<'tcx> for traits::ObligationCauseCode<'a> {
156156
super::SizedYieldType => Some(super::SizedYieldType),
157157
super::InlineAsmSized => Some(super::InlineAsmSized),
158158
super::RepeatVec(suggest_flag) => Some(super::RepeatVec(suggest_flag)),
159-
super::FieldSized { adt_kind, last } => Some(super::FieldSized { adt_kind, last }),
159+
super::FieldSized { adt_kind, span, last } => {
160+
Some(super::FieldSized { adt_kind, span, last })
161+
}
160162
super::ConstSized => Some(super::ConstSized),
161163
super::ConstPatternStructural => Some(super::ConstPatternStructural),
162164
super::SharedStatic => Some(super::SharedStatic),

src/librustc_trait_selection/traits/error_reporting/suggestions.rs

+35-18
Original file line numberDiff line numberDiff line change
@@ -1856,26 +1856,43 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
18561856
ObligationCauseCode::StructInitializerSized => {
18571857
err.note("structs must have a statically known size to be initialized");
18581858
}
1859-
ObligationCauseCode::FieldSized { adt_kind: ref item, last } => match *item {
1860-
AdtKind::Struct => {
1861-
if last {
1862-
err.note(
1863-
"the last field of a packed struct may only have a \
1864-
dynamically sized type if it does not need drop to be run",
1865-
);
1866-
} else {
1867-
err.note(
1868-
"only the last field of a struct may have a dynamically sized type",
1869-
);
1859+
ObligationCauseCode::FieldSized { adt_kind: ref item, last, span } => {
1860+
match *item {
1861+
AdtKind::Struct => {
1862+
if last {
1863+
err.note(
1864+
"the last field of a packed struct may only have a \
1865+
dynamically sized type if it does not need drop to be run",
1866+
);
1867+
} else {
1868+
err.note(
1869+
"only the last field of a struct may have a dynamically sized type",
1870+
);
1871+
}
1872+
}
1873+
AdtKind::Union => {
1874+
err.note("no field of a union may have a dynamically sized type");
1875+
}
1876+
AdtKind::Enum => {
1877+
err.note("no field of an enum variant may have a dynamically sized type");
18701878
}
18711879
}
1872-
AdtKind::Union => {
1873-
err.note("no field of a union may have a dynamically sized type");
1874-
}
1875-
AdtKind::Enum => {
1876-
err.note("no field of an enum variant may have a dynamically sized type");
1877-
}
1878-
},
1880+
err.help("change the field's type to have a statically known size");
1881+
err.span_suggestion(
1882+
span.shrink_to_lo(),
1883+
"borrowed types always have a statically known size",
1884+
"&".to_string(),
1885+
Applicability::MachineApplicable,
1886+
);
1887+
err.multipart_suggestion(
1888+
"heap allocated types always have a statically known size",
1889+
vec![
1890+
(span.shrink_to_lo(), "Box<".to_string()),
1891+
(span.shrink_to_hi(), ">".to_string()),
1892+
],
1893+
Applicability::MachineApplicable,
1894+
);
1895+
}
18791896
ObligationCauseCode::ConstSized => {
18801897
err.note("constant expressions must have a statically known size");
18811898
}

src/librustc_typeck/check/wfcheck.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -394,6 +394,7 @@ fn check_type_defn<'tcx, F>(
394394
Some(i) => i,
395395
None => bug!(),
396396
},
397+
span: field.span,
397398
last,
398399
},
399400
),
@@ -1329,7 +1330,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
13291330
let field_ty = self.normalize_associated_types_in(field.ty.span, &field_ty);
13301331
let field_ty = self.resolve_vars_if_possible(&field_ty);
13311332
debug!("non_enum_variant: type of field {:?} is {:?}", field, field_ty);
1332-
AdtField { ty: field_ty, span: field.span }
1333+
AdtField { ty: field_ty, span: field.ty.span }
13331334
})
13341335
.collect();
13351336
AdtVariant { fields, explicit_discr: None }

src/test/ui/const-generics/array-size-in-generic-struct-param.stderr

+2-2
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,10 @@ LL | struct ArithArrayLen<const N: usize>([u32; 0 + N]);
1616
= note: this may fail depending on what value the parameter takes
1717

1818
error: constant expression depends on a generic parameter
19-
--> $DIR/array-size-in-generic-struct-param.rs:14:5
19+
--> $DIR/array-size-in-generic-struct-param.rs:14:10
2020
|
2121
LL | arr: [u8; CFG.arr_size],
22-
| ^^^^^^^^^^^^^^^^^^^^^^^
22+
| ^^^^^^^^^^^^^^^^^^
2323
|
2424
= note: this may fail depending on what value the parameter takes
2525

src/test/ui/error-codes/E0478.stderr

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
error[E0478]: lifetime bound not satisfied
2-
--> $DIR/E0478.rs:4:5
2+
--> $DIR/E0478.rs:4:12
33
|
44
LL | child: Box<dyn Wedding<'kiss> + 'SnowWhite>,
5-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
5+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
66
|
77
note: lifetime parameter instantiated with the lifetime `'SnowWhite` as defined on the struct at 3:22
88
--> $DIR/E0478.rs:3:22

src/test/ui/feature-gates/feature-gate-infer_static_outlives_requirements.stderr

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
error[E0310]: the parameter type `U` may not live long enough
2-
--> $DIR/feature-gate-infer_static_outlives_requirements.rs:5:5
2+
--> $DIR/feature-gate-infer_static_outlives_requirements.rs:5:10
33
|
44
LL | struct Foo<U> {
55
| - help: consider adding an explicit lifetime bound...: `U: 'static`
66
LL | bar: Bar<U>
7-
| ^^^^^^^^^^^ ...so that the type `U` will meet its required lifetime bounds
7+
| ^^^^^^ ...so that the type `U` will meet its required lifetime bounds
88

99
error: aborting due to previous error
1010

src/test/ui/issues/issue-19380.stderr

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
error[E0038]: the trait `Qiz` cannot be made into an object
2-
--> $DIR/issue-19380.rs:11:3
2+
--> $DIR/issue-19380.rs:11:9
33
|
44
LL | trait Qiz {
55
| --- this trait cannot be made into an object...
66
LL | fn qiz();
77
| --- ...because associated function `qiz` has no `self` parameter
88
...
99
LL | foos: &'static [&'static (dyn Qiz + 'static)]
10-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Qiz` cannot be made into an object
10+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Qiz` cannot be made into an object
1111
|
1212
help: consider turning `qiz` into a method by giving it a `&self` argument or constraining it so it does not apply to trait objects
1313
|

src/test/ui/issues/issue-22874.stderr

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
error[E0277]: the size for values of type `[std::string::String]` cannot be known at compilation time
2-
--> $DIR/issue-22874.rs:2:5
2+
--> $DIR/issue-22874.rs:2:11
33
|
44
LL | rows: [[String]],
5-
| ^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
5+
| ^^^^^^^^^^ doesn't have a size known at compile-time
66
|
77
= help: the trait `std::marker::Sized` is not implemented for `[std::string::String]`
88
= note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>

src/test/ui/issues/issue-27060-2.stderr

+11-2
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,23 @@
11
error[E0277]: the size for values of type `T` cannot be known at compilation time
2-
--> $DIR/issue-27060-2.rs:3:5
2+
--> $DIR/issue-27060-2.rs:3:11
33
|
44
LL | pub struct Bad<T: ?Sized> {
55
| - this type parameter needs to be `std::marker::Sized`
66
LL | data: T,
7-
| ^^^^^^^ doesn't have a size known at compile-time
7+
| ^ doesn't have a size known at compile-time
88
|
99
= help: the trait `std::marker::Sized` is not implemented for `T`
1010
= note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
1111
= note: the last field of a packed struct may only have a dynamically sized type if it does not need drop to be run
12+
= help: change the field's type to have a statically known size
13+
help: borrowed types always have a statically known size
14+
|
15+
LL | data: &T,
16+
| ^
17+
help: heap allocated types always have a statically known size
18+
|
19+
LL | data: Box<T>,
20+
| ^^^^ ^
1221

1322
error: aborting due to previous error
1423

src/test/ui/issues/issue-35988.stderr

+9
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,15 @@ LL | V([Box<E>]),
77
= help: the trait `std::marker::Sized` is not implemented for `[std::boxed::Box<E>]`
88
= note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
99
= note: no field of an enum variant may have a dynamically sized type
10+
= help: change the field's type to have a statically known size
11+
help: borrowed types always have a statically known size
12+
|
13+
LL | V(&[Box<E>]),
14+
| ^
15+
help: heap allocated types always have a statically known size
16+
|
17+
LL | V(Box<[Box<E>]>),
18+
| ^^^^ ^
1019

1120
error: aborting due to previous error
1221

src/test/ui/lazy_normalization_consts/issue-57739.stderr

+2-2
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,10 @@ LL | #![feature(lazy_normalization_consts)]
88
= note: see issue #72219 <https://github.com/rust-lang/rust/issues/72219> for more information
99

1010
error: constant expression depends on a generic parameter
11-
--> $DIR/issue-57739.rs:12:5
11+
--> $DIR/issue-57739.rs:12:12
1212
|
1313
LL | array: [u8; T::SIZE],
14-
| ^^^^^^^^^^^^^^^^^^^^
14+
| ^^^^^^^^^^^^^
1515
|
1616
= note: this may fail depending on what value the parameter takes
1717

src/test/ui/lifetimes/lifetime-doesnt-live-long-enough.stderr

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
error[E0310]: the parameter type `T` may not live long enough
2-
--> $DIR/lifetime-doesnt-live-long-enough.rs:19:5
2+
--> $DIR/lifetime-doesnt-live-long-enough.rs:19:10
33
|
44
LL | struct Foo<T> {
55
| - help: consider adding an explicit lifetime bound...: `T: 'static`
66
LL | foo: &'static T
7-
| ^^^^^^^^^^^^^^^ ...so that the reference type `&'static T` does not outlive the data it points at
7+
| ^^^^^^^^^^ ...so that the reference type `&'static T` does not outlive the data it points at
88

99
error[E0309]: the parameter type `K` may not live long enough
1010
--> $DIR/lifetime-doesnt-live-long-enough.rs:24:19

src/test/ui/regions/region-bounds-on-objects-and-type-parameters.stderr

+2-2
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,10 @@ LL | z: Box<dyn Is<'a>+'b+'c>,
55
| ^^
66

77
error[E0478]: lifetime bound not satisfied
8-
--> $DIR/region-bounds-on-objects-and-type-parameters.rs:21:5
8+
--> $DIR/region-bounds-on-objects-and-type-parameters.rs:21:8
99
|
1010
LL | z: Box<dyn Is<'a>+'b+'c>,
11-
| ^^^^^^^^^^^^^^^^^^^^^^^^
11+
| ^^^^^^^^^^^^^^^^^^^^^
1212
|
1313
note: lifetime parameter instantiated with the lifetime `'b` as defined on the struct at 11:15
1414
--> $DIR/region-bounds-on-objects-and-type-parameters.rs:11:15

src/test/ui/regions/regions-wf-trait-object.stderr

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
error[E0478]: lifetime bound not satisfied
2-
--> $DIR/regions-wf-trait-object.rs:7:5
2+
--> $DIR/regions-wf-trait-object.rs:7:8
33
|
44
LL | x: Box<dyn TheTrait<'a>+'b>
5-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
5+
| ^^^^^^^^^^^^^^^^^^^^^^^^
66
|
77
note: lifetime parameter instantiated with the lifetime `'b` as defined on the struct at 6:15
88
--> $DIR/regions-wf-trait-object.rs:6:15

src/test/ui/rfc-2093-infer-outlives/dont-infer-static.stderr

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
error[E0310]: the parameter type `U` may not live long enough
2-
--> $DIR/dont-infer-static.rs:8:5
2+
--> $DIR/dont-infer-static.rs:8:10
33
|
44
LL | struct Foo<U> {
55
| - help: consider adding an explicit lifetime bound...: `U: 'static`
66
LL | bar: Bar<U>
7-
| ^^^^^^^^^^^ ...so that the type `U` will meet its required lifetime bounds
7+
| ^^^^^^ ...so that the type `U` will meet its required lifetime bounds
88

99
error: aborting due to previous error
1010

src/test/ui/suggestions/adt-param-with-implicit-sized-bound.stderr

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
error[E0277]: the size for values of type `T` cannot be known at compilation time
2-
--> $DIR/adt-param-with-implicit-sized-bound.rs:25:5
2+
--> $DIR/adt-param-with-implicit-sized-bound.rs:25:9
33
|
44
LL | struct X<T>(T);
55
| - required by this bound in `X`
66
...
77
LL | struct Struct5<T: ?Sized>{
88
| - this type parameter needs to be `std::marker::Sized`
99
LL | _t: X<T>,
10-
| ^^^^^^^^ doesn't have a size known at compile-time
10+
| ^^^^ doesn't have a size known at compile-time
1111
|
1212
= help: the trait `std::marker::Sized` is not implemented for `T`
1313
= note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>

src/test/ui/traits/trait-bounds-on-structs-and-enums.stderr

+6-6
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,13 @@ LL | impl<T: Trait> Foo<T> {
1313
| ^^^^^^^
1414

1515
error[E0277]: the trait bound `isize: Trait` is not satisfied
16-
--> $DIR/trait-bounds-on-structs-and-enums.rs:19:5
16+
--> $DIR/trait-bounds-on-structs-and-enums.rs:19:8
1717
|
1818
LL | struct Foo<T:Trait> {
1919
| ----- required by this bound in `Foo`
2020
...
2121
LL | a: Foo<isize>,
22-
| ^^^^^^^^^^^^^ the trait `Trait` is not implemented for `isize`
22+
| ^^^^^^^^^^ the trait `Trait` is not implemented for `isize`
2323

2424
error[E0277]: the trait bound `usize: Trait` is not satisfied
2525
--> $DIR/trait-bounds-on-structs-and-enums.rs:23:10
@@ -31,13 +31,13 @@ LL | Quux(Bar<usize>),
3131
| ^^^^^^^^^^ the trait `Trait` is not implemented for `usize`
3232

3333
error[E0277]: the trait bound `U: Trait` is not satisfied
34-
--> $DIR/trait-bounds-on-structs-and-enums.rs:27:5
34+
--> $DIR/trait-bounds-on-structs-and-enums.rs:27:8
3535
|
3636
LL | struct Foo<T:Trait> {
3737
| ----- required by this bound in `Foo`
3838
...
3939
LL | b: Foo<U>,
40-
| ^^^^^^^^^ the trait `Trait` is not implemented for `U`
40+
| ^^^^^^ the trait `Trait` is not implemented for `U`
4141
|
4242
help: consider restricting type parameter `U`
4343
|
@@ -68,13 +68,13 @@ LL | Foo<i32>,
6868
| ^^^^^^^^ the trait `Trait` is not implemented for `i32`
6969

7070
error[E0277]: the trait bound `u8: Trait` is not satisfied
71-
--> $DIR/trait-bounds-on-structs-and-enums.rs:39:22
71+
--> $DIR/trait-bounds-on-structs-and-enums.rs:39:29
7272
|
7373
LL | enum Bar<T:Trait> {
7474
| ----- required by this bound in `Bar`
7575
...
7676
LL | DictionaryLike { field: Bar<u8> },
77-
| ^^^^^^^^^^^^^^ the trait `Trait` is not implemented for `u8`
77+
| ^^^^^^^ the trait `Trait` is not implemented for `u8`
7878

7979
error: aborting due to 7 previous errors
8080

src/test/ui/union/union-sized-field.stderr

+31-4
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,44 @@
11
error[E0277]: the size for values of type `T` cannot be known at compilation time
2-
--> $DIR/union-sized-field.rs:4:5
2+
--> $DIR/union-sized-field.rs:4:12
33
|
44
LL | union Foo<T: ?Sized> {
55
| - this type parameter needs to be `std::marker::Sized`
66
LL | value: T,
7-
| ^^^^^^^^ doesn't have a size known at compile-time
7+
| ^ doesn't have a size known at compile-time
88
|
99
= help: the trait `std::marker::Sized` is not implemented for `T`
1010
= note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
1111
= note: no field of a union may have a dynamically sized type
12+
= help: change the field's type to have a statically known size
13+
help: borrowed types always have a statically known size
14+
|
15+
LL | value: &T,
16+
| ^
17+
help: heap allocated types always have a statically known size
18+
|
19+
LL | value: Box<T>,
20+
| ^^^^ ^
1221

1322
error[E0277]: the size for values of type `T` cannot be known at compilation time
14-
--> $DIR/union-sized-field.rs:9:5
23+
--> $DIR/union-sized-field.rs:9:12
1524
|
1625
LL | struct Foo2<T: ?Sized> {
1726
| - this type parameter needs to be `std::marker::Sized`
1827
LL | value: T,
19-
| ^^^^^^^^ doesn't have a size known at compile-time
28+
| ^ doesn't have a size known at compile-time
2029
|
2130
= help: the trait `std::marker::Sized` is not implemented for `T`
2231
= note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
2332
= note: only the last field of a struct may have a dynamically sized type
33+
= help: change the field's type to have a statically known size
34+
help: borrowed types always have a statically known size
35+
|
36+
LL | value: &T,
37+
| ^
38+
help: heap allocated types always have a statically known size
39+
|
40+
LL | value: Box<T>,
41+
| ^^^^ ^
2442

2543
error[E0277]: the size for values of type `T` cannot be known at compilation time
2644
--> $DIR/union-sized-field.rs:15:11
@@ -33,6 +51,15 @@ LL | Value(T),
3351
= help: the trait `std::marker::Sized` is not implemented for `T`
3452
= note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
3553
= note: no field of an enum variant may have a dynamically sized type
54+
= help: change the field's type to have a statically known size
55+
help: borrowed types always have a statically known size
56+
|
57+
LL | Value(&T),
58+
| ^
59+
help: heap allocated types always have a statically known size
60+
|
61+
LL | Value(Box<T>),
62+
| ^^^^ ^
3663

3764
error: aborting due to 3 previous errors
3865

0 commit comments

Comments
 (0)