From dd748cbf5591c858fe2387d1d85212e972617bcc Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Tue, 12 Dec 2023 16:39:05 +0000 Subject: [PATCH] Check normalized call signature for WF in mir typeck --- compiler/rustc_borrowck/src/type_check/mod.rs | 12 +++++ .../higher-ranked/trait-bounds/issue-59311.rs | 1 + .../trait-bounds/issue-59311.stderr | 11 ++++- tests/ui/nll/check-normalized-sig-for-wf.rs | 27 +++++++++++ .../ui/nll/check-normalized-sig-for-wf.stderr | 47 +++++++++++++++++++ .../missing-universe-cause-issue-114907.rs | 2 + ...missing-universe-cause-issue-114907.stderr | 36 +++++++++++++- 7 files changed, 134 insertions(+), 2 deletions(-) create mode 100644 tests/ui/nll/check-normalized-sig-for-wf.rs create mode 100644 tests/ui/nll/check-normalized-sig-for-wf.stderr diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs index e782221a4c223..b7b9d047b839c 100644 --- a/compiler/rustc_borrowck/src/type_check/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/mod.rs @@ -1413,6 +1413,18 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { ConstraintCategory::Boring, ); let sig = self.normalize(sig, term_location); + // HACK(#114936): `WF(sig)` does not imply `WF(normalized(sig))` + // with built-in `Fn` implementations, since the impl may not be + // well-formed itself. + self.prove_predicates( + sig.inputs_and_output.iter().map(|ty| { + ty::Binder::dummy(ty::PredicateKind::Clause(ty::ClauseKind::WellFormed( + ty.into(), + ))) + }), + term_location.to_locations(), + ConstraintCategory::Boring, + ); self.check_call_dest(body, term, &sig, *destination, *target, term_location); // The ordinary liveness rules will ensure that all diff --git a/tests/ui/higher-ranked/trait-bounds/issue-59311.rs b/tests/ui/higher-ranked/trait-bounds/issue-59311.rs index 3ad548450e583..387c78a802a72 100644 --- a/tests/ui/higher-ranked/trait-bounds/issue-59311.rs +++ b/tests/ui/higher-ranked/trait-bounds/issue-59311.rs @@ -17,6 +17,7 @@ where v.t(|| {}); //~^ ERROR: higher-ranked lifetime error //~| ERROR: higher-ranked lifetime error + //~| ERROR: higher-ranked lifetime error } fn main() {} diff --git a/tests/ui/higher-ranked/trait-bounds/issue-59311.stderr b/tests/ui/higher-ranked/trait-bounds/issue-59311.stderr index 28c259be35f6f..2420e57f94bd2 100644 --- a/tests/ui/higher-ranked/trait-bounds/issue-59311.stderr +++ b/tests/ui/higher-ranked/trait-bounds/issue-59311.stderr @@ -6,6 +6,15 @@ LL | v.t(|| {}); | = note: could not prove `{closure@$DIR/issue-59311.rs:17:9: 17:11} well-formed` +error: higher-ranked lifetime error + --> $DIR/issue-59311.rs:17:5 + | +LL | v.t(|| {}); + | ^^^^^^^^^^ + | + = note: could not prove `{closure@$DIR/issue-59311.rs:17:9: 17:11} well-formed` + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + error: higher-ranked lifetime error --> $DIR/issue-59311.rs:17:9 | @@ -14,5 +23,5 @@ LL | v.t(|| {}); | = note: could not prove `for<'a> &'a V: 'static` -error: aborting due to 2 previous errors +error: aborting due to 3 previous errors diff --git a/tests/ui/nll/check-normalized-sig-for-wf.rs b/tests/ui/nll/check-normalized-sig-for-wf.rs new file mode 100644 index 0000000000000..cb0f34ce02f7a --- /dev/null +++ b/tests/ui/nll/check-normalized-sig-for-wf.rs @@ -0,0 +1,27 @@ +// +fn whoops( + s: String, + f: impl for<'s> FnOnce(&'s str) -> (&'static str, [&'static &'s (); 0]), +) -> &'static str +{ + f(&s).0 + //~^ ERROR `s` does not live long enough +} + +// +fn extend(input: &T) -> &'static T { + struct Bounded<'a, 'b: 'static, T>(&'a T, [&'b (); 0]); + let n: Box Bounded<'static, '_, T>> = Box::new(|x| Bounded(x, [])); + n(input).0 + //~^ ERROR borrowed data escapes outside of function +} + +// +fn extend_mut<'a, T>(input: &'a mut T) -> &'static mut T { + struct Bounded<'a, 'b: 'static, T>(&'a mut T, [&'b (); 0]); + let mut n: Box Bounded<'static, '_, T>> = Box::new(|x| Bounded(x, [])); + n(input).0 + //~^ ERROR borrowed data escapes outside of function +} + +fn main() {} diff --git a/tests/ui/nll/check-normalized-sig-for-wf.stderr b/tests/ui/nll/check-normalized-sig-for-wf.stderr new file mode 100644 index 0000000000000..5c96b0c6561a1 --- /dev/null +++ b/tests/ui/nll/check-normalized-sig-for-wf.stderr @@ -0,0 +1,47 @@ +error[E0597]: `s` does not live long enough + --> $DIR/check-normalized-sig-for-wf.rs:7:7 + | +LL | s: String, + | - binding `s` declared here +... +LL | f(&s).0 + | --^^- + | | | + | | borrowed value does not live long enough + | argument requires that `s` is borrowed for `'static` +LL | +LL | } + | - `s` dropped here while still borrowed + +error[E0521]: borrowed data escapes outside of function + --> $DIR/check-normalized-sig-for-wf.rs:15:5 + | +LL | fn extend(input: &T) -> &'static T { + | ----- - let's call the lifetime of this reference `'1` + | | + | `input` is a reference that is only valid in the function body +... +LL | n(input).0 + | ^^^^^^^^ + | | + | `input` escapes the function body here + | argument requires that `'1` must outlive `'static` + +error[E0521]: borrowed data escapes outside of function + --> $DIR/check-normalized-sig-for-wf.rs:23:5 + | +LL | fn extend_mut<'a, T>(input: &'a mut T) -> &'static mut T { + | -- ----- `input` is a reference that is only valid in the function body + | | + | lifetime `'a` defined here +... +LL | n(input).0 + | ^^^^^^^^ + | | + | `input` escapes the function body here + | argument requires that `'a` must outlive `'static` + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0521, E0597. +For more information about an error, try `rustc --explain E0521`. diff --git a/tests/ui/nll/missing-universe-cause-issue-114907.rs b/tests/ui/nll/missing-universe-cause-issue-114907.rs index 94acdccfcf254..aa5af0e594d60 100644 --- a/tests/ui/nll/missing-universe-cause-issue-114907.rs +++ b/tests/ui/nll/missing-universe-cause-issue-114907.rs @@ -33,6 +33,8 @@ fn main() { accept(callback); //~^ ERROR mismatched types //~| ERROR mismatched types + //~| ERROR mismatched types + //~| ERROR implementation of `FnOnce` is not general enough //~| ERROR implementation of `FnOnce` is not general enough //~| ERROR implementation of `FnOnce` is not general enough //~| ERROR higher-ranked subtype error diff --git a/tests/ui/nll/missing-universe-cause-issue-114907.stderr b/tests/ui/nll/missing-universe-cause-issue-114907.stderr index a616d29c4fea6..39d3ca6488f8b 100644 --- a/tests/ui/nll/missing-universe-cause-issue-114907.stderr +++ b/tests/ui/nll/missing-universe-cause-issue-114907.stderr @@ -63,6 +63,40 @@ help: consider specifying the type of the closure parameters LL | let callback = |_: &_| {}; | ~~~~~~~ +error: implementation of `FnOnce` is not general enough + --> $DIR/missing-universe-cause-issue-114907.rs:33:5 + | +LL | accept(callback); + | ^^^^^^^^^^^^^^^^ implementation of `FnOnce` is not general enough + | + = note: closure with signature `fn(&'2 ())` must implement `FnOnce<(&'1 (),)>`, for any lifetime `'1`... + = note: ...but it actually implements `FnOnce<(&'2 (),)>`, for some specific lifetime `'2` + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error[E0308]: mismatched types + --> $DIR/missing-universe-cause-issue-114907.rs:33:5 + | +LL | accept(callback); + | ^^^^^^^^^^^^^^^^ one type is more general than the other + | + = note: expected trait `for<'a> FnOnce(&'a ())` + found trait `FnOnce(&())` +note: this closure does not fulfill the lifetime requirements + --> $DIR/missing-universe-cause-issue-114907.rs:32:20 + | +LL | let callback = |_| {}; + | ^^^ +note: the lifetime requirement is introduced here + --> $DIR/missing-universe-cause-issue-114907.rs:20:21 + | +LL | struct Handshake { + | ^^^^ + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` +help: consider specifying the type of the closure parameters + | +LL | let callback = |_: &_| {}; + | ~~~~~~~ + error: higher-ranked subtype error --> $DIR/missing-universe-cause-issue-114907.rs:33:21 | @@ -77,6 +111,6 @@ LL | accept(callback); | = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -error: aborting due to 6 previous errors +error: aborting due to 8 previous errors For more information about this error, try `rustc --explain E0308`.