Skip to content

Commit 1634023

Browse files
committedAug 30, 2022
Register wf obligation before normalizing in wfcheck
1 parent 9f4d5d2 commit 1634023

32 files changed

+348
-227
lines changed
 

‎compiler/rustc_trait_selection/src/traits/fulfill.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -288,7 +288,8 @@ impl<'a, 'b, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'b, 'tcx> {
288288

289289
let infcx = self.selcx.infcx();
290290

291-
if obligation.predicate.has_projections() {
291+
// Normalizing WellFormed predicates is not sound, see #100041
292+
if obligation.predicate.has_projections() && obligation.predicate.allow_normalization() {
292293
let mut obligations = Vec::new();
293294
let predicate = crate::traits::project::try_normalize_with_depth_to(
294295
self.selcx,

‎compiler/rustc_typeck/src/check/wfcheck.rs

+2-35
Original file line numberDiff line numberDiff line change
@@ -991,7 +991,6 @@ fn check_associated_item(
991991
match item.kind {
992992
ty::AssocKind::Const => {
993993
let ty = tcx.type_of(item.def_id);
994-
let ty = wfcx.normalize(span, Some(WellFormedLoc::Ty(item_id)), ty);
995994
wfcx.register_wf_obligation(span, loc, ty.into());
996995
}
997996
ty::AssocKind::Fn => {
@@ -1012,7 +1011,6 @@ fn check_associated_item(
10121011
}
10131012
if item.defaultness(tcx).has_value() {
10141013
let ty = tcx.type_of(item.def_id);
1015-
let ty = wfcx.normalize(span, Some(WellFormedLoc::Ty(item_id)), ty);
10161014
wfcx.register_wf_obligation(span, loc, ty.into());
10171015
}
10181016
}
@@ -1188,6 +1186,8 @@ fn check_item_type(tcx: TyCtxt<'_>, item_id: LocalDefId, ty_span: Span, allow_fo
11881186

11891187
enter_wf_checking_ctxt(tcx, ty_span, item_id, |wfcx| {
11901188
let ty = tcx.type_of(item_id);
1189+
wfcx.register_wf_obligation(ty_span, Some(WellFormedLoc::Ty(item_id)), ty.into());
1190+
11911191
let item_ty = wfcx.normalize(ty_span, Some(WellFormedLoc::Ty(item_id)), ty);
11921192

11931193
let mut forbid_unsized = true;
@@ -1197,8 +1197,6 @@ fn check_item_type(tcx: TyCtxt<'_>, item_id: LocalDefId, ty_span: Span, allow_fo
11971197
forbid_unsized = false;
11981198
}
11991199
}
1200-
1201-
wfcx.register_wf_obligation(ty_span, Some(WellFormedLoc::Ty(item_id)), item_ty.into());
12021200
if forbid_unsized {
12031201
wfcx.register_bound(
12041202
traits::ObligationCause::new(ty_span, wfcx.body_id, traits::WellFormed(None)),
@@ -1262,7 +1260,6 @@ fn check_impl<'tcx>(
12621260
}
12631261
None => {
12641262
let self_ty = tcx.type_of(item.def_id);
1265-
let self_ty = wfcx.normalize(item.span, None, self_ty);
12661263
wfcx.register_wf_obligation(
12671264
ast_self_ty.span,
12681265
Some(WellFormedLoc::Ty(item.hir_id().expect_owner())),
@@ -1475,35 +1472,6 @@ fn check_fn_or_method<'tcx>(
14751472
let tcx = wfcx.tcx();
14761473
let sig = tcx.liberate_late_bound_regions(def_id.to_def_id(), sig);
14771474

1478-
// Normalize the input and output types one at a time, using a different
1479-
// `WellFormedLoc` for each. We cannot call `normalize_associated_types`
1480-
// on the entire `FnSig`, since this would use the same `WellFormedLoc`
1481-
// for each type, preventing the HIR wf check from generating
1482-
// a nice error message.
1483-
let ty::FnSig { mut inputs_and_output, c_variadic, unsafety, abi } = sig;
1484-
inputs_and_output = tcx.mk_type_list(inputs_and_output.iter().enumerate().map(|(i, ty)| {
1485-
wfcx.normalize(
1486-
span,
1487-
Some(WellFormedLoc::Param {
1488-
function: def_id,
1489-
// Note that the `param_idx` of the output type is
1490-
// one greater than the index of the last input type.
1491-
param_idx: i.try_into().unwrap(),
1492-
}),
1493-
ty,
1494-
)
1495-
}));
1496-
// Manually call `normalize_associated_types_in` on the other types
1497-
// in `FnSig`. This ensures that if the types of these fields
1498-
// ever change to include projections, we will start normalizing
1499-
// them automatically.
1500-
let sig = ty::FnSig {
1501-
inputs_and_output,
1502-
c_variadic: wfcx.normalize(span, None, c_variadic),
1503-
unsafety: wfcx.normalize(span, None, unsafety),
1504-
abi: wfcx.normalize(span, None, abi),
1505-
};
1506-
15071475
for (i, (&input_ty, ty)) in iter::zip(sig.inputs(), hir_decl.inputs).enumerate() {
15081476
wfcx.register_wf_obligation(
15091477
ty.span,
@@ -1886,7 +1854,6 @@ impl<'a, 'tcx> WfCheckingCtxt<'a, 'tcx> {
18861854
.map(|field| {
18871855
let def_id = self.tcx().hir().local_def_id(field.hir_id);
18881856
let field_ty = self.tcx().type_of(def_id);
1889-
let field_ty = self.normalize(field.ty.span, None, field_ty);
18901857
debug!("non_enum_variant: type of field {:?} is {:?}", field, field_ty);
18911858
AdtField { ty: field_ty, span: field.ty.span, def_id }
18921859
})

‎src/test/ui/associated-types/defaults-cyclic-fail-1.rs

-2
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,7 @@ impl Tr for u32 {
2424
// ...but not in an impl that redefines one of the types.
2525
impl Tr for bool {
2626
type A = Box<Self::B>;
27-
//~^ ERROR overflow evaluating the requirement `<bool as Tr>::B == _`
2827
}
29-
// (the error is shown twice for some reason)
3028

3129
impl Tr for usize {
3230
type B = &'static Self::A;
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,9 @@
1-
error[E0275]: overflow evaluating the requirement `<bool as Tr>::B == _`
2-
--> $DIR/defaults-cyclic-fail-1.rs:26:14
3-
|
4-
LL | type A = Box<Self::B>;
5-
| ^^^^^^^^^^^^
6-
71
error[E0275]: overflow evaluating the requirement `<usize as Tr>::A == _`
8-
--> $DIR/defaults-cyclic-fail-1.rs:32:14
2+
--> $DIR/defaults-cyclic-fail-1.rs:30:14
93
|
104
LL | type B = &'static Self::A;
115
| ^^^^^^^^^^^^^^^^
126

13-
error: aborting due to 2 previous errors
7+
error: aborting due to previous error
148

159
For more information about this error, try `rustc --explain E0275`.

‎src/test/ui/associated-types/defaults-cyclic-fail-2.rs

-2
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,7 @@ impl Tr for u32 {
2525

2626
impl Tr for bool {
2727
type A = Box<Self::B>;
28-
//~^ ERROR overflow evaluating the requirement `<bool as Tr>::B == _`
2928
}
30-
// (the error is shown twice for some reason)
3129

3230
impl Tr for usize {
3331
type B = &'static Self::A;
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,9 @@
1-
error[E0275]: overflow evaluating the requirement `<bool as Tr>::B == _`
2-
--> $DIR/defaults-cyclic-fail-2.rs:27:14
3-
|
4-
LL | type A = Box<Self::B>;
5-
| ^^^^^^^^^^^^
6-
71
error[E0275]: overflow evaluating the requirement `<usize as Tr>::A == _`
8-
--> $DIR/defaults-cyclic-fail-2.rs:33:14
2+
--> $DIR/defaults-cyclic-fail-2.rs:31:14
93
|
104
LL | type B = &'static Self::A;
115
| ^^^^^^^^^^^^^^^^
126

13-
error: aborting due to 2 previous errors
7+
error: aborting due to previous error
148

159
For more information about this error, try `rustc --explain E0275`.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
trait Wf {
2+
type Ty;
3+
}
4+
5+
impl<T: ?Sized> Wf for T {
6+
type Ty = ();
7+
}
8+
9+
const _: <Vec<str> as Wf>::Ty = ();
10+
//~^ ERROR the size for values of type `str` cannot be known at compilation time
11+
12+
struct Foo {
13+
x: <Vec<str> as Wf>::Ty,
14+
//~^ ERROR the size for values of type `str` cannot be known at compilation time
15+
}
16+
17+
fn foo(x: <Vec<str> as Wf>::Ty) {}
18+
//~^ ERROR the size for values of type `str` cannot be known at compilation time
19+
20+
fn bar() -> <Vec<str> as Wf>::Ty {}
21+
//~^ ERROR the size for values of type `str` cannot be known at compilation time
22+
23+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
error[E0277]: the size for values of type `str` cannot be known at compilation time
2+
--> $DIR/issue-100041.rs:9:11
3+
|
4+
LL | const _: <Vec<str> as Wf>::Ty = ();
5+
| ^^^^^^^^ doesn't have a size known at compile-time
6+
|
7+
= help: the trait `Sized` is not implemented for `str`
8+
note: required by a bound in `Vec`
9+
--> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
10+
|
11+
LL | pub struct Vec<T, #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global> {
12+
| ^ required by this bound in `Vec`
13+
14+
error[E0277]: the size for values of type `str` cannot be known at compilation time
15+
--> $DIR/issue-100041.rs:13:9
16+
|
17+
LL | x: <Vec<str> as Wf>::Ty,
18+
| ^^^^^^^^ doesn't have a size known at compile-time
19+
|
20+
= help: the trait `Sized` is not implemented for `str`
21+
note: required by a bound in `Vec`
22+
--> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
23+
|
24+
LL | pub struct Vec<T, #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global> {
25+
| ^ required by this bound in `Vec`
26+
27+
error[E0277]: the size for values of type `str` cannot be known at compilation time
28+
--> $DIR/issue-100041.rs:17:12
29+
|
30+
LL | fn foo(x: <Vec<str> as Wf>::Ty) {}
31+
| ^^^^^^^^ doesn't have a size known at compile-time
32+
|
33+
= help: the trait `Sized` is not implemented for `str`
34+
note: required by a bound in `Vec`
35+
--> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
36+
|
37+
LL | pub struct Vec<T, #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global> {
38+
| ^ required by this bound in `Vec`
39+
40+
error[E0277]: the size for values of type `str` cannot be known at compilation time
41+
--> $DIR/issue-100041.rs:20:13
42+
|
43+
LL | fn bar() -> <Vec<str> as Wf>::Ty {}
44+
| ^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
45+
|
46+
= help: the trait `Sized` is not implemented for `str`
47+
note: required by a bound in `Vec`
48+
--> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
49+
|
50+
LL | pub struct Vec<T, #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global> {
51+
| ^ required by this bound in `Vec`
52+
53+
error: aborting due to 4 previous errors
54+
55+
For more information about this error, try `rustc --explain E0277`.

‎src/test/ui/associated-types/issue-59324.rs

+1
Original file line numberDiff line numberDiff line change
@@ -22,5 +22,6 @@ pub trait ThriftService<Bug: NotFoo>:
2222

2323
fn with_factory<H>(factory: dyn ThriftService<()>) {}
2424
//~^ ERROR the trait bound `(): Foo` is not satisfied
25+
//~| ERROR the trait bound `(): NotFoo` is not satisfied
2526

2627
fn main() {}

‎src/test/ui/associated-types/issue-59324.stderr

+13-1
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,18 @@ error[E0277]: the trait bound `(): Foo` is not satisfied
5050
LL | fn with_factory<H>(factory: dyn ThriftService<()>) {}
5151
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `()`
5252

53+
error[E0277]: the trait bound `(): NotFoo` is not satisfied
54+
--> $DIR/issue-59324.rs:23:29
55+
|
56+
LL | fn with_factory<H>(factory: dyn ThriftService<()>) {}
57+
| ^^^^^^^^^^^^^^^^^^^^^ the trait `NotFoo` is not implemented for `()`
58+
|
59+
note: required by a bound in `Foo`
60+
--> $DIR/issue-59324.rs:3:16
61+
|
62+
LL | pub trait Foo: NotFoo {
63+
| ^^^^^^ required by this bound in `Foo`
64+
5365
error[E0277]: the trait bound `Bug: Foo` is not satisfied
5466
--> $DIR/issue-59324.rs:16:5
5567
|
@@ -65,6 +77,6 @@ help: consider further restricting this bound
6577
LL | pub trait ThriftService<Bug: NotFoo + Foo>:
6678
| +++++
6779

68-
error: aborting due to 5 previous errors
80+
error: aborting due to 6 previous errors
6981

7082
For more information about this error, try `rustc --explain E0277`.

‎src/test/ui/consts/const-size_of-cycle.stderr

+10-10
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,13 @@
1-
error[E0391]: cycle detected when evaluating type-level constant
1+
error[E0391]: cycle detected when const-evaluating + checking `Foo::bytes::{constant#0}`
22
--> $DIR/const-size_of-cycle.rs:4:17
33
|
44
LL | bytes: [u8; std::mem::size_of::<Foo>()]
55
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
66
|
7-
note: ...which requires const-evaluating + checking `Foo::bytes::{constant#0}`...
7+
= note: ...which requires computing layout of `Foo`...
8+
= note: ...which requires computing layout of `[u8; _]`...
9+
= note: ...which requires normalizing `[u8; _]`...
10+
note: ...which requires evaluating type-level constant...
811
--> $DIR/const-size_of-cycle.rs:4:17
912
|
1013
LL | bytes: [u8; std::mem::size_of::<Foo>()]
@@ -14,15 +17,12 @@ note: ...which requires const-evaluating + checking `Foo::bytes::{constant#0}`..
1417
|
1518
LL | bytes: [u8; std::mem::size_of::<Foo>()]
1619
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
17-
= note: ...which requires computing layout of `Foo`...
18-
= note: ...which requires computing layout of `[u8; _]`...
19-
= note: ...which requires normalizing `[u8; _]`...
20-
= note: ...which again requires evaluating type-level constant, completing the cycle
21-
note: cycle used when checking that `Foo` is well-formed
22-
--> $DIR/const-size_of-cycle.rs:3:1
20+
= note: ...which again requires const-evaluating + checking `Foo::bytes::{constant#0}`, completing the cycle
21+
note: cycle used when evaluating type-level constant
22+
--> $DIR/const-size_of-cycle.rs:4:17
2323
|
24-
LL | struct Foo {
25-
| ^^^^^^^^^^
24+
LL | bytes: [u8; std::mem::size_of::<Foo>()]
25+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
2626

2727
error: aborting due to previous error
2828

‎src/test/ui/consts/issue-44415.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ use std::intrinsics;
44

55
struct Foo {
66
bytes: [u8; unsafe { intrinsics::size_of::<Foo>() }],
7-
//~^ ERROR cycle detected when evaluating type-level constant
7+
//~^ ERROR cycle detected when const-evaluating + checking `Foo::bytes::{constant#0}`
88
x: usize,
99
}
1010

‎src/test/ui/consts/issue-44415.stderr

+10-10
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,13 @@
1-
error[E0391]: cycle detected when evaluating type-level constant
1+
error[E0391]: cycle detected when const-evaluating + checking `Foo::bytes::{constant#0}`
22
--> $DIR/issue-44415.rs:6:17
33
|
44
LL | bytes: [u8; unsafe { intrinsics::size_of::<Foo>() }],
55
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
66
|
7-
note: ...which requires const-evaluating + checking `Foo::bytes::{constant#0}`...
7+
= note: ...which requires computing layout of `Foo`...
8+
= note: ...which requires computing layout of `[u8; _]`...
9+
= note: ...which requires normalizing `[u8; _]`...
10+
note: ...which requires evaluating type-level constant...
811
--> $DIR/issue-44415.rs:6:17
912
|
1013
LL | bytes: [u8; unsafe { intrinsics::size_of::<Foo>() }],
@@ -14,15 +17,12 @@ note: ...which requires const-evaluating + checking `Foo::bytes::{constant#0}`..
1417
|
1518
LL | bytes: [u8; unsafe { intrinsics::size_of::<Foo>() }],
1619
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
17-
= note: ...which requires computing layout of `Foo`...
18-
= note: ...which requires computing layout of `[u8; _]`...
19-
= note: ...which requires normalizing `[u8; _]`...
20-
= note: ...which again requires evaluating type-level constant, completing the cycle
21-
note: cycle used when checking that `Foo` is well-formed
22-
--> $DIR/issue-44415.rs:5:1
20+
= note: ...which again requires const-evaluating + checking `Foo::bytes::{constant#0}`, completing the cycle
21+
note: cycle used when evaluating type-level constant
22+
--> $DIR/issue-44415.rs:6:17
2323
|
24-
LL | struct Foo {
25-
| ^^^^^^^^^^
24+
LL | bytes: [u8; unsafe { intrinsics::size_of::<Foo>() }],
25+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
2626

2727
error: aborting due to previous error
2828

‎src/test/ui/fn/implied-bounds-unnorm-associated-type-2.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ impl<T> Trait for T {
99
}
1010

1111
fn f<'a, 'b>(_: <&'a &'b () as Trait>::Type)
12+
//~^ ERROR in type `&'a &'b ()`, reference has a longer lifetime than the data it references
1213
where
1314
'a: 'a,
1415
'b: 'b,
@@ -17,7 +18,6 @@ where
1718

1819
fn g<'a, 'b>() {
1920
f::<'a, 'b>(());
20-
//~^ ERROR lifetime may not live long enough
2121
}
2222

2323
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,20 @@
1-
error: lifetime may not live long enough
2-
--> $DIR/implied-bounds-unnorm-associated-type-2.rs:19:5
1+
error[E0491]: in type `&'a &'b ()`, reference has a longer lifetime than the data it references
2+
--> $DIR/implied-bounds-unnorm-associated-type-2.rs:11:17
33
|
4-
LL | fn g<'a, 'b>() {
5-
| -- -- lifetime `'b` defined here
6-
| |
7-
| lifetime `'a` defined here
8-
LL | f::<'a, 'b>(());
9-
| ^^^^^^^^^^^^^^^ requires that `'b` must outlive `'a`
4+
LL | fn f<'a, 'b>(_: <&'a &'b () as Trait>::Type)
5+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
106
|
11-
= help: consider adding the following bound: `'b: 'a`
12-
= note: requirement occurs because of a function pointer to `f`
13-
= note: the function `f` is invariant over the parameter `'a`
14-
= help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
7+
note: the pointer is valid for the lifetime `'a` as defined here
8+
--> $DIR/implied-bounds-unnorm-associated-type-2.rs:11:6
9+
|
10+
LL | fn f<'a, 'b>(_: <&'a &'b () as Trait>::Type)
11+
| ^^
12+
note: but the referenced data is only valid for the lifetime `'b` as defined here
13+
--> $DIR/implied-bounds-unnorm-associated-type-2.rs:11:10
14+
|
15+
LL | fn f<'a, 'b>(_: <&'a &'b () as Trait>::Type)
16+
| ^^
1517

1618
error: aborting due to previous error
1719

20+
For more information about this error, try `rustc --explain E0491`.

0 commit comments

Comments
 (0)
Please sign in to comment.