Skip to content

Commit

Permalink
check output ty is WF except for FnDef
Browse files Browse the repository at this point in the history
  • Loading branch information
aliemjay committed Aug 24, 2023
1 parent 489afcc commit d06f509
Show file tree
Hide file tree
Showing 8 changed files with 148 additions and 14 deletions.
35 changes: 29 additions & 6 deletions compiler/rustc_borrowck/src/type_check/free_region_relations.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use rustc_infer::infer::region_constraints::GenericKind;
use rustc_infer::infer::InferCtxt;
use rustc_middle::mir::ConstraintCategory;
use rustc_middle::traits::query::OutlivesBound;
use rustc_middle::ty::{self, RegionVid, Ty};
use rustc_middle::ty::{self, RegionVid, ToPredicate, Ty};
use rustc_span::{Span, DUMMY_SP};
use rustc_trait_selection::traits::query::type_op::{self, TypeOp};
use std::rc::Rc;
Expand Down Expand Up @@ -232,14 +232,21 @@ impl<'tcx> UniversalRegionRelationsBuilder<'_, 'tcx> {
let mut normalized_inputs_and_output =
Vec::with_capacity(self.universal_regions.unnormalized_input_tys.len() + 1);
let mut constraints = vec![];
for ty in unnormalized_input_output_tys {
for (i, ty) in unnormalized_input_output_tys.enumerate() {
debug!("build: input_or_output={:?}", ty);

let use_implied_bounds = i < self.universal_regions.unnormalized_input_tys.len()
|| self.universal_regions.defining_ty.is_fn_def();

// We add implied bounds from both the unnormalized and normalized ty.
// See issue #87748
let constraints_unnorm = self.add_implied_bounds(ty);
if let Some(c) = constraints_unnorm {
constraints.push(c)
if use_implied_bounds {
let constraints_unnorm = self.add_implied_bounds(ty);
if let Some(c) = constraints_unnorm {
constraints.push(c)
}
}

let TypeOpOutput { output: norm_ty, constraints: constraints_normalize, .. } = self
.param_env
.and(type_op::normalize::Normalize::new(ty))
Expand All @@ -265,7 +272,7 @@ impl<'tcx> UniversalRegionRelationsBuilder<'_, 'tcx> {
// }
// ```
// Both &Self::Bar and &() are WF
if ty != norm_ty {
if use_implied_bounds && ty != norm_ty {
let constraints_norm = self.add_implied_bounds(norm_ty);
if let Some(c) = constraints_norm {
constraints.push(c)
Expand All @@ -275,6 +282,22 @@ impl<'tcx> UniversalRegionRelationsBuilder<'_, 'tcx> {
normalized_inputs_and_output.push(norm_ty);
}

let TypeOpOutput { constraints: constraints_wf, .. } = self
.param_env
.and(type_op::ProvePredicate::new(
ty::ClauseKind::WellFormed((*normalized_inputs_and_output.last().unwrap()).into())
.to_predicate(self.infcx.tcx),
))
.fully_perform(self.infcx, span)
.unwrap_or_else(|_: rustc_span::ErrorGuaranteed| TypeOpOutput {
output: (),
constraints: None,
error_info: None,
});
if let Some(c) = constraints_wf {
constraints.push(c)
}

for c in constraints {
self.push_region_constraints(c, span);
}
Expand Down
17 changes: 17 additions & 0 deletions tests/ui/async-await/generator-wf-check.output.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
error[E0310]: the parameter type `T` may not live long enough
--> $DIR/generator-wf-check.rs:17:5
|
LL | / async {
LL | |
LL | | None::<Static<T>>
LL | | };
| |_____^ ...so that the type `T` will meet its required lifetime bounds
|
help: consider adding an explicit lifetime bound...
|
LL | fn test_output<T: 'static>() {
| +++++++++

error: aborting due to previous error

For more information about this error, try `rustc --explain E0310`.
18 changes: 18 additions & 0 deletions tests/ui/async-await/generator-wf-check.output_wf.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
error[E0310]: the parameter type `T` may not live long enough
--> $DIR/generator-wf-check.rs:25:8
|
LL | wf(async {
| ________^
LL | |
LL | | None::<Static<T>>
LL | | });
| |_____^ ...so that the type `T` will meet its required lifetime bounds
|
help: consider adding an explicit lifetime bound...
|
LL | fn test_output_wf<T: 'static>() {
| +++++++++

error: aborting due to previous error

For more information about this error, try `rustc --explain E0310`.
6 changes: 4 additions & 2 deletions tests/ui/async-await/generator-wf-check.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@

// edition: 2021
// revisions: output output_wf witness witness_wf
//[output] check-pass
//[output_wf] check-pass
//[output] check-fail
//[output_wf] check-fail
//[witness] check-fail
//[witness_wf] check-fail

Expand All @@ -15,13 +15,15 @@ fn wf<T>(_: T) {}
#[cfg(output)]
fn test_output<T>() {
async {
//[output]~^ ERROR `T` may not live long enough
None::<Static<T>>
};
}

#[cfg(output_wf)]
fn test_output_wf<T>() {
wf(async {
//[output_wf]~^ ERROR `T` may not live long enough
None::<Static<T>>
});
}
Expand Down
4 changes: 2 additions & 2 deletions tests/ui/async-await/generator-wf-check.witness.stderr
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
error[E0310]: the parameter type `T` may not live long enough
--> $DIR/generator-wf-check.rs:32:22
--> $DIR/generator-wf-check.rs:34:22
|
LL | let witness: Option<Static<T>> = None;
| ^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds
Expand All @@ -10,7 +10,7 @@ LL | fn test_witness<T: 'static>() {
| +++++++++

error[E0310]: the parameter type `T` may not live long enough
--> $DIR/generator-wf-check.rs:35:9
--> $DIR/generator-wf-check.rs:37:9
|
LL | drop(witness);
| ^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds
Expand Down
4 changes: 2 additions & 2 deletions tests/ui/async-await/generator-wf-check.witness_wf.stderr
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
error[E0310]: the parameter type `T` may not live long enough
--> $DIR/generator-wf-check.rs:43:22
--> $DIR/generator-wf-check.rs:45:22
|
LL | let witness: Option<Static<T>> = None;
| ^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds
Expand All @@ -10,7 +10,7 @@ LL | fn test_witness_wf<T: 'static>() {
| +++++++++

error[E0310]: the parameter type `T` may not live long enough
--> $DIR/generator-wf-check.rs:46:9
--> $DIR/generator-wf-check.rs:48:9
|
LL | drop(witness);
| ^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds
Expand Down
7 changes: 7 additions & 0 deletions tests/ui/borrowck/erase-error-in-mir-drop-tracking.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,13 @@ where
{
async move { c.connect().await }
//~^ ERROR `C` does not live long enough
//~| ERROR `C` may not live long enough
//~| ERROR `C` may not live long enough
//~| ERROR `C` may not live long enough
//~| ERROR `C` may not live long enough
//~| ERROR `C` may not live long enough
//~| ERROR `C` may not live long enough

}

fn main() {}
71 changes: 69 additions & 2 deletions tests/ui/borrowck/erase-error-in-mir-drop-tracking.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,73 @@ 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[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[E0310]: the parameter type `C` may not live long enough
--> $DIR/erase-error-in-mir-drop-tracking.rs:19:18
|
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[E0310]: the parameter type `C` may not live long enough
--> $DIR/erase-error-in-mir-drop-tracking.rs:19:18
|
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[E0310]: the parameter type `C` may not live long enough
--> $DIR/erase-error-in-mir-drop-tracking.rs:19:30
|
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[E0310]: the parameter type `C` may not live long enough
--> $DIR/erase-error-in-mir-drop-tracking.rs:19:30
|
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 8 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`.

0 comments on commit d06f509

Please sign in to comment.