Skip to content

Commit 71d82c2

Browse files
committed
when defining opaques, require the hidden type to be well-formed
1 parent 93bc7a4 commit 71d82c2

21 files changed

+167
-140
lines changed

compiler/rustc_infer/src/infer/opaque_types.rs

+18-1
Original file line numberDiff line numberDiff line change
@@ -605,8 +605,25 @@ impl<'tcx> InferCtxt<'tcx> {
605605
obligations: &mut Vec<PredicateObligation<'tcx>>,
606606
) {
607607
let tcx = self.tcx;
608-
let item_bounds = tcx.explicit_item_bounds(def_id);
608+
// Require that the hidden type is well-formed. We have to
609+
// make sure we wf-check the hidden type to fix #114728.
610+
//
611+
// However, we don't check that all types are well-formed.
612+
// We only do so for types provided by the user or if they are
613+
// "used", e.g. for method selection.
614+
//
615+
// This means we never check the wf requirements of the hidden
616+
// type during MIR borrowck, causing us to infer the wrong
617+
// lifetime for its member constraints which then results in
618+
// unexpected region errors.
619+
obligations.push(traits::Obligation::new(
620+
tcx,
621+
cause.clone(),
622+
param_env,
623+
ty::ClauseKind::WellFormed(hidden_ty.into()),
624+
));
609625

626+
let item_bounds = tcx.explicit_item_bounds(def_id);
610627
for (predicate, _) in item_bounds.iter_instantiated_copied(tcx, args) {
611628
let predicate = predicate.fold_with(&mut BottomUpFolder {
612629
tcx,

tests/ui/closures/issue-78720.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
fn server() -> impl {
2-
//~^ ERROR at least one trait must be specified
2+
//~^ ERROR at least one trait must be specified
3+
//~| ERROR type annotations needed
34
().map2(|| "")
4-
//~^ ERROR type annotations needed
55
}
66

77
trait FilterBase2 {

tests/ui/closures/issue-78720.stderr

+3-3
Original file line numberDiff line numberDiff line change
@@ -23,10 +23,10 @@ LL | struct Map2<Segment2, F> {
2323
| +++
2424

2525
error[E0282]: type annotations needed
26-
--> $DIR/issue-78720.rs:3:5
26+
--> $DIR/issue-78720.rs:1:16
2727
|
28-
LL | ().map2(|| "")
29-
| ^^^^^^^^^^^^^^ cannot infer type
28+
LL | fn server() -> impl {
29+
| ^^^^ cannot infer type
3030

3131
error[E0308]: mismatched types
3232
--> $DIR/issue-78720.rs:8:39

tests/ui/impl-trait/issues/issue-86800.rs

+3-6
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,6 @@
11
#![feature(type_alias_impl_trait)]
22

33
//@ edition:2021
4-
//@ compile-flags:-Z treat-err-as-bug=2
5-
//@ error-pattern: due to `-Z treat-err-as-bug=2
6-
//@ failure-status:101
7-
//@ normalize-stderr-test ".*note: .*\n\n" -> ""
8-
//@ normalize-stderr-test "thread 'rustc' panicked.*:\n.*\n" -> ""
9-
//@ rustc-env:RUST_BACKTRACE=0
104

115
use std::future::Future;
126

@@ -29,6 +23,7 @@ struct Context {
2923
type TransactionResult<O> = Result<O, ()>;
3024

3125
type TransactionFuture<'__, O> = impl '__ + Future<Output = TransactionResult<O>>;
26+
//~^ ERROR unconstrained opaque type
3227

3328
fn execute_transaction_fut<'f, F, O>(
3429
f: F,
@@ -37,13 +32,15 @@ where
3732
F: FnOnce(&mut dyn Transaction) -> TransactionFuture<'_, O> + 'f
3833
{
3934
f
35+
//~^ ERROR expected generic lifetime parameter, found `'_`
4036
}
4137

4238
impl Context {
4339
async fn do_transaction<O>(
4440
&self, f: impl FnOnce(&mut dyn Transaction) -> TransactionFuture<'_, O>
4541
) -> TransactionResult<O>
4642
{
43+
//~^ ERROR expected generic lifetime parameter, found `'_`
4744
let mut conn = Connection {};
4845
let mut transaction = TestTransaction { conn: &mut conn };
4946
f(&mut transaction).await
+21-8
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,34 @@
11
error: unconstrained opaque type
2-
--> $DIR/issue-86800.rs:31:34
2+
--> $DIR/issue-86800.rs:25:34
33
|
44
LL | type TransactionFuture<'__, O> = impl '__ + Future<Output = TransactionResult<O>>;
55
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
66
|
7-
error: internal compiler error[E0792]: expected generic lifetime parameter, found `'_`
8-
--> $DIR/issue-86800.rs:39:5
7+
= note: `TransactionFuture` must be used in combination with a concrete type within the same module
8+
9+
error[E0792]: expected generic lifetime parameter, found `'_`
10+
--> $DIR/issue-86800.rs:34:5
911
|
1012
LL | type TransactionFuture<'__, O> = impl '__ + Future<Output = TransactionResult<O>>;
1113
| --- this generic parameter must be used with a generic lifetime parameter
1214
...
1315
LL | f
1416
| ^
1517

16-
error: the compiler unexpectedly panicked. this is a bug.
18+
error[E0792]: expected generic lifetime parameter, found `'_`
19+
--> $DIR/issue-86800.rs:42:5
20+
|
21+
LL | type TransactionFuture<'__, O> = impl '__ + Future<Output = TransactionResult<O>>;
22+
| --- this generic parameter must be used with a generic lifetime parameter
23+
...
24+
LL | / {
25+
LL | |
26+
LL | | let mut conn = Connection {};
27+
LL | | let mut transaction = TestTransaction { conn: &mut conn };
28+
LL | | f(&mut transaction).await
29+
LL | | }
30+
| |_____^
31+
32+
error: aborting due to 3 previous errors
1733

18-
query stack during panic:
19-
#0 [mir_borrowck] borrow-checking `execute_transaction_fut`
20-
#1 [type_of_opaque] computing type of opaque `execute_transaction_fut::{opaque#0}`
21-
end of query stack
34+
For more information about this error, try `rustc --explain E0792`.

tests/ui/impl-trait/recursive-coroutine-boxed.next.stderr

+5-5
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
error[E0282]: type annotations needed
2-
--> $DIR/recursive-coroutine-boxed.rs:10:23
2+
--> $DIR/recursive-coroutine-boxed.rs:11:23
33
|
44
LL | let mut gen = Box::pin(foo());
55
| ^^^^^^^^ cannot infer type of the type parameter `T` declared on the struct `Box`
6-
...
6+
LL |
77
LL | let mut r = gen.as_mut().resume(());
88
| ------ type must be known at this point
99
|
@@ -13,10 +13,10 @@ LL | let mut gen = Box::<T>::pin(foo());
1313
| +++++
1414

1515
error[E0282]: type annotations needed
16-
--> $DIR/recursive-coroutine-boxed.rs:10:32
16+
--> $DIR/recursive-coroutine-boxed.rs:8:13
1717
|
18-
LL | let mut gen = Box::pin(foo());
19-
| ^^^^^ cannot infer type for opaque type `impl Coroutine<Yield = (), Return = ()>`
18+
LL | fn foo() -> impl Coroutine<Yield = (), Return = ()> {
19+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot infer type for opaque type `impl Coroutine<Yield = (), Return = ()>`
2020

2121
error: aborting due to 2 previous errors
2222

tests/ui/impl-trait/recursive-coroutine-boxed.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,10 @@
66
use std::ops::{Coroutine, CoroutineState};
77

88
fn foo() -> impl Coroutine<Yield = (), Return = ()> {
9+
//[next]~^ ERROR type annotations needed
910
|| {
1011
let mut gen = Box::pin(foo());
1112
//[next]~^ ERROR type annotations needed
12-
//[next]~| ERROR type annotations needed
1313
let mut r = gen.as_mut().resume(());
1414
while let CoroutineState::Yielded(v) = r {
1515
yield v;

tests/ui/impl-trait/wf-check-hidden-type.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,7 @@ impl<'a, 'b> Extend<'a, 'b> for Option<&'b &'a ()> {
1111
}
1212

1313
fn boom<'a, 'b>() -> impl Extend<'a, 'b> {
14-
//~^ ERROR in type `&'b &'a ()`, reference has a longer lifetime than the data it references
15-
None::<&'_ &'_ ()>
14+
None::<&'_ &'_ ()> //~ ERROR lifetime may not live long enough
1615
}
1716

1817
fn main() {
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,14 @@
1-
error[E0491]: in type `&'b &'a ()`, reference has a longer lifetime than the data it references
2-
--> $DIR/wf-check-hidden-type.rs:13:22
1+
error: lifetime may not live long enough
2+
--> $DIR/wf-check-hidden-type.rs:14:5
33
|
44
LL | fn boom<'a, 'b>() -> impl Extend<'a, 'b> {
5-
| ^^^^^^^^^^^^^^^^^^^
5+
| -- -- lifetime `'b` defined here
6+
| |
7+
| lifetime `'a` defined here
8+
LL | None::<&'_ &'_ ()>
9+
| ^^^^^^^^^^^^^^^^^^ function was supposed to return data with lifetime `'b` but it is returning data with lifetime `'a`
610
|
7-
note: the pointer is valid for the lifetime `'b` as defined here
8-
--> $DIR/wf-check-hidden-type.rs:13:13
9-
|
10-
LL | fn boom<'a, 'b>() -> impl Extend<'a, 'b> {
11-
| ^^
12-
note: but the referenced data is only valid for the lifetime `'a` as defined here
13-
--> $DIR/wf-check-hidden-type.rs:13:9
14-
|
15-
LL | fn boom<'a, 'b>() -> impl Extend<'a, 'b> {
16-
| ^^
11+
= help: consider adding the following bound: `'a: 'b`
1712

1813
error: aborting due to 1 previous error
1914

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

tests/ui/lifetimes/issue-76168-hr-outlives-3.rs

+1
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ use std::future::Future;
66
async fn wrapper<F>(f: F)
77
//~^ ERROR: expected a `FnOnce(&'a mut i32)` closure, found `i32`
88
//~| ERROR: expected a `FnOnce(&'a mut i32)` closure, found `i32`
9+
//~| ERROR: expected a `FnOnce(&'a mut i32)` closure, found `i32`
910
where
1011
F:,
1112
for<'a> <i32 as FnOnce<(&'a mut i32,)>>::Output: Future<Output = ()> + 'a,

tests/ui/lifetimes/issue-76168-hr-outlives-3.stderr

+17-2
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ error[E0277]: expected a `FnOnce(&'a mut i32)` closure, found `i32`
44
LL | / async fn wrapper<F>(f: F)
55
LL | |
66
LL | |
7+
LL | |
78
LL | | where
89
LL | | F:,
910
LL | | for<'a> <i32 as FnOnce<(&'a mut i32,)>>::Output: Future<Output = ()> + 'a,
@@ -20,7 +21,21 @@ LL | async fn wrapper<F>(f: F)
2021
= help: the trait `for<'a> FnOnce<(&'a mut i32,)>` is not implemented for `i32`
2122

2223
error[E0277]: expected a `FnOnce(&'a mut i32)` closure, found `i32`
23-
--> $DIR/issue-76168-hr-outlives-3.rs:12:1
24+
--> $DIR/issue-76168-hr-outlives-3.rs:6:1
25+
|
26+
LL | / async fn wrapper<F>(f: F)
27+
LL | |
28+
LL | |
29+
LL | |
30+
LL | | where
31+
LL | | F:,
32+
LL | | for<'a> <i32 as FnOnce<(&'a mut i32,)>>::Output: Future<Output = ()> + 'a,
33+
| |__________________________________________________________________________^ expected an `FnOnce(&'a mut i32)` closure, found `i32`
34+
|
35+
= help: the trait `for<'a> FnOnce<(&'a mut i32,)>` is not implemented for `i32`
36+
37+
error[E0277]: expected a `FnOnce(&'a mut i32)` closure, found `i32`
38+
--> $DIR/issue-76168-hr-outlives-3.rs:13:1
2439
|
2540
LL | / {
2641
LL | |
@@ -31,6 +46,6 @@ LL | | }
3146
|
3247
= help: the trait `for<'a> FnOnce<(&'a mut i32,)>` is not implemented for `i32`
3348

34-
error: aborting due to 3 previous errors
49+
error: aborting due to 4 previous errors
3550

3651
For more information about this error, try `rustc --explain E0277`.

tests/ui/traits/next-solver/normalize-async-closure-in-trait.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
//@ compile-flags: -Znext-solver
2-
//@ check-pass
2+
//@ known-bug: unknown
33
//@ edition:2021
44

55
trait Foo {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
error[E0271]: type mismatch resolving `impl Future<Output = ()> == {async fn body@$DIR/normalize-async-closure-in-trait.rs:6:20: 6:22}`
2+
--> $DIR/normalize-async-closure-in-trait.rs:6:20
3+
|
4+
LL | async fn bar() {}
5+
| ^^ types differ
6+
7+
error[E0271]: type mismatch resolving `{async fn body@$DIR/normalize-async-closure-in-trait.rs:6:20: 6:22} <: impl Future<Output = ()>`
8+
--> $DIR/normalize-async-closure-in-trait.rs:6:20
9+
|
10+
LL | async fn bar() {}
11+
| ^^ types differ
12+
13+
error: aborting due to 2 previous errors
14+
15+
For more information about this error, try `rustc --explain E0271`.

tests/ui/traits/non_lifetime_binders/type-match-with-late-bound.stderr

+15-1
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,20 @@ help: consider adding an explicit lifetime bound
2121
LL | for<F> F: 'a, !1_"F": 'a
2222
| ~~~~~~~~~~~~
2323

24-
error: aborting due to 1 previous error; 1 warning emitted
24+
error[E0309]: the placeholder type `!2_"F"` may not live long enough
25+
--> $DIR/type-match-with-late-bound.rs:11:1
26+
|
27+
LL | async fn walk2<'a, T: 'a>(_: T)
28+
| -- the placeholder type `!2_"F"` must be valid for the lifetime `'a` as defined here...
29+
...
30+
LL | {}
31+
| ^^ ...so that the type `F` will meet its required lifetime bounds
32+
|
33+
help: consider adding an explicit lifetime bound
34+
|
35+
LL | for<F> F: 'a, !2_"F": 'a
36+
| ~~~~~~~~~~~~
37+
38+
error: aborting due to 2 previous errors; 1 warning emitted
2539

2640
For more information about this error, try `rustc --explain E0309`.

tests/ui/type-alias-impl-trait/issue-90400-2.stderr

+5-7
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,13 @@ error[E0277]: the trait bound `B: Bar` is not satisfied
22
--> $DIR/issue-90400-2.rs:25:9
33
|
44
LL | MyBaz(bar)
5-
| ^^^^^^^^^^ the trait `Bar` is not implemented for `B`, which is required by `MyBaz<B>: Baz`
5+
| ^^^^^^^^^^ the trait `Bar` is not implemented for `B`
66
|
7-
note: required for `MyBaz<B>` to implement `Baz`
8-
--> $DIR/issue-90400-2.rs:30:14
7+
note: required by a bound in `MyBaz`
8+
--> $DIR/issue-90400-2.rs:29:17
99
|
10-
LL | impl<B: Bar> Baz for MyBaz<B> {
11-
| --- ^^^ ^^^^^^^^
12-
| |
13-
| unsatisfied trait bound introduced here
10+
LL | struct MyBaz<B: Bar>(B);
11+
| ^^^ required by this bound in `MyBaz`
1412
help: consider restricting type parameter `B`
1513
|
1614
LL | type FooFn<B: Bar> = impl Baz;

tests/ui/type-alias-impl-trait/wf-check-definition-site.rs

+2-4
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
//@ check-pass
2+
13
// Regression test for #114572, We were inferring an ill-formed type:
24
//
35
// `Opaque<'a> = Static<&'a str>`, vs
@@ -7,18 +9,15 @@
79
struct Static<T: 'static>(T);
810

911
type OpaqueRet<'a> = impl Sized + 'a;
10-
//~^ ERROR the type `&'a u8` does not fulfill the required lifetime
1112
fn test_return<'a>(msg: Static<&'static u8>) -> OpaqueRet<'a> {
1213
msg
1314
}
1415

1516
fn test_rpit<'a>(msg: Static<&'static u8>) -> impl Sized + 'a {
16-
//~^ ERROR the type `&'a u8` does not fulfill the required lifetime
1717
msg
1818
}
1919

2020
type OpaqueAssign<'a> = impl Sized + 'a;
21-
//~^ ERROR the type `&'a u8` does not fulfill the required lifetime
2221
fn test_assign<'a>(msg: Static<&'static u8>) -> Option<OpaqueAssign<'a>> {
2322
let _: OpaqueAssign<'a> = msg;
2423
None
@@ -29,7 +28,6 @@ fn test_assign<'a>(msg: Static<&'static u8>) -> Option<OpaqueAssign<'a>> {
2928
trait RefAt<'a>: 'a {}
3029
struct Ref<'a, T: RefAt<'a>>(&'a T);
3130
type OpaqueRef<'a, T: RefAt<'static>> = impl Sized + 'a;
32-
//~^ ERROR mismatched types
3331
fn test_trait<'a, T: RefAt<'static>>(msg: Ref<'static, T>) -> OpaqueRef<'a, T> {
3432
msg
3533
}

0 commit comments

Comments
 (0)