Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Register wf obligation before normalizing in wfcheck #100046

Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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() {
Comment on lines +291 to +292
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

already dealt with by try_normalize_with_depth_to, no need to check for allow_normalization here

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh cool

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