when defining opaques, require the hidden type to be well-formed

This commit is contained in:
lcnr 2024-02-27 15:57:49 +01:00
parent 93bc7a428c
commit 71d82c2899
21 changed files with 167 additions and 140 deletions

View file

@ -605,8 +605,25 @@ pub fn add_item_bounds_for_hidden_type(
obligations: &mut Vec<PredicateObligation<'tcx>>,
) {
let tcx = self.tcx;
let item_bounds = tcx.explicit_item_bounds(def_id);
// Require that the hidden type is well-formed. We have to
// make sure we wf-check the hidden type to fix #114728.
//
// However, we don't check that all types are well-formed.
// We only do so for types provided by the user or if they are
// "used", e.g. for method selection.
//
// This means we never check the wf requirements of the hidden
// type during MIR borrowck, causing us to infer the wrong
// lifetime for its member constraints which then results in
// unexpected region errors.
obligations.push(traits::Obligation::new(
tcx,
cause.clone(),
param_env,
ty::ClauseKind::WellFormed(hidden_ty.into()),
));
let item_bounds = tcx.explicit_item_bounds(def_id);
for (predicate, _) in item_bounds.iter_instantiated_copied(tcx, args) {
let predicate = predicate.fold_with(&mut BottomUpFolder {
tcx,

View file

@ -1,7 +1,7 @@
fn server() -> impl {
//~^ ERROR at least one trait must be specified
//~^ ERROR at least one trait must be specified
//~| ERROR type annotations needed
().map2(|| "")
//~^ ERROR type annotations needed
}
trait FilterBase2 {

View file

@ -23,10 +23,10 @@ LL | struct Map2<Segment2, F> {
| +++
error[E0282]: type annotations needed
--> $DIR/issue-78720.rs:3:5
--> $DIR/issue-78720.rs:1:16
|
LL | ().map2(|| "")
| ^^^^^^^^^^^^^^ cannot infer type
LL | fn server() -> impl {
| ^^^^ cannot infer type
error[E0308]: mismatched types
--> $DIR/issue-78720.rs:8:39

View file

@ -1,12 +1,6 @@
#![feature(type_alias_impl_trait)]
//@ edition:2021
//@ compile-flags:-Z treat-err-as-bug=2
//@ error-pattern: due to `-Z treat-err-as-bug=2
//@ failure-status:101
//@ normalize-stderr-test ".*note: .*\n\n" -> ""
//@ normalize-stderr-test "thread 'rustc' panicked.*:\n.*\n" -> ""
//@ rustc-env:RUST_BACKTRACE=0
use std::future::Future;
@ -29,6 +23,7 @@ struct Context {
type TransactionResult<O> = Result<O, ()>;
type TransactionFuture<'__, O> = impl '__ + Future<Output = TransactionResult<O>>;
//~^ ERROR unconstrained opaque type
fn execute_transaction_fut<'f, F, O>(
f: F,
@ -37,6 +32,7 @@ fn execute_transaction_fut<'f, F, O>(
F: FnOnce(&mut dyn Transaction) -> TransactionFuture<'_, O> + 'f
{
f
//~^ ERROR expected generic lifetime parameter, found `'_`
}
impl Context {
@ -44,6 +40,7 @@ async fn do_transaction<O>(
&self, f: impl FnOnce(&mut dyn Transaction) -> TransactionFuture<'_, O>
) -> TransactionResult<O>
{
//~^ ERROR expected generic lifetime parameter, found `'_`
let mut conn = Connection {};
let mut transaction = TestTransaction { conn: &mut conn };
f(&mut transaction).await

View file

@ -1,11 +1,13 @@
error: unconstrained opaque type
--> $DIR/issue-86800.rs:31:34
--> $DIR/issue-86800.rs:25:34
|
LL | type TransactionFuture<'__, O> = impl '__ + Future<Output = TransactionResult<O>>;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
error: internal compiler error[E0792]: expected generic lifetime parameter, found `'_`
--> $DIR/issue-86800.rs:39:5
= note: `TransactionFuture` must be used in combination with a concrete type within the same module
error[E0792]: expected generic lifetime parameter, found `'_`
--> $DIR/issue-86800.rs:34:5
|
LL | type TransactionFuture<'__, O> = impl '__ + Future<Output = TransactionResult<O>>;
| --- this generic parameter must be used with a generic lifetime parameter
@ -13,9 +15,20 @@ LL | type TransactionFuture<'__, O> = impl '__ + Future<Output = TransactionResu
LL | f
| ^
error: the compiler unexpectedly panicked. this is a bug.
error[E0792]: expected generic lifetime parameter, found `'_`
--> $DIR/issue-86800.rs:42:5
|
LL | type TransactionFuture<'__, O> = impl '__ + Future<Output = TransactionResult<O>>;
| --- this generic parameter must be used with a generic lifetime parameter
...
LL | / {
LL | |
LL | | let mut conn = Connection {};
LL | | let mut transaction = TestTransaction { conn: &mut conn };
LL | | f(&mut transaction).await
LL | | }
| |_____^
query stack during panic:
#0 [mir_borrowck] borrow-checking `execute_transaction_fut`
#1 [type_of_opaque] computing type of opaque `execute_transaction_fut::{opaque#0}`
end of query stack
error: aborting due to 3 previous errors
For more information about this error, try `rustc --explain E0792`.

View file

@ -1,9 +1,9 @@
error[E0282]: type annotations needed
--> $DIR/recursive-coroutine-boxed.rs:10:23
--> $DIR/recursive-coroutine-boxed.rs:11:23
|
LL | let mut gen = Box::pin(foo());
| ^^^^^^^^ cannot infer type of the type parameter `T` declared on the struct `Box`
...
LL |
LL | let mut r = gen.as_mut().resume(());
| ------ type must be known at this point
|
@ -13,10 +13,10 @@ LL | let mut gen = Box::<T>::pin(foo());
| +++++
error[E0282]: type annotations needed
--> $DIR/recursive-coroutine-boxed.rs:10:32
--> $DIR/recursive-coroutine-boxed.rs:8:13
|
LL | let mut gen = Box::pin(foo());
| ^^^^^ cannot infer type for opaque type `impl Coroutine<Yield = (), Return = ()>`
LL | fn foo() -> impl Coroutine<Yield = (), Return = ()> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot infer type for opaque type `impl Coroutine<Yield = (), Return = ()>`
error: aborting due to 2 previous errors

View file

@ -6,10 +6,10 @@
use std::ops::{Coroutine, CoroutineState};
fn foo() -> impl Coroutine<Yield = (), Return = ()> {
//[next]~^ ERROR type annotations needed
|| {
let mut gen = Box::pin(foo());
//[next]~^ ERROR type annotations needed
//[next]~| ERROR type annotations needed
let mut r = gen.as_mut().resume(());
while let CoroutineState::Yielded(v) = r {
yield v;

View file

@ -11,8 +11,7 @@ fn extend(self, s: &'a str) -> &'b str {
}
fn boom<'a, 'b>() -> impl Extend<'a, 'b> {
//~^ ERROR in type `&'b &'a ()`, reference has a longer lifetime than the data it references
None::<&'_ &'_ ()>
None::<&'_ &'_ ()> //~ ERROR lifetime may not live long enough
}
fn main() {

View file

@ -1,20 +1,14 @@
error[E0491]: in type `&'b &'a ()`, reference has a longer lifetime than the data it references
--> $DIR/wf-check-hidden-type.rs:13:22
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`
|
note: the pointer is valid for the lifetime `'b` as defined here
--> $DIR/wf-check-hidden-type.rs:13:13
|
LL | fn boom<'a, 'b>() -> impl Extend<'a, 'b> {
| ^^
note: but the referenced data is only valid for the lifetime `'a` as defined here
--> $DIR/wf-check-hidden-type.rs:13:9
|
LL | fn boom<'a, 'b>() -> impl Extend<'a, 'b> {
| ^^
= help: consider adding the following bound: `'a: 'b`
error: aborting due to 1 previous error
For more information about this error, try `rustc --explain E0491`.

View file

@ -6,6 +6,7 @@
async fn wrapper<F>(f: F)
//~^ ERROR: expected a `FnOnce(&'a mut i32)` closure, found `i32`
//~| ERROR: expected a `FnOnce(&'a mut i32)` closure, found `i32`
//~| ERROR: expected a `FnOnce(&'a mut i32)` closure, found `i32`
where
F:,
for<'a> <i32 as FnOnce<(&'a mut i32,)>>::Output: Future<Output = ()> + 'a,

View file

@ -4,6 +4,7 @@ error[E0277]: expected a `FnOnce(&'a mut i32)` closure, found `i32`
LL | / async fn wrapper<F>(f: F)
LL | |
LL | |
LL | |
LL | | where
LL | | F:,
LL | | for<'a> <i32 as FnOnce<(&'a mut i32,)>>::Output: Future<Output = ()> + 'a,
@ -20,7 +21,21 @@ LL | async fn wrapper<F>(f: F)
= help: the trait `for<'a> FnOnce<(&'a mut i32,)>` is not implemented for `i32`
error[E0277]: expected a `FnOnce(&'a mut i32)` closure, found `i32`
--> $DIR/issue-76168-hr-outlives-3.rs:12:1
--> $DIR/issue-76168-hr-outlives-3.rs:6:1
|
LL | / async fn wrapper<F>(f: F)
LL | |
LL | |
LL | |
LL | | where
LL | | F:,
LL | | for<'a> <i32 as FnOnce<(&'a mut i32,)>>::Output: Future<Output = ()> + 'a,
| |__________________________________________________________________________^ expected an `FnOnce(&'a mut i32)` closure, found `i32`
|
= help: the trait `for<'a> FnOnce<(&'a mut i32,)>` is not implemented for `i32`
error[E0277]: expected a `FnOnce(&'a mut i32)` closure, found `i32`
--> $DIR/issue-76168-hr-outlives-3.rs:13:1
|
LL | / {
LL | |
@ -31,6 +46,6 @@ LL | | }
|
= help: the trait `for<'a> FnOnce<(&'a mut i32,)>` is not implemented for `i32`
error: aborting due to 3 previous errors
error: aborting due to 4 previous errors
For more information about this error, try `rustc --explain E0277`.

View file

@ -1,5 +1,5 @@
//@ compile-flags: -Znext-solver
//@ check-pass
//@ known-bug: unknown
//@ edition:2021
trait Foo {

View file

@ -0,0 +1,15 @@
error[E0271]: type mismatch resolving `impl Future<Output = ()> == {async fn body@$DIR/normalize-async-closure-in-trait.rs:6:20: 6:22}`
--> $DIR/normalize-async-closure-in-trait.rs:6:20
|
LL | async fn bar() {}
| ^^ types differ
error[E0271]: type mismatch resolving `{async fn body@$DIR/normalize-async-closure-in-trait.rs:6:20: 6:22} <: impl Future<Output = ()>`
--> $DIR/normalize-async-closure-in-trait.rs:6:20
|
LL | async fn bar() {}
| ^^ types differ
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0271`.

View file

@ -21,6 +21,20 @@ help: consider adding an explicit lifetime bound
LL | for<F> F: 'a, !1_"F": 'a
| ~~~~~~~~~~~~
error: aborting due to 1 previous error; 1 warning emitted
error[E0309]: the placeholder type `!2_"F"` may not live long enough
--> $DIR/type-match-with-late-bound.rs:11:1
|
LL | async fn walk2<'a, T: 'a>(_: T)
| -- the placeholder type `!2_"F"` must be valid for the lifetime `'a` as defined here...
...
LL | {}
| ^^ ...so that the type `F` will meet its required lifetime bounds
|
help: consider adding an explicit lifetime bound
|
LL | for<F> F: 'a, !2_"F": 'a
| ~~~~~~~~~~~~
error: aborting due to 2 previous errors; 1 warning emitted
For more information about this error, try `rustc --explain E0309`.

View file

@ -2,15 +2,13 @@ error[E0277]: the trait bound `B: Bar` is not satisfied
--> $DIR/issue-90400-2.rs:25:9
|
LL | MyBaz(bar)
| ^^^^^^^^^^ the trait `Bar` is not implemented for `B`, which is required by `MyBaz<B>: Baz`
| ^^^^^^^^^^ the trait `Bar` is not implemented for `B`
|
note: required for `MyBaz<B>` to implement `Baz`
--> $DIR/issue-90400-2.rs:30:14
note: required by a bound in `MyBaz`
--> $DIR/issue-90400-2.rs:29:17
|
LL | impl<B: Bar> Baz for MyBaz<B> {
| --- ^^^ ^^^^^^^^
| |
| unsatisfied trait bound introduced here
LL | struct MyBaz<B: Bar>(B);
| ^^^ required by this bound in `MyBaz`
help: consider restricting type parameter `B`
|
LL | type FooFn<B: Bar> = impl Baz;

View file

@ -1,3 +1,5 @@
//@ check-pass
// Regression test for #114572, We were inferring an ill-formed type:
//
// `Opaque<'a> = Static<&'a str>`, vs
@ -7,18 +9,15 @@
struct Static<T: 'static>(T);
type OpaqueRet<'a> = impl Sized + 'a;
//~^ ERROR the type `&'a u8` does not fulfill the required lifetime
fn test_return<'a>(msg: Static<&'static u8>) -> OpaqueRet<'a> {
msg
}
fn test_rpit<'a>(msg: Static<&'static u8>) -> impl Sized + 'a {
//~^ ERROR the type `&'a u8` does not fulfill the required lifetime
msg
}
type OpaqueAssign<'a> = impl Sized + 'a;
//~^ ERROR the type `&'a u8` does not fulfill the required lifetime
fn test_assign<'a>(msg: Static<&'static u8>) -> Option<OpaqueAssign<'a>> {
let _: OpaqueAssign<'a> = msg;
None
@ -29,7 +28,6 @@ fn test_assign<'a>(msg: Static<&'static u8>) -> Option<OpaqueAssign<'a>> {
trait RefAt<'a>: 'a {}
struct Ref<'a, T: RefAt<'a>>(&'a T);
type OpaqueRef<'a, T: RefAt<'static>> = impl Sized + 'a;
//~^ ERROR mismatched types
fn test_trait<'a, T: RefAt<'static>>(msg: Ref<'static, T>) -> OpaqueRef<'a, T> {
msg
}

View file

@ -1,55 +0,0 @@
error[E0477]: the type `&'a u8` does not fulfill the required lifetime
--> $DIR/wf-check-definition-site.rs:9:22
|
LL | type OpaqueRet<'a> = impl Sized + 'a;
| ^^^^^^^^^^^^^^^
|
note: type must satisfy the static lifetime as required by this binding
--> $DIR/wf-check-definition-site.rs:7:18
|
LL | struct Static<T: 'static>(T);
| ^^^^^^^
error[E0477]: the type `&'a u8` does not fulfill the required lifetime
--> $DIR/wf-check-definition-site.rs:15:47
|
LL | fn test_rpit<'a>(msg: Static<&'static u8>) -> impl Sized + 'a {
| ^^^^^^^^^^^^^^^
|
note: type must satisfy the static lifetime as required by this binding
--> $DIR/wf-check-definition-site.rs:7:18
|
LL | struct Static<T: 'static>(T);
| ^^^^^^^
error[E0477]: the type `&'a u8` does not fulfill the required lifetime
--> $DIR/wf-check-definition-site.rs:20:25
|
LL | type OpaqueAssign<'a> = impl Sized + 'a;
| ^^^^^^^^^^^^^^^
|
note: type must satisfy the static lifetime as required by this binding
--> $DIR/wf-check-definition-site.rs:7:18
|
LL | struct Static<T: 'static>(T);
| ^^^^^^^
error[E0308]: mismatched types
--> $DIR/wf-check-definition-site.rs:31:41
|
LL | type OpaqueRef<'a, T: RefAt<'static>> = impl Sized + 'a;
| ^^^^^^^^^^^^^^^ lifetime mismatch
|
= note: expected trait `RefAt<'a>`
found trait `RefAt<'static>`
note: the lifetime `'a` as defined here...
--> $DIR/wf-check-definition-site.rs:31:16
|
LL | type OpaqueRef<'a, T: RefAt<'static>> = impl Sized + 'a;
| ^^
= note: ...does not necessarily outlive the static lifetime
error: aborting due to 4 previous errors
Some errors have detailed explanations: E0308, E0477.
For more information about an error, try `rustc --explain E0308`.

View file

@ -1,21 +1,16 @@
error[E0310]: the parameter type `T` may not live long enough
--> $DIR/wf-nested.rs:60:27
--> $DIR/wf-nested.rs:64:38
|
LL | type InnerOpaque<T> = impl Sized;
| ^^^^^^^^^^
| |
| the parameter type `T` must be valid for the static lifetime...
| ...so that the type `T` will meet its required lifetime bounds...
LL | fn define<T>() -> OuterOpaque<T> {}
| ^^
| |
| the parameter type `T` must be valid for the static lifetime...
| ...so that the type `T` will meet its required lifetime bounds
|
note: ...that is required by this bound
--> $DIR/wf-nested.rs:12:20
|
LL | struct IsStatic<T: 'static>(T);
| ^^^^^^^
help: consider adding an explicit lifetime bound
|
LL | type InnerOpaque<T: 'static> = impl Sized;
| +++++++++
LL | fn define<T: 'static>() -> OuterOpaque<T> {}
| +++++++++
error: aborting due to 1 previous error

View file

@ -1,22 +1,31 @@
error[E0310]: the parameter type `T` may not live long enough
--> $DIR/wf-nested.rs:36:57
--> $DIR/wf-nested.rs:34:38
|
LL | fn define<T>() -> OuterOpaque<T> {}
| ^^
| |
| the parameter type `T` must be valid for the static lifetime...
| ...so that the type `T` will meet its required lifetime bounds
|
help: consider adding an explicit lifetime bound
|
LL | fn define<T: 'static>() -> OuterOpaque<T> {}
| +++++++++
error[E0310]: the parameter type `T` may not live long enough
--> $DIR/wf-nested.rs:37:69
|
LL | fn define_rpit<T>() -> impl Trait<&'static T, Out = impl Sized> {}
| ^^^^^^^^^^
| |
| the parameter type `T` must be valid for the static lifetime...
| ...so that the type `T` will meet its required lifetime bounds...
| ^^
| |
| the parameter type `T` must be valid for the static lifetime...
| ...so that the type `T` will meet its required lifetime bounds
|
note: ...that is required by this bound
--> $DIR/wf-nested.rs:12:20
|
LL | struct IsStatic<T: 'static>(T);
| ^^^^^^^
help: consider adding an explicit lifetime bound
|
LL | fn define_rpit<T: 'static>() -> impl Trait<&'static T, Out = impl Sized> {}
| +++++++++
error: aborting due to 1 previous error
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0310`.

View file

@ -1,5 +1,19 @@
error[E0310]: the parameter type `T` may not live long enough
--> $DIR/wf-nested.rs:49:17
--> $DIR/wf-nested.rs:46:38
|
LL | fn define<T>() -> OuterOpaque<T> {}
| ^^
| |
| the parameter type `T` must be valid for the static lifetime...
| ...so that the type `T` will meet its required lifetime bounds
|
help: consider adding an explicit lifetime bound
|
LL | fn define<T: 'static>() -> OuterOpaque<T> {}
| +++++++++
error[E0310]: the parameter type `T` may not live long enough
--> $DIR/wf-nested.rs:51:17
|
LL | let _ = outer.get();
| ^^^^^^^^^^^
@ -13,7 +27,7 @@ LL | fn test<T: 'static>() {
| +++++++++
error[E0310]: the parameter type `T` may not live long enough
--> $DIR/wf-nested.rs:49:17
--> $DIR/wf-nested.rs:51:17
|
LL | let _ = outer.get();
| ^^^^^^^^^^^
@ -27,6 +41,6 @@ help: consider adding an explicit lifetime bound
LL | fn test<T: 'static>() {
| +++++++++
error: aborting due to 2 previous errors
error: aborting due to 3 previous errors
For more information about this error, try `rustc --explain E0310`.

View file

@ -32,6 +32,7 @@ mod pass {
use super::*;
type OuterOpaque<T> = impl Trait<&'static T, Out = impl Sized>;
fn define<T>() -> OuterOpaque<T> {}
//[pass]~^ ERROR `T` may not live long enough
fn define_rpit<T>() -> impl Trait<&'static T, Out = impl Sized> {}
//[pass]~^ ERROR the parameter type `T` may not live long enough
@ -43,6 +44,7 @@ mod pass_sound {
use super::*;
type OuterOpaque<T> = impl Trait<&'static T, Out = impl Sized>;
fn define<T>() -> OuterOpaque<T> {}
//[pass_sound]~^ ERROR `T` may not live long enough
fn test<T>() {
let outer = define::<T>();
@ -57,9 +59,10 @@ fn test<T>() {
#[cfg(fail)]
mod fail {
use super::*;
type InnerOpaque<T> = impl Sized; //[fail]~ ERROR `T` may not live long enough
type InnerOpaque<T> = impl Sized;
type OuterOpaque<T> = impl Trait<&'static T, Out = InnerOpaque<T>>;
fn define<T>() -> OuterOpaque<T> {}
//[fail]~^ ERROR the parameter type `T` may not live long enough
}
fn main() {}