diff --git a/compiler/rustc_borrowck/src/type_check/free_region_relations.rs b/compiler/rustc_borrowck/src/type_check/free_region_relations.rs index f22851d76b31a..cc2a9b1311e01 100644 --- a/compiler/rustc_borrowck/src/type_check/free_region_relations.rs +++ b/compiler/rustc_borrowck/src/type_check/free_region_relations.rs @@ -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; @@ -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)) @@ -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) @@ -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); } diff --git a/tests/ui/async-await/generator-wf-check.output.stderr b/tests/ui/async-await/generator-wf-check.output.stderr new file mode 100644 index 0000000000000..804bcc05d7e61 --- /dev/null +++ b/tests/ui/async-await/generator-wf-check.output.stderr @@ -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::> +LL | | }; + | |_____^ ...so that the type `T` will meet its required lifetime bounds + | +help: consider adding an explicit lifetime bound... + | +LL | fn test_output() { + | +++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0310`. diff --git a/tests/ui/async-await/generator-wf-check.output_wf.stderr b/tests/ui/async-await/generator-wf-check.output_wf.stderr new file mode 100644 index 0000000000000..f6527bcba84d3 --- /dev/null +++ b/tests/ui/async-await/generator-wf-check.output_wf.stderr @@ -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::> +LL | | }); + | |_____^ ...so that the type `T` will meet its required lifetime bounds + | +help: consider adding an explicit lifetime bound... + | +LL | fn test_output_wf() { + | +++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0310`. diff --git a/tests/ui/async-await/generator-wf-check.rs b/tests/ui/async-await/generator-wf-check.rs index 9add62b125e49..efc3a390b10d5 100644 --- a/tests/ui/async-await/generator-wf-check.rs +++ b/tests/ui/async-await/generator-wf-check.rs @@ -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 @@ -15,6 +15,7 @@ fn wf(_: T) {} #[cfg(output)] fn test_output() { async { + //[output]~^ ERROR `T` may not live long enough None::> }; } @@ -22,6 +23,7 @@ fn test_output() { #[cfg(output_wf)] fn test_output_wf() { wf(async { + //[output_wf]~^ ERROR `T` may not live long enough None::> }); } diff --git a/tests/ui/async-await/generator-wf-check.witness.stderr b/tests/ui/async-await/generator-wf-check.witness.stderr index 0ecef6727e8b7..3c9246702474d 100644 --- a/tests/ui/async-await/generator-wf-check.witness.stderr +++ b/tests/ui/async-await/generator-wf-check.witness.stderr @@ -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> = None; | ^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds @@ -10,7 +10,7 @@ LL | fn test_witness() { | +++++++++ 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 diff --git a/tests/ui/async-await/generator-wf-check.witness_wf.stderr b/tests/ui/async-await/generator-wf-check.witness_wf.stderr index cab374044ed1a..a0fb98dc1f09b 100644 --- a/tests/ui/async-await/generator-wf-check.witness_wf.stderr +++ b/tests/ui/async-await/generator-wf-check.witness_wf.stderr @@ -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> = None; | ^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds @@ -10,7 +10,7 @@ LL | fn test_witness_wf() { | +++++++++ 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 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..92cdcbda7c315 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,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() {} 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..b44538e650528 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,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`.