Skip to content

Commit d06f509

Browse files
committed
check output ty is WF except for FnDef
1 parent 489afcc commit d06f509

8 files changed

+148
-14
lines changed

compiler/rustc_borrowck/src/type_check/free_region_relations.rs

Lines changed: 29 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use rustc_infer::infer::region_constraints::GenericKind;
77
use rustc_infer::infer::InferCtxt;
88
use rustc_middle::mir::ConstraintCategory;
99
use rustc_middle::traits::query::OutlivesBound;
10-
use rustc_middle::ty::{self, RegionVid, Ty};
10+
use rustc_middle::ty::{self, RegionVid, ToPredicate, Ty};
1111
use rustc_span::{Span, DUMMY_SP};
1212
use rustc_trait_selection::traits::query::type_op::{self, TypeOp};
1313
use std::rc::Rc;
@@ -232,14 +232,21 @@ impl<'tcx> UniversalRegionRelationsBuilder<'_, 'tcx> {
232232
let mut normalized_inputs_and_output =
233233
Vec::with_capacity(self.universal_regions.unnormalized_input_tys.len() + 1);
234234
let mut constraints = vec![];
235-
for ty in unnormalized_input_output_tys {
235+
for (i, ty) in unnormalized_input_output_tys.enumerate() {
236236
debug!("build: input_or_output={:?}", ty);
237+
238+
let use_implied_bounds = i < self.universal_regions.unnormalized_input_tys.len()
239+
|| self.universal_regions.defining_ty.is_fn_def();
240+
237241
// We add implied bounds from both the unnormalized and normalized ty.
238242
// See issue #87748
239-
let constraints_unnorm = self.add_implied_bounds(ty);
240-
if let Some(c) = constraints_unnorm {
241-
constraints.push(c)
243+
if use_implied_bounds {
244+
let constraints_unnorm = self.add_implied_bounds(ty);
245+
if let Some(c) = constraints_unnorm {
246+
constraints.push(c)
247+
}
242248
}
249+
243250
let TypeOpOutput { output: norm_ty, constraints: constraints_normalize, .. } = self
244251
.param_env
245252
.and(type_op::normalize::Normalize::new(ty))
@@ -265,7 +272,7 @@ impl<'tcx> UniversalRegionRelationsBuilder<'_, 'tcx> {
265272
// }
266273
// ```
267274
// Both &Self::Bar and &() are WF
268-
if ty != norm_ty {
275+
if use_implied_bounds && ty != norm_ty {
269276
let constraints_norm = self.add_implied_bounds(norm_ty);
270277
if let Some(c) = constraints_norm {
271278
constraints.push(c)
@@ -275,6 +282,22 @@ impl<'tcx> UniversalRegionRelationsBuilder<'_, 'tcx> {
275282
normalized_inputs_and_output.push(norm_ty);
276283
}
277284

285+
let TypeOpOutput { constraints: constraints_wf, .. } = self
286+
.param_env
287+
.and(type_op::ProvePredicate::new(
288+
ty::ClauseKind::WellFormed((*normalized_inputs_and_output.last().unwrap()).into())
289+
.to_predicate(self.infcx.tcx),
290+
))
291+
.fully_perform(self.infcx, span)
292+
.unwrap_or_else(|_: rustc_span::ErrorGuaranteed| TypeOpOutput {
293+
output: (),
294+
constraints: None,
295+
error_info: None,
296+
});
297+
if let Some(c) = constraints_wf {
298+
constraints.push(c)
299+
}
300+
278301
for c in constraints {
279302
self.push_region_constraints(c, span);
280303
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
error[E0310]: the parameter type `T` may not live long enough
2+
--> $DIR/generator-wf-check.rs:17:5
3+
|
4+
LL | / async {
5+
LL | |
6+
LL | | None::<Static<T>>
7+
LL | | };
8+
| |_____^ ...so that the type `T` will meet its required lifetime bounds
9+
|
10+
help: consider adding an explicit lifetime bound...
11+
|
12+
LL | fn test_output<T: 'static>() {
13+
| +++++++++
14+
15+
error: aborting due to previous error
16+
17+
For more information about this error, try `rustc --explain E0310`.
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
error[E0310]: the parameter type `T` may not live long enough
2+
--> $DIR/generator-wf-check.rs:25:8
3+
|
4+
LL | wf(async {
5+
| ________^
6+
LL | |
7+
LL | | None::<Static<T>>
8+
LL | | });
9+
| |_____^ ...so that the type `T` will meet its required lifetime bounds
10+
|
11+
help: consider adding an explicit lifetime bound...
12+
|
13+
LL | fn test_output_wf<T: 'static>() {
14+
| +++++++++
15+
16+
error: aborting due to previous error
17+
18+
For more information about this error, try `rustc --explain E0310`.

tests/ui/async-await/generator-wf-check.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@
33
44
// edition: 2021
55
// revisions: output output_wf witness witness_wf
6-
//[output] check-pass
7-
//[output_wf] check-pass
6+
//[output] check-fail
7+
//[output_wf] check-fail
88
//[witness] check-fail
99
//[witness_wf] check-fail
1010

@@ -15,13 +15,15 @@ fn wf<T>(_: T) {}
1515
#[cfg(output)]
1616
fn test_output<T>() {
1717
async {
18+
//[output]~^ ERROR `T` may not live long enough
1819
None::<Static<T>>
1920
};
2021
}
2122

2223
#[cfg(output_wf)]
2324
fn test_output_wf<T>() {
2425
wf(async {
26+
//[output_wf]~^ ERROR `T` may not live long enough
2527
None::<Static<T>>
2628
});
2729
}

tests/ui/async-await/generator-wf-check.witness.stderr

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
error[E0310]: the parameter type `T` may not live long enough
2-
--> $DIR/generator-wf-check.rs:32:22
2+
--> $DIR/generator-wf-check.rs:34:22
33
|
44
LL | let witness: Option<Static<T>> = None;
55
| ^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds
@@ -10,7 +10,7 @@ LL | fn test_witness<T: 'static>() {
1010
| +++++++++
1111

1212
error[E0310]: the parameter type `T` may not live long enough
13-
--> $DIR/generator-wf-check.rs:35:9
13+
--> $DIR/generator-wf-check.rs:37:9
1414
|
1515
LL | drop(witness);
1616
| ^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds

tests/ui/async-await/generator-wf-check.witness_wf.stderr

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
error[E0310]: the parameter type `T` may not live long enough
2-
--> $DIR/generator-wf-check.rs:43:22
2+
--> $DIR/generator-wf-check.rs:45:22
33
|
44
LL | let witness: Option<Static<T>> = None;
55
| ^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds
@@ -10,7 +10,7 @@ LL | fn test_witness_wf<T: 'static>() {
1010
| +++++++++
1111

1212
error[E0310]: the parameter type `T` may not live long enough
13-
--> $DIR/generator-wf-check.rs:46:9
13+
--> $DIR/generator-wf-check.rs:48:9
1414
|
1515
LL | drop(witness);
1616
| ^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds

tests/ui/borrowck/erase-error-in-mir-drop-tracking.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,13 @@ where
1818
{
1919
async move { c.connect().await }
2020
//~^ ERROR `C` does not live long enough
21+
//~| ERROR `C` may not live long enough
22+
//~| ERROR `C` may not live long enough
23+
//~| ERROR `C` may not live long enough
24+
//~| ERROR `C` may not live long enough
25+
//~| ERROR `C` may not live long enough
26+
//~| ERROR `C` may not live long enough
27+
2128
}
2229

2330
fn main() {}

tests/ui/borrowck/erase-error-in-mir-drop-tracking.stderr

Lines changed: 69 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,73 @@ error: `C` does not live long enough
1919
LL | async move { c.connect().await }
2020
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
2121

22-
error: aborting due to 2 previous errors
22+
error[E0310]: the parameter type `C` may not live long enough
23+
--> $DIR/erase-error-in-mir-drop-tracking.rs:19:5
24+
|
25+
LL | async move { c.connect().await }
26+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ...so that the type `C` will meet its required lifetime bounds
27+
|
28+
help: consider adding an explicit lifetime bound...
29+
|
30+
LL | C: Client + Send + Sync + 'static,
31+
| +++++++++
32+
33+
error[E0310]: the parameter type `C` may not live long enough
34+
--> $DIR/erase-error-in-mir-drop-tracking.rs:19:5
35+
|
36+
LL | async move { c.connect().await }
37+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ...so that the type `C` will meet its required lifetime bounds
38+
|
39+
help: consider adding an explicit lifetime bound...
40+
|
41+
LL | C: Client + Send + Sync + 'static,
42+
| +++++++++
43+
44+
error[E0310]: the parameter type `C` may not live long enough
45+
--> $DIR/erase-error-in-mir-drop-tracking.rs:19:18
46+
|
47+
LL | async move { c.connect().await }
48+
| ^^^^^^^^^^^ ...so that the type `C` will meet its required lifetime bounds
49+
|
50+
help: consider adding an explicit lifetime bound...
51+
|
52+
LL | C: Client + Send + Sync + 'static,
53+
| +++++++++
54+
55+
error[E0310]: the parameter type `C` may not live long enough
56+
--> $DIR/erase-error-in-mir-drop-tracking.rs:19:18
57+
|
58+
LL | async move { c.connect().await }
59+
| ^^^^^^^^^^^ ...so that the type `C` will meet its required lifetime bounds
60+
|
61+
help: consider adding an explicit lifetime bound...
62+
|
63+
LL | C: Client + Send + Sync + 'static,
64+
| +++++++++
65+
66+
error[E0310]: the parameter type `C` may not live long enough
67+
--> $DIR/erase-error-in-mir-drop-tracking.rs:19:30
68+
|
69+
LL | async move { c.connect().await }
70+
| ^^^^^ ...so that the type `C` will meet its required lifetime bounds
71+
|
72+
help: consider adding an explicit lifetime bound...
73+
|
74+
LL | C: Client + Send + Sync + 'static,
75+
| +++++++++
76+
77+
error[E0310]: the parameter type `C` may not live long enough
78+
--> $DIR/erase-error-in-mir-drop-tracking.rs:19:30
79+
|
80+
LL | async move { c.connect().await }
81+
| ^^^^^ ...so that the type `C` will meet its required lifetime bounds
82+
|
83+
help: consider adding an explicit lifetime bound...
84+
|
85+
LL | C: Client + Send + Sync + 'static,
86+
| +++++++++
87+
88+
error: aborting due to 8 previous errors
2389

24-
For more information about this error, try `rustc --explain E0261`.
90+
Some errors have detailed explanations: E0261, E0310.
91+
For more information about an error, try `rustc --explain E0261`.

0 commit comments

Comments
 (0)