From 83930b0f7d9e07baf7ed7c525482ae2555676043 Mon Sep 17 00:00:00 2001 From: Ali MJ Al-Nasrawy Date: Thu, 17 Aug 2023 11:47:53 +0000 Subject: [PATCH] wf-check hidden types at definition site --- .../rustc_infer/src/infer/nll_relate/mod.rs | 8 +++++ .../src/solve/alias_relate.rs | 5 +++ .../erase-error-in-mir-drop-tracking.rs | 1 + .../erase-error-in-mir-drop-tracking.stderr | 16 ++++++++-- tests/ui/impl-trait/wf-check-hidden-type.rs | 21 +++++++++++++ .../ui/impl-trait/wf-check-hidden-type.stderr | 14 +++++++++ .../auto-with-drop_tracking_mir.fail.stderr | 4 +-- .../new-solver/auto-with-drop_tracking_mir.rs | 5 ++- .../wf-check-definition-site.rs | 31 +++++++++++++++++++ .../wf-nested.fail.stderr | 2 +- .../wf-nested.pass_sound.stderr | 2 +- tests/ui/type-alias-impl-trait/wf-nested.rs | 2 ++ 12 files changed, 104 insertions(+), 7 deletions(-) create mode 100644 tests/ui/impl-trait/wf-check-hidden-type.rs create mode 100644 tests/ui/impl-trait/wf-check-hidden-type.stderr create mode 100644 tests/ui/type-alias-impl-trait/wf-check-definition-site.rs diff --git a/compiler/rustc_infer/src/infer/nll_relate/mod.rs b/compiler/rustc_infer/src/infer/nll_relate/mod.rs index 71c07f31bc952..5e0961b30657f 100644 --- a/compiler/rustc_infer/src/infer/nll_relate/mod.rs +++ b/compiler/rustc_infer/src/infer/nll_relate/mod.rs @@ -254,6 +254,10 @@ where .handle_opaque_type(a, b, true, &cause, self.delegate.param_env())? .obligations; self.delegate.register_obligations(obligations); + self.register_predicates([ + ty::ClauseKind::WellFormed(a.into()), + ty::ClauseKind::WellFormed(b.into()), + ]); trace!(a = ?a.kind(), b = ?b.kind(), "opaque type instantiated"); Ok(a) } @@ -687,6 +691,10 @@ where } fn register_type_relate_obligation(&mut self, a: Ty<'tcx>, b: Ty<'tcx>) { + self.register_predicates([ + ty::ClauseKind::WellFormed(a.into()), + ty::ClauseKind::WellFormed(b.into()), + ]); self.register_predicates([ty::Binder::dummy(match self.ambient_variance { ty::Variance::Covariant => ty::PredicateKind::AliasRelate( a.into(), diff --git a/compiler/rustc_trait_selection/src/solve/alias_relate.rs b/compiler/rustc_trait_selection/src/solve/alias_relate.rs index 73362d823065a..93dc422491b06 100644 --- a/compiler/rustc_trait_selection/src/solve/alias_relate.rs +++ b/compiler/rustc_trait_selection/src/solve/alias_relate.rs @@ -134,6 +134,11 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { Invert::Yes => (other, fresh), }; self.sub(param_env, sub, sup)?; + self.add_goal(Goal::new( + self.tcx(), + param_env, + ty::ClauseKind::WellFormed(fresh.into()), + )); fresh } }; diff --git a/tests/ui/borrowck/erase-error-in-mir-drop-tracking.rs b/tests/ui/borrowck/erase-error-in-mir-drop-tracking.rs index addbe5d658aee..6c354d89ec89e 100644 --- a/tests/ui/borrowck/erase-error-in-mir-drop-tracking.rs +++ b/tests/ui/borrowck/erase-error-in-mir-drop-tracking.rs @@ -18,6 +18,7 @@ where { async move { c.connect().await } //~^ ERROR `C` does not live long enough + //~| ERROR `C` may not live long enough } fn main() {} diff --git a/tests/ui/borrowck/erase-error-in-mir-drop-tracking.stderr b/tests/ui/borrowck/erase-error-in-mir-drop-tracking.stderr index 53abe3dc9521d..8d4d04b72b102 100644 --- a/tests/ui/borrowck/erase-error-in-mir-drop-tracking.stderr +++ b/tests/ui/borrowck/erase-error-in-mir-drop-tracking.stderr @@ -19,6 +19,18 @@ error: `C` does not live long enough LL | async move { c.connect().await } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 2 previous errors +error[E0310]: the parameter type `C` may not live long enough + --> $DIR/erase-error-in-mir-drop-tracking.rs:19:5 + | +LL | async move { c.connect().await } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ...so that the type `C` will meet its required lifetime bounds + | +help: consider adding an explicit lifetime bound... + | +LL | C: Client + Send + Sync + 'static, + | +++++++++ + +error: aborting due to 3 previous errors -For more information about this error, try `rustc --explain E0261`. +Some errors have detailed explanations: E0261, E0310. +For more information about an error, try `rustc --explain E0261`. diff --git a/tests/ui/impl-trait/wf-check-hidden-type.rs b/tests/ui/impl-trait/wf-check-hidden-type.rs new file mode 100644 index 0000000000000..d82f30cc4666e --- /dev/null +++ b/tests/ui/impl-trait/wf-check-hidden-type.rs @@ -0,0 +1,21 @@ +//! Regression test for #114728. + +trait Extend<'a, 'b> { + fn extend(self, _: &'a str) -> &'b str; +} + +impl<'a, 'b> Extend<'a, 'b> for Option<&'b &'a ()> { + fn extend(self, s: &'a str) -> &'b str { + s + } +} + +fn boom<'a, 'b>() -> impl Extend<'a, 'b> { + None::<&'_ &'_ ()> + //~^ ERROR lifetime may not live long enough +} + +fn main() { + let y = boom().extend(&String::from("temporary")); + println!("{}", y); +} diff --git a/tests/ui/impl-trait/wf-check-hidden-type.stderr b/tests/ui/impl-trait/wf-check-hidden-type.stderr new file mode 100644 index 0000000000000..eb5b4fab8b5e1 --- /dev/null +++ b/tests/ui/impl-trait/wf-check-hidden-type.stderr @@ -0,0 +1,14 @@ +error: lifetime may not live long enough + --> $DIR/wf-check-hidden-type.rs:14:5 + | +LL | fn boom<'a, 'b>() -> impl Extend<'a, 'b> { + | -- -- lifetime `'b` defined here + | | + | lifetime `'a` defined here +LL | None::<&'_ &'_ ()> + | ^^^^^^^^^^^^^^^^^^ function was supposed to return data with lifetime `'b` but it is returning data with lifetime `'a` + | + = help: consider adding the following bound: `'a: 'b` + +error: aborting due to previous error + diff --git a/tests/ui/traits/new-solver/auto-with-drop_tracking_mir.fail.stderr b/tests/ui/traits/new-solver/auto-with-drop_tracking_mir.fail.stderr index 4aefdd6bb0735..8becb26870799 100644 --- a/tests/ui/traits/new-solver/auto-with-drop_tracking_mir.fail.stderr +++ b/tests/ui/traits/new-solver/auto-with-drop_tracking_mir.fail.stderr @@ -1,5 +1,5 @@ error[E0277]: `impl Future` cannot be sent between threads safely - --> $DIR/auto-with-drop_tracking_mir.rs:25:13 + --> $DIR/auto-with-drop_tracking_mir.rs:28:13 | LL | is_send(foo()); | ------- ^^^^^ `impl Future` cannot be sent between threads safely @@ -8,7 +8,7 @@ LL | is_send(foo()); | = help: the trait `Send` is not implemented for `impl Future` note: required by a bound in `is_send` - --> $DIR/auto-with-drop_tracking_mir.rs:24:24 + --> $DIR/auto-with-drop_tracking_mir.rs:27:24 | LL | fn is_send(_: impl Send) {} | ^^^^ required by this bound in `is_send` diff --git a/tests/ui/traits/new-solver/auto-with-drop_tracking_mir.rs b/tests/ui/traits/new-solver/auto-with-drop_tracking_mir.rs index e311a4af2f4ea..ecfa18a2577b9 100644 --- a/tests/ui/traits/new-solver/auto-with-drop_tracking_mir.rs +++ b/tests/ui/traits/new-solver/auto-with-drop_tracking_mir.rs @@ -1,7 +1,8 @@ // compile-flags: -Ztrait-solver=next -Zdrop-tracking-mir // edition: 2021 // revisions: pass fail -//[pass] check-pass +//[pass] check-fail +// WARN new-solver BUG. #![feature(negative_impls)] @@ -9,6 +10,7 @@ struct NotSync; impl !Sync for NotSync {} async fn foo() { +//[pass]~^ ERROR type mismatch #[cfg(pass)] let x = &(); #[cfg(fail)] @@ -19,6 +21,7 @@ async fn foo() { } async fn bar() {} +//[pass]~^ ERROR type mismatch fn main() { fn is_send(_: impl Send) {} diff --git a/tests/ui/type-alias-impl-trait/wf-check-definition-site.rs b/tests/ui/type-alias-impl-trait/wf-check-definition-site.rs new file mode 100644 index 0000000000000..a67fb4f2c3d16 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/wf-check-definition-site.rs @@ -0,0 +1,31 @@ +//! Regression test for #114572. +//! We were inferring an ill-formed type: +//! `Opaque<'a> = Static<&'a str>`, vs +//! `Opaque<'a> = Static<&'static str>`. +// check-pass + +#![feature(type_alias_impl_trait)] + +struct Static(T); + +type OpaqueRet<'a> = impl Sized + 'a; +fn test_return<'a>(msg: Static<&'static u8>) -> OpaqueRet<'a> { + msg +} + +type OpaqueAssign<'a> = impl Sized + 'a; +fn test_assign<'a>(msg: Static<&'static u8>) -> Option> { + let _: OpaqueAssign<'a> = msg; + None +} + +// `OpaqueRef<'a, T> = Ref<'a, T>`, vs +// `OpaqueRef<'a, T> = Ref<'static, T>`. +trait RefAt<'a>: 'a {} +struct Ref<'a, T: RefAt<'a>>(&'a T); +type OpaqueRef<'a, T: RefAt<'static>> = impl Sized + 'a; +fn test_trait<'a, T: RefAt<'static>>(msg: Ref<'static, T>) -> OpaqueRef<'a, T> { + msg +} + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/wf-nested.fail.stderr b/tests/ui/type-alias-impl-trait/wf-nested.fail.stderr index 753a46e882eda..4c398262359e5 100644 --- a/tests/ui/type-alias-impl-trait/wf-nested.fail.stderr +++ b/tests/ui/type-alias-impl-trait/wf-nested.fail.stderr @@ -1,5 +1,5 @@ error[E0310]: the parameter type `T` may not live long enough - --> $DIR/wf-nested.rs:55:27 + --> $DIR/wf-nested.rs:57:27 | LL | type InnerOpaque = impl Sized; | ^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds... diff --git a/tests/ui/type-alias-impl-trait/wf-nested.pass_sound.stderr b/tests/ui/type-alias-impl-trait/wf-nested.pass_sound.stderr index 9ab6685a7f73f..fed11fc8a8640 100644 --- a/tests/ui/type-alias-impl-trait/wf-nested.pass_sound.stderr +++ b/tests/ui/type-alias-impl-trait/wf-nested.pass_sound.stderr @@ -1,5 +1,5 @@ error[E0310]: the parameter type `T` may not live long enough - --> $DIR/wf-nested.rs:46:17 + --> $DIR/wf-nested.rs:48:17 | LL | let _ = outer.get(); | ^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds diff --git a/tests/ui/type-alias-impl-trait/wf-nested.rs b/tests/ui/type-alias-impl-trait/wf-nested.rs index de38832948918..f51ee3cfc319a 100644 --- a/tests/ui/type-alias-impl-trait/wf-nested.rs +++ b/tests/ui/type-alias-impl-trait/wf-nested.rs @@ -32,6 +32,8 @@ mod pass { use super::*; type OuterOpaque = impl Trait<&'static T, Out = impl Sized>; fn define() -> OuterOpaque {} + + fn define_rpit() -> impl Trait<&'static T, Out = impl Sized> {} } // Test the soundness of `pass` - We should require `T: 'static` at the use site.