Skip to content

Commit

Permalink
Register wf obligation before normalizing in wfcheck
Browse files Browse the repository at this point in the history
  • Loading branch information
compiler-errors committed Aug 30, 2022
1 parent 9f4d5d2 commit 1634023
Show file tree
Hide file tree
Showing 32 changed files with 348 additions and 227 deletions.
3 changes: 2 additions & 1 deletion compiler/rustc_trait_selection/src/traits/fulfill.rs
Original file line number Diff line number Diff line change
Expand Up @@ -288,7 +288,8 @@ impl<'a, 'b, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'b, 'tcx> {

let infcx = self.selcx.infcx();

if obligation.predicate.has_projections() {
// Normalizing WellFormed predicates is not sound, see #100041
if obligation.predicate.has_projections() && obligation.predicate.allow_normalization() {
let mut obligations = Vec::new();
let predicate = crate::traits::project::try_normalize_with_depth_to(
self.selcx,
Expand Down
37 changes: 2 additions & 35 deletions compiler/rustc_typeck/src/check/wfcheck.rs
Original file line number Diff line number Diff line change
Expand Up @@ -991,7 +991,6 @@ fn check_associated_item(
match item.kind {
ty::AssocKind::Const => {
let ty = tcx.type_of(item.def_id);
let ty = wfcx.normalize(span, Some(WellFormedLoc::Ty(item_id)), ty);
wfcx.register_wf_obligation(span, loc, ty.into());
}
ty::AssocKind::Fn => {
Expand All @@ -1012,7 +1011,6 @@ fn check_associated_item(
}
if item.defaultness(tcx).has_value() {
let ty = tcx.type_of(item.def_id);
let ty = wfcx.normalize(span, Some(WellFormedLoc::Ty(item_id)), ty);
wfcx.register_wf_obligation(span, loc, ty.into());
}
}
Expand Down Expand Up @@ -1188,6 +1186,8 @@ fn check_item_type(tcx: TyCtxt<'_>, item_id: LocalDefId, ty_span: Span, allow_fo

enter_wf_checking_ctxt(tcx, ty_span, item_id, |wfcx| {
let ty = tcx.type_of(item_id);
wfcx.register_wf_obligation(ty_span, Some(WellFormedLoc::Ty(item_id)), ty.into());

let item_ty = wfcx.normalize(ty_span, Some(WellFormedLoc::Ty(item_id)), ty);

let mut forbid_unsized = true;
Expand All @@ -1197,8 +1197,6 @@ fn check_item_type(tcx: TyCtxt<'_>, item_id: LocalDefId, ty_span: Span, allow_fo
forbid_unsized = false;
}
}

wfcx.register_wf_obligation(ty_span, Some(WellFormedLoc::Ty(item_id)), item_ty.into());
if forbid_unsized {
wfcx.register_bound(
traits::ObligationCause::new(ty_span, wfcx.body_id, traits::WellFormed(None)),
Expand Down Expand Up @@ -1262,7 +1260,6 @@ fn check_impl<'tcx>(
}
None => {
let self_ty = tcx.type_of(item.def_id);
let self_ty = wfcx.normalize(item.span, None, self_ty);
wfcx.register_wf_obligation(
ast_self_ty.span,
Some(WellFormedLoc::Ty(item.hir_id().expect_owner())),
Expand Down Expand Up @@ -1475,35 +1472,6 @@ fn check_fn_or_method<'tcx>(
let tcx = wfcx.tcx();
let sig = tcx.liberate_late_bound_regions(def_id.to_def_id(), sig);

// Normalize the input and output types one at a time, using a different
// `WellFormedLoc` for each. We cannot call `normalize_associated_types`
// on the entire `FnSig`, since this would use the same `WellFormedLoc`
// for each type, preventing the HIR wf check from generating
// a nice error message.
let ty::FnSig { mut inputs_and_output, c_variadic, unsafety, abi } = sig;
inputs_and_output = tcx.mk_type_list(inputs_and_output.iter().enumerate().map(|(i, ty)| {
wfcx.normalize(
span,
Some(WellFormedLoc::Param {
function: def_id,
// Note that the `param_idx` of the output type is
// one greater than the index of the last input type.
param_idx: i.try_into().unwrap(),
}),
ty,
)
}));
// Manually call `normalize_associated_types_in` on the other types
// in `FnSig`. This ensures that if the types of these fields
// ever change to include projections, we will start normalizing
// them automatically.
let sig = ty::FnSig {
inputs_and_output,
c_variadic: wfcx.normalize(span, None, c_variadic),
unsafety: wfcx.normalize(span, None, unsafety),
abi: wfcx.normalize(span, None, abi),
};

for (i, (&input_ty, ty)) in iter::zip(sig.inputs(), hir_decl.inputs).enumerate() {
wfcx.register_wf_obligation(
ty.span,
Expand Down Expand Up @@ -1886,7 +1854,6 @@ impl<'a, 'tcx> WfCheckingCtxt<'a, 'tcx> {
.map(|field| {
let def_id = self.tcx().hir().local_def_id(field.hir_id);
let field_ty = self.tcx().type_of(def_id);
let field_ty = self.normalize(field.ty.span, None, field_ty);
debug!("non_enum_variant: type of field {:?} is {:?}", field, field_ty);
AdtField { ty: field_ty, span: field.ty.span, def_id }
})
Expand Down
2 changes: 0 additions & 2 deletions src/test/ui/associated-types/defaults-cyclic-fail-1.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,7 @@ impl Tr for u32 {
// ...but not in an impl that redefines one of the types.
impl Tr for bool {
type A = Box<Self::B>;
//~^ ERROR overflow evaluating the requirement `<bool as Tr>::B == _`
}
// (the error is shown twice for some reason)

impl Tr for usize {
type B = &'static Self::A;
Expand Down
10 changes: 2 additions & 8 deletions src/test/ui/associated-types/defaults-cyclic-fail-1.stderr
Original file line number Diff line number Diff line change
@@ -1,15 +1,9 @@
error[E0275]: overflow evaluating the requirement `<bool as Tr>::B == _`
--> $DIR/defaults-cyclic-fail-1.rs:26:14
|
LL | type A = Box<Self::B>;
| ^^^^^^^^^^^^

error[E0275]: overflow evaluating the requirement `<usize as Tr>::A == _`
--> $DIR/defaults-cyclic-fail-1.rs:32:14
--> $DIR/defaults-cyclic-fail-1.rs:30:14
|
LL | type B = &'static Self::A;
| ^^^^^^^^^^^^^^^^

error: aborting due to 2 previous errors
error: aborting due to previous error

For more information about this error, try `rustc --explain E0275`.
2 changes: 0 additions & 2 deletions src/test/ui/associated-types/defaults-cyclic-fail-2.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,7 @@ impl Tr for u32 {

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

impl Tr for usize {
type B = &'static Self::A;
Expand Down
10 changes: 2 additions & 8 deletions src/test/ui/associated-types/defaults-cyclic-fail-2.stderr
Original file line number Diff line number Diff line change
@@ -1,15 +1,9 @@
error[E0275]: overflow evaluating the requirement `<bool as Tr>::B == _`
--> $DIR/defaults-cyclic-fail-2.rs:27:14
|
LL | type A = Box<Self::B>;
| ^^^^^^^^^^^^

error[E0275]: overflow evaluating the requirement `<usize as Tr>::A == _`
--> $DIR/defaults-cyclic-fail-2.rs:33:14
--> $DIR/defaults-cyclic-fail-2.rs:31:14
|
LL | type B = &'static Self::A;
| ^^^^^^^^^^^^^^^^

error: aborting due to 2 previous errors
error: aborting due to previous error

For more information about this error, try `rustc --explain E0275`.
23 changes: 23 additions & 0 deletions src/test/ui/associated-types/issue-100041.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
trait Wf {
type Ty;
}

impl<T: ?Sized> Wf for T {
type Ty = ();
}

const _: <Vec<str> as Wf>::Ty = ();
//~^ ERROR the size for values of type `str` cannot be known at compilation time

struct Foo {
x: <Vec<str> as Wf>::Ty,
//~^ ERROR the size for values of type `str` cannot be known at compilation time
}

fn foo(x: <Vec<str> as Wf>::Ty) {}
//~^ ERROR the size for values of type `str` cannot be known at compilation time

fn bar() -> <Vec<str> as Wf>::Ty {}
//~^ ERROR the size for values of type `str` cannot be known at compilation time

fn main() {}
55 changes: 55 additions & 0 deletions src/test/ui/associated-types/issue-100041.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
error[E0277]: the size for values of type `str` cannot be known at compilation time
--> $DIR/issue-100041.rs:9:11
|
LL | const _: <Vec<str> as Wf>::Ty = ();
| ^^^^^^^^ doesn't have a size known at compile-time
|
= help: the trait `Sized` is not implemented for `str`
note: required by a bound in `Vec`
--> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
|
LL | pub struct Vec<T, #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global> {
| ^ required by this bound in `Vec`

error[E0277]: the size for values of type `str` cannot be known at compilation time
--> $DIR/issue-100041.rs:13:9
|
LL | x: <Vec<str> as Wf>::Ty,
| ^^^^^^^^ doesn't have a size known at compile-time
|
= help: the trait `Sized` is not implemented for `str`
note: required by a bound in `Vec`
--> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
|
LL | pub struct Vec<T, #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global> {
| ^ required by this bound in `Vec`

error[E0277]: the size for values of type `str` cannot be known at compilation time
--> $DIR/issue-100041.rs:17:12
|
LL | fn foo(x: <Vec<str> as Wf>::Ty) {}
| ^^^^^^^^ doesn't have a size known at compile-time
|
= help: the trait `Sized` is not implemented for `str`
note: required by a bound in `Vec`
--> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
|
LL | pub struct Vec<T, #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global> {
| ^ required by this bound in `Vec`

error[E0277]: the size for values of type `str` cannot be known at compilation time
--> $DIR/issue-100041.rs:20:13
|
LL | fn bar() -> <Vec<str> as Wf>::Ty {}
| ^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
|
= help: the trait `Sized` is not implemented for `str`
note: required by a bound in `Vec`
--> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
|
LL | pub struct Vec<T, #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global> {
| ^ required by this bound in `Vec`

error: aborting due to 4 previous errors

For more information about this error, try `rustc --explain E0277`.
1 change: 1 addition & 0 deletions src/test/ui/associated-types/issue-59324.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,5 +22,6 @@ pub trait ThriftService<Bug: NotFoo>:

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

fn main() {}
14 changes: 13 additions & 1 deletion src/test/ui/associated-types/issue-59324.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,18 @@ error[E0277]: the trait bound `(): Foo` is not satisfied
LL | fn with_factory<H>(factory: dyn ThriftService<()>) {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `()`

error[E0277]: the trait bound `(): NotFoo` is not satisfied
--> $DIR/issue-59324.rs:23:29
|
LL | fn with_factory<H>(factory: dyn ThriftService<()>) {}
| ^^^^^^^^^^^^^^^^^^^^^ the trait `NotFoo` is not implemented for `()`
|
note: required by a bound in `Foo`
--> $DIR/issue-59324.rs:3:16
|
LL | pub trait Foo: NotFoo {
| ^^^^^^ required by this bound in `Foo`

error[E0277]: the trait bound `Bug: Foo` is not satisfied
--> $DIR/issue-59324.rs:16:5
|
Expand All @@ -65,6 +77,6 @@ help: consider further restricting this bound
LL | pub trait ThriftService<Bug: NotFoo + Foo>:
| +++++

error: aborting due to 5 previous errors
error: aborting due to 6 previous errors

For more information about this error, try `rustc --explain E0277`.
20 changes: 10 additions & 10 deletions src/test/ui/consts/const-size_of-cycle.stderr
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
error[E0391]: cycle detected when evaluating type-level constant
error[E0391]: cycle detected when const-evaluating + checking `Foo::bytes::{constant#0}`
--> $DIR/const-size_of-cycle.rs:4:17
|
LL | bytes: [u8; std::mem::size_of::<Foo>()]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
note: ...which requires const-evaluating + checking `Foo::bytes::{constant#0}`...
= note: ...which requires computing layout of `Foo`...
= note: ...which requires computing layout of `[u8; _]`...
= note: ...which requires normalizing `[u8; _]`...
note: ...which requires evaluating type-level constant...
--> $DIR/const-size_of-cycle.rs:4:17
|
LL | bytes: [u8; std::mem::size_of::<Foo>()]
Expand All @@ -14,15 +17,12 @@ note: ...which requires const-evaluating + checking `Foo::bytes::{constant#0}`..
|
LL | bytes: [u8; std::mem::size_of::<Foo>()]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
= note: ...which requires computing layout of `Foo`...
= note: ...which requires computing layout of `[u8; _]`...
= note: ...which requires normalizing `[u8; _]`...
= note: ...which again requires evaluating type-level constant, completing the cycle
note: cycle used when checking that `Foo` is well-formed
--> $DIR/const-size_of-cycle.rs:3:1
= note: ...which again requires const-evaluating + checking `Foo::bytes::{constant#0}`, completing the cycle
note: cycle used when evaluating type-level constant
--> $DIR/const-size_of-cycle.rs:4:17
|
LL | struct Foo {
| ^^^^^^^^^^
LL | bytes: [u8; std::mem::size_of::<Foo>()]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^

error: aborting due to previous error

Expand Down
2 changes: 1 addition & 1 deletion src/test/ui/consts/issue-44415.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use std::intrinsics;

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

Expand Down
20 changes: 10 additions & 10 deletions src/test/ui/consts/issue-44415.stderr
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
error[E0391]: cycle detected when evaluating type-level constant
error[E0391]: cycle detected when const-evaluating + checking `Foo::bytes::{constant#0}`
--> $DIR/issue-44415.rs:6:17
|
LL | bytes: [u8; unsafe { intrinsics::size_of::<Foo>() }],
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
note: ...which requires const-evaluating + checking `Foo::bytes::{constant#0}`...
= note: ...which requires computing layout of `Foo`...
= note: ...which requires computing layout of `[u8; _]`...
= note: ...which requires normalizing `[u8; _]`...
note: ...which requires evaluating type-level constant...
--> $DIR/issue-44415.rs:6:17
|
LL | bytes: [u8; unsafe { intrinsics::size_of::<Foo>() }],
Expand All @@ -14,15 +17,12 @@ note: ...which requires const-evaluating + checking `Foo::bytes::{constant#0}`..
|
LL | bytes: [u8; unsafe { intrinsics::size_of::<Foo>() }],
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= note: ...which requires computing layout of `Foo`...
= note: ...which requires computing layout of `[u8; _]`...
= note: ...which requires normalizing `[u8; _]`...
= note: ...which again requires evaluating type-level constant, completing the cycle
note: cycle used when checking that `Foo` is well-formed
--> $DIR/issue-44415.rs:5:1
= note: ...which again requires const-evaluating + checking `Foo::bytes::{constant#0}`, completing the cycle
note: cycle used when evaluating type-level constant
--> $DIR/issue-44415.rs:6:17
|
LL | struct Foo {
| ^^^^^^^^^^
LL | bytes: [u8; unsafe { intrinsics::size_of::<Foo>() }],
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error: aborting due to previous error

Expand Down
2 changes: 1 addition & 1 deletion src/test/ui/fn/implied-bounds-unnorm-associated-type-2.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ impl<T> Trait for T {
}

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

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

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

error: aborting due to previous error

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

0 comments on commit 1634023

Please sign in to comment.