Skip to content

Commit 9479792

Browse files
committed
WF-check struct field types at construction site
Rustc of course already WF-checked the field types at the definition site, but for error tainting of consts to work properly, there needs to be an error emitted at the use site. Previously, with no use-site error, we proceeded with CTFE and ran into ICEs since we are running code with type errors. Emitting use-site errors also brings struct-like constructors more in line with fn-like constructors since they already emit use-site errors for WF issues.
1 parent 1890675 commit 9479792

17 files changed

+387
-57
lines changed

Diff for: compiler/rustc_hir_typeck/src/expr.rs

+9
Original file line numberDiff line numberDiff line change
@@ -1736,6 +1736,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
17361736
Ty::new_error(tcx, guar)
17371737
};
17381738

1739+
// Check that the expected field type is WF. Otherwise, we emit no use-site error
1740+
// in the case of coercions for non-WF fields, which leads to incorrect error
1741+
// tainting. See issue #126272.
1742+
self.register_wf_obligation(
1743+
field_type.into(),
1744+
field.expr.span,
1745+
ObligationCauseCode::WellFormed(None),
1746+
);
1747+
17391748
// Make sure to give a type to the field even if there's
17401749
// an error, so we can continue type-checking.
17411750
let ty = self.check_expr_with_hint(field.expr, field_type);

Diff for: tests/crashes/126272.rs

-28
This file was deleted.

Diff for: tests/crashes/127299.rs

-12
This file was deleted.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
// This ensures we don't ICE in situations like rust-lang/rust#126272.
2+
3+
#![feature(adt_const_params)]
4+
#![allow(incomplete_features)]
5+
6+
use std::marker::ConstParamTy;
7+
8+
#[derive(Debug, PartialEq, Eq, ConstParamTy)]
9+
//~^ ERROR the trait `ConstParamTy_`
10+
//~| ERROR the trait `ConstParamTy_`
11+
struct Foo {
12+
nested: &'static Bar<dyn std::fmt::Debug>,
13+
//~^ ERROR the size for values
14+
//~| ERROR the size for values
15+
//~| ERROR binary operation `==` cannot
16+
//~| ERROR the trait bound `dyn Debug: Eq`
17+
//~| ERROR the size for values
18+
}
19+
20+
#[derive(Debug, PartialEq, Eq, ConstParamTy)]
21+
struct Bar<T>(T);
22+
23+
struct Test<const F: Foo>;
24+
25+
fn main() {
26+
let x: Test<{ Foo { nested: &Bar(4) } }> = Test;
27+
//~^ ERROR the size for values
28+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,160 @@
1+
error[E0277]: the size for values of type `(dyn Debug + 'static)` cannot be known at compilation time
2+
--> $DIR/unsizing-wfcheck-issue-126272.rs:12:13
3+
|
4+
LL | nested: &'static Bar<dyn std::fmt::Debug>,
5+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
6+
|
7+
= help: the trait `Sized` is not implemented for `(dyn Debug + 'static)`
8+
note: required by an implicit `Sized` bound in `Bar`
9+
--> $DIR/unsizing-wfcheck-issue-126272.rs:21:12
10+
|
11+
LL | struct Bar<T>(T);
12+
| ^ required by the implicit `Sized` requirement on this type parameter in `Bar`
13+
help: you could relax the implicit `Sized` bound on `T` if it were used through indirection like `&T` or `Box<T>`
14+
--> $DIR/unsizing-wfcheck-issue-126272.rs:21:12
15+
|
16+
LL | struct Bar<T>(T);
17+
| ^ - ...if indirection were used here: `Box<T>`
18+
| |
19+
| this could be changed to `T: ?Sized`...
20+
21+
error[E0204]: the trait `ConstParamTy_` cannot be implemented for this type
22+
--> $DIR/unsizing-wfcheck-issue-126272.rs:8:32
23+
|
24+
LL | #[derive(Debug, PartialEq, Eq, ConstParamTy)]
25+
| ^^^^^^^^^^^^
26+
...
27+
LL | nested: &'static Bar<dyn std::fmt::Debug>,
28+
| ----------------------------------------- this field does not implement `ConstParamTy_`
29+
|
30+
= note: this error originates in the derive macro `ConstParamTy` (in Nightly builds, run with -Z macro-backtrace for more info)
31+
32+
error[E0204]: the trait `ConstParamTy_` cannot be implemented for this type
33+
--> $DIR/unsizing-wfcheck-issue-126272.rs:8:32
34+
|
35+
LL | #[derive(Debug, PartialEq, Eq, ConstParamTy)]
36+
| ^^^^^^^^^^^^
37+
...
38+
LL | nested: &'static Bar<dyn std::fmt::Debug>,
39+
| ----------------------------------------- this field does not implement `ConstParamTy_`
40+
|
41+
note: the `ConstParamTy_` impl for `&'static Bar<(dyn Debug + 'static)>` requires that `(dyn Debug + 'static): Eq`
42+
--> $DIR/unsizing-wfcheck-issue-126272.rs:12:13
43+
|
44+
LL | nested: &'static Bar<dyn std::fmt::Debug>,
45+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
46+
note: the `ConstParamTy_` impl for `&'static Bar<(dyn Debug + 'static)>` requires that `(dyn Debug + 'static): Sized`
47+
--> $DIR/unsizing-wfcheck-issue-126272.rs:12:13
48+
|
49+
LL | nested: &'static Bar<dyn std::fmt::Debug>,
50+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
51+
note: the `ConstParamTy_` impl for `&'static Bar<(dyn Debug + 'static)>` requires that `(dyn Debug + 'static): UnsizedConstParamTy`
52+
--> $DIR/unsizing-wfcheck-issue-126272.rs:12:13
53+
|
54+
LL | nested: &'static Bar<dyn std::fmt::Debug>,
55+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
56+
= note: this error originates in the derive macro `ConstParamTy` (in Nightly builds, run with -Z macro-backtrace for more info)
57+
58+
error[E0277]: the size for values of type `(dyn Debug + 'static)` cannot be known at compilation time
59+
--> $DIR/unsizing-wfcheck-issue-126272.rs:12:5
60+
|
61+
LL | #[derive(Debug, PartialEq, Eq, ConstParamTy)]
62+
| ----- in this derive macro expansion
63+
...
64+
LL | nested: &'static Bar<dyn std::fmt::Debug>,
65+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
66+
|
67+
= help: the trait `Sized` is not implemented for `(dyn Debug + 'static)`, which is required by `&&'static Bar<(dyn Debug + 'static)>: Debug`
68+
= help: the trait `Debug` is implemented for `Bar<T>`
69+
note: required for `Bar<(dyn Debug + 'static)>` to implement `Debug`
70+
--> $DIR/unsizing-wfcheck-issue-126272.rs:20:10
71+
|
72+
LL | #[derive(Debug, PartialEq, Eq, ConstParamTy)]
73+
| ^^^^^
74+
LL | struct Bar<T>(T);
75+
| - unsatisfied trait bound introduced in this `derive` macro
76+
= note: 2 redundant requirements hidden
77+
= note: required for `&&'static Bar<(dyn Debug + 'static)>` to implement `Debug`
78+
= note: required for the cast from `&&&'static Bar<(dyn Debug + 'static)>` to `&dyn Debug`
79+
= note: this error originates in the derive macro `Debug` (in Nightly builds, run with -Z macro-backtrace for more info)
80+
81+
error[E0369]: binary operation `==` cannot be applied to type `&Bar<dyn Debug>`
82+
--> $DIR/unsizing-wfcheck-issue-126272.rs:12:5
83+
|
84+
LL | #[derive(Debug, PartialEq, Eq, ConstParamTy)]
85+
| --------- in this derive macro expansion
86+
...
87+
LL | nested: &'static Bar<dyn std::fmt::Debug>,
88+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
89+
|
90+
= note: this error originates in the derive macro `PartialEq` (in Nightly builds, run with -Z macro-backtrace for more info)
91+
92+
error[E0277]: the trait bound `dyn Debug: Eq` is not satisfied
93+
--> $DIR/unsizing-wfcheck-issue-126272.rs:12:5
94+
|
95+
LL | #[derive(Debug, PartialEq, Eq, ConstParamTy)]
96+
| -- in this derive macro expansion
97+
...
98+
LL | nested: &'static Bar<dyn std::fmt::Debug>,
99+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Eq` is not implemented for `dyn Debug`, which is required by `&'static Bar<dyn Debug>: Eq`
100+
|
101+
= help: the trait `Eq` is implemented for `Bar<T>`
102+
note: required for `Bar<dyn Debug>` to implement `Eq`
103+
--> $DIR/unsizing-wfcheck-issue-126272.rs:20:28
104+
|
105+
LL | #[derive(Debug, PartialEq, Eq, ConstParamTy)]
106+
| ^^ unsatisfied trait bound introduced in this `derive` macro
107+
= note: 1 redundant requirement hidden
108+
= note: required for `&'static Bar<dyn Debug>` to implement `Eq`
109+
note: required by a bound in `AssertParamIsEq`
110+
--> $SRC_DIR/core/src/cmp.rs:LL:COL
111+
= note: this error originates in the derive macro `Eq` (in Nightly builds, run with -Z macro-backtrace for more info)
112+
113+
error[E0277]: the size for values of type `dyn Debug` cannot be known at compilation time
114+
--> $DIR/unsizing-wfcheck-issue-126272.rs:12:5
115+
|
116+
LL | #[derive(Debug, PartialEq, Eq, ConstParamTy)]
117+
| -- in this derive macro expansion
118+
...
119+
LL | nested: &'static Bar<dyn std::fmt::Debug>,
120+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
121+
|
122+
= help: the trait `Sized` is not implemented for `dyn Debug`
123+
note: required by an implicit `Sized` bound in `Bar`
124+
--> $DIR/unsizing-wfcheck-issue-126272.rs:21:12
125+
|
126+
LL | struct Bar<T>(T);
127+
| ^ required by the implicit `Sized` requirement on this type parameter in `Bar`
128+
help: you could relax the implicit `Sized` bound on `T` if it were used through indirection like `&T` or `Box<T>`
129+
--> $DIR/unsizing-wfcheck-issue-126272.rs:21:12
130+
|
131+
LL | struct Bar<T>(T);
132+
| ^ - ...if indirection were used here: `Box<T>`
133+
| |
134+
| this could be changed to `T: ?Sized`...
135+
= note: this error originates in the derive macro `Eq` (in Nightly builds, run with -Z macro-backtrace for more info)
136+
137+
error[E0277]: the size for values of type `(dyn Debug + 'static)` cannot be known at compilation time
138+
--> $DIR/unsizing-wfcheck-issue-126272.rs:26:33
139+
|
140+
LL | let x: Test<{ Foo { nested: &Bar(4) } }> = Test;
141+
| ^^^^^^^ doesn't have a size known at compile-time
142+
|
143+
= help: the trait `Sized` is not implemented for `(dyn Debug + 'static)`
144+
note: required by an implicit `Sized` bound in `Bar`
145+
--> $DIR/unsizing-wfcheck-issue-126272.rs:21:12
146+
|
147+
LL | struct Bar<T>(T);
148+
| ^ required by the implicit `Sized` requirement on this type parameter in `Bar`
149+
help: you could relax the implicit `Sized` bound on `T` if it were used through indirection like `&T` or `Box<T>`
150+
--> $DIR/unsizing-wfcheck-issue-126272.rs:21:12
151+
|
152+
LL | struct Bar<T>(T);
153+
| ^ - ...if indirection were used here: `Box<T>`
154+
| |
155+
| this could be changed to `T: ?Sized`...
156+
157+
error: aborting due to 8 previous errors
158+
159+
Some errors have detailed explanations: E0204, E0277, E0369.
160+
For more information about an error, try `rustc --explain E0204`.

Diff for: tests/ui/const-generics/generic_const_exprs/no_where_clause.rs

+1
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ impl<const N: usize> Example<N> {
1717
a: [0.; N],
1818
b: [0.; complex_maths(N)],
1919
//~^ ERROR: unconstrained generic constant
20+
//~| ERROR: unconstrained generic constant
2021
}
2122
}
2223
}

Diff for: tests/ui/const-generics/generic_const_exprs/no_where_clause.stderr

+12-1
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,17 @@ help: try adding a `where` bound
99
LL | pub struct Example<const N: usize> where [(); complex_maths(N)]: {
1010
| +++++++++++++++++++++++++++++
1111

12+
error: unconstrained generic constant
13+
--> $DIR/no_where_clause.rs:18:10
14+
|
15+
LL | b: [0.; complex_maths(N)],
16+
| ^^^^^^^^^^^^^^^^^^^^^^
17+
|
18+
help: try adding a `where` bound
19+
|
20+
LL | pub fn new() -> Self where [(); complex_maths(N)]: {
21+
| +++++++++++++++++++++++++++++
22+
1223
error: unconstrained generic constant
1324
--> $DIR/no_where_clause.rs:18:15
1425
|
@@ -20,5 +31,5 @@ help: try adding a `where` bound
2031
LL | pub fn new() -> Self where [(); complex_maths(N)]: {
2132
| +++++++++++++++++++++++++++++
2233

23-
error: aborting due to 2 previous errors
34+
error: aborting due to 3 previous errors
2435

Diff for: tests/ui/generic-associated-types/issue-71176.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,6 @@ struct Holder<B> {
1616

1717
fn main() {
1818
Holder {
19-
inner: Box::new(()),
19+
inner: Box::new(()), //~ ERROR: the trait `Provider` cannot be made into an object
2020
};
2121
}

Diff for: tests/ui/generic-associated-types/issue-71176.stderr

+17-1
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,23 @@ LL | type A<'a>;
6464
= help: consider moving `A` to another trait
6565
= help: only type `()` implements the trait, consider using it directly instead
6666

67-
error: aborting due to 4 previous errors
67+
error[E0038]: the trait `Provider` cannot be made into an object
68+
--> $DIR/issue-71176.rs:19:16
69+
|
70+
LL | inner: Box::new(()),
71+
| ^^^^^^^^^^^^ `Provider` cannot be made into an object
72+
|
73+
note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
74+
--> $DIR/issue-71176.rs:2:10
75+
|
76+
LL | trait Provider {
77+
| -------- this trait cannot be made into an object...
78+
LL | type A<'a>;
79+
| ^ ...because it contains the generic associated type `A`
80+
= help: consider moving `A` to another trait
81+
= help: only type `()` implements the trait, consider using it directly instead
82+
83+
error: aborting due to 5 previous errors
6884

6985
Some errors have detailed explanations: E0038, E0107.
7086
For more information about an error, try `rustc --explain E0038`.

Diff for: tests/ui/issues/issue-19380.rs

+1
Original file line numberDiff line numberDiff line change
@@ -15,5 +15,6 @@ struct Bar {
1515
const FOO : Foo = Foo;
1616
const BAR : Bar = Bar { foos: &[&FOO]};
1717
//~^ ERROR E0038
18+
//~| ERROR E0038
1819

1920
fn main() { }

Diff for: tests/ui/issues/issue-19380.stderr

+24-1
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,29 @@ help: alternatively, consider constraining `qiz` so it does not apply to trait o
4545
LL | fn qiz() where Self: Sized;
4646
| +++++++++++++++++
4747

48-
error: aborting due to 2 previous errors
48+
error[E0038]: the trait `Qiz` cannot be made into an object
49+
--> $DIR/issue-19380.rs:16:31
50+
|
51+
LL | const BAR : Bar = Bar { foos: &[&FOO]};
52+
| ^^^^^^^ `Qiz` cannot be made into an object
53+
|
54+
note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
55+
--> $DIR/issue-19380.rs:2:6
56+
|
57+
LL | trait Qiz {
58+
| --- this trait cannot be made into an object...
59+
LL | fn qiz();
60+
| ^^^ ...because associated function `qiz` has no `self` parameter
61+
= help: only type `Foo` implements the trait, consider using it directly instead
62+
help: consider turning `qiz` into a method by giving it a `&self` argument
63+
|
64+
LL | fn qiz(&self);
65+
| +++++
66+
help: alternatively, consider constraining `qiz` so it does not apply to trait objects
67+
|
68+
LL | fn qiz() where Self: Sized;
69+
| +++++++++++++++++
70+
71+
error: aborting due to 3 previous errors
4972

5073
For more information about this error, try `rustc --explain E0038`.

Diff for: tests/ui/statics/unsizing-wfcheck-issue-127299.rs

+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
// This ensures we don't ICE in situations like rust-lang/rust#127299.
2+
3+
trait Qux {
4+
fn bar() -> i32;
5+
}
6+
7+
pub struct Lint {
8+
pub desc: &'static dyn Qux,
9+
//~^ ERROR cannot be made into an object
10+
}
11+
12+
static FOO: &Lint = &Lint { desc: "desc" };
13+
//~^ ERROR cannot be shared between threads safely
14+
//~| ERROR cannot be made into an object
15+
//~| ERROR cannot be made into an object
16+
17+
fn main() {}

0 commit comments

Comments
 (0)