From f838daac376c7163688a9274a4f7dbbeb40e1485 Mon Sep 17 00:00:00 2001 From: Ali MJ Al-Nasrawy Date: Thu, 24 Aug 2023 11:28:13 +0000 Subject: [PATCH 1/5] tests --- .../generator-wf-check.output_wf.stderr | 17 +++++++ tests/ui/async-await/generator-wf-check.rs | 49 +++++++++++++++++++ .../generator-wf-check.witness_wf.stderr | 19 +++++++ 3 files changed, 85 insertions(+) create mode 100644 tests/ui/async-await/generator-wf-check.output_wf.stderr create mode 100644 tests/ui/async-await/generator-wf-check.rs create mode 100644 tests/ui/async-await/generator-wf-check.witness_wf.stderr 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..14ada6b6f81bb --- /dev/null +++ b/tests/ui/async-await/generator-wf-check.output_wf.stderr @@ -0,0 +1,17 @@ +error[E0310]: the parameter type `T` may not live long enough + --> $DIR/generator-wf-check.rs:24:5 + | +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 new file mode 100644 index 0000000000000..cd1b60af25aa5 --- /dev/null +++ b/tests/ui/async-await/generator-wf-check.rs @@ -0,0 +1,49 @@ +//! Tests if we draw implied bounds from the generator output or witness types, +//! and if so, whether we check these types are WF when checking the generator. + +// edition: 2021 +// revisions: output output_wf witness witness_wf +//[output] check-pass +//[output_wf] check-fail +//[witness] check-pass +//[witness_wf] check-fail + +struct Static(T); + +fn wf(_: T) {} + +#[cfg(output)] +fn test_output() { + async { + None::> + }; +} + +#[cfg(output_wf)] +fn test_output_wf() { + wf(async { + //[output_wf]~^ ERROR `T` may not live long enough + None::> + }); +} + +#[cfg(witness)] +fn test_witness() { + async { + let witness: Option> = None; + async {}.await; + drop(witness); + }; +} + +#[cfg(witness_wf)] +fn test_witness_wf() { + wf(async { + //[witness_wf]~^ ERROR `T` may not live long enough + let witness: Option> = None; + async {}.await; + drop(witness); + }); +} + +fn main() {} diff --git a/tests/ui/async-await/generator-wf-check.witness_wf.stderr b/tests/ui/async-await/generator-wf-check.witness_wf.stderr new file mode 100644 index 0000000000000..9e5e58e605051 --- /dev/null +++ b/tests/ui/async-await/generator-wf-check.witness_wf.stderr @@ -0,0 +1,19 @@ +error[E0310]: the parameter type `T` may not live long enough + --> $DIR/generator-wf-check.rs:41:5 + | +LL | / wf(async { +LL | | +LL | | let witness: Option> = None; +LL | | async {}.await; +LL | | drop(witness); +LL | | }); + | |______^ ...so that the type `T` will meet its required lifetime bounds + | +help: consider adding an explicit lifetime bound... + | +LL | fn test_witness_wf() { + | +++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0310`. From 7a3d4775363d4b71ba145838ac43a67e3dde8505 Mon Sep 17 00:00:00 2001 From: Ali MJ Al-Nasrawy Date: Thu, 24 Aug 2023 11:31:48 +0000 Subject: [PATCH 2/5] don't use generator witness for implied bounds --- .../rustc_trait_selection/src/traits/wf.rs | 8 ++++-- tests/ui/async-await/generator-wf-check.rs | 7 ++++-- .../generator-wf-check.witness.stderr | 25 +++++++++++++++++++ .../generator-wf-check.witness_wf.stderr | 24 +++++++++++------- 4 files changed, 51 insertions(+), 13 deletions(-) create mode 100644 tests/ui/async-await/generator-wf-check.witness.stderr diff --git a/compiler/rustc_trait_selection/src/traits/wf.rs b/compiler/rustc_trait_selection/src/traits/wf.rs index f26310665f9fa..beb5afe3a1117 100644 --- a/compiler/rustc_trait_selection/src/traits/wf.rs +++ b/compiler/rustc_trait_selection/src/traits/wf.rs @@ -608,8 +608,6 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> { | ty::Float(..) | ty::Error(_) | ty::Str - | ty::GeneratorWitness(..) - | ty::GeneratorWitnessMIR(..) | ty::Never | ty::Param(_) | ty::Bound(..) @@ -681,6 +679,12 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> { } } + ty::GeneratorWitness(..) | ty::GeneratorWitnessMIR(..) => { + // Unspecified in RFC 1214. + // They are always WF when the gnereator passes typeck/borrowck. + walker.skip_current_subtree(); + } + ty::Generator(did, args, ..) => { // Walk ALL the types in the generator: this will // include the upvar types as well as the yield diff --git a/tests/ui/async-await/generator-wf-check.rs b/tests/ui/async-await/generator-wf-check.rs index cd1b60af25aa5..ab815700d5dd9 100644 --- a/tests/ui/async-await/generator-wf-check.rs +++ b/tests/ui/async-await/generator-wf-check.rs @@ -5,7 +5,7 @@ // revisions: output output_wf witness witness_wf //[output] check-pass //[output_wf] check-fail -//[witness] check-pass +//[witness] check-fail //[witness_wf] check-fail struct Static(T); @@ -31,18 +31,21 @@ fn test_output_wf() { fn test_witness() { async { let witness: Option> = None; + //[witness]~^ ERROR `T` may not live long enough async {}.await; drop(witness); + //[witness]~^ ERROR `T` may not live long enough }; } #[cfg(witness_wf)] fn test_witness_wf() { wf(async { - //[witness_wf]~^ ERROR `T` may not live long enough let witness: Option> = None; + //[witness_wf]~^ ERROR `T` may not live long enough async {}.await; drop(witness); + //[witness_wf]~^ ERROR `T` may not live long enough }); } diff --git a/tests/ui/async-await/generator-wf-check.witness.stderr b/tests/ui/async-await/generator-wf-check.witness.stderr new file mode 100644 index 0000000000000..b8888f78080ed --- /dev/null +++ b/tests/ui/async-await/generator-wf-check.witness.stderr @@ -0,0 +1,25 @@ +error[E0310]: the parameter type `T` may not live long enough + --> $DIR/generator-wf-check.rs:33:22 + | +LL | let witness: Option> = None; + | ^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds + | +help: consider adding an explicit lifetime bound... + | +LL | fn test_witness() { + | +++++++++ + +error[E0310]: the parameter type `T` may not live long enough + --> $DIR/generator-wf-check.rs:36:9 + | +LL | drop(witness); + | ^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds + | +help: consider adding an explicit lifetime bound... + | +LL | fn test_witness() { + | +++++++++ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0310`. 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 9e5e58e605051..8780c50f4ec36 100644 --- a/tests/ui/async-await/generator-wf-check.witness_wf.stderr +++ b/tests/ui/async-await/generator-wf-check.witness_wf.stderr @@ -1,19 +1,25 @@ error[E0310]: the parameter type `T` may not live long enough - --> $DIR/generator-wf-check.rs:41:5 + --> $DIR/generator-wf-check.rs:44:22 | -LL | / wf(async { -LL | | -LL | | let witness: Option> = None; -LL | | async {}.await; -LL | | drop(witness); -LL | | }); - | |______^ ...so that the type `T` will meet its required lifetime bounds +LL | let witness: Option> = None; + | ^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds | help: consider adding an explicit lifetime bound... | LL | fn test_witness_wf() { | +++++++++ -error: aborting due to previous error +error[E0310]: the parameter type `T` may not live long enough + --> $DIR/generator-wf-check.rs:47:9 + | +LL | drop(witness); + | ^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds + | +help: consider adding an explicit lifetime bound... + | +LL | fn test_witness_wf() { + | +++++++++ + +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0310`. From 489afcce0cf68643c7d911c515dffed5cddb817f Mon Sep 17 00:00:00 2001 From: Ali MJ Al-Nasrawy Date: Thu, 24 Aug 2023 11:58:36 +0000 Subject: [PATCH 3/5] unify closures and generator handling in wf --- .../rustc_trait_selection/src/traits/wf.rs | 25 +++++++------------ .../generator-wf-check.output_wf.stderr | 17 ------------- tests/ui/async-await/generator-wf-check.rs | 3 +-- .../generator-wf-check.witness.stderr | 4 +-- .../generator-wf-check.witness_wf.stderr | 4 +-- 5 files changed, 14 insertions(+), 39 deletions(-) delete mode 100644 tests/ui/async-await/generator-wf-check.output_wf.stderr diff --git a/compiler/rustc_trait_selection/src/traits/wf.rs b/compiler/rustc_trait_selection/src/traits/wf.rs index beb5afe3a1117..df721c3fd1f68 100644 --- a/compiler/rustc_trait_selection/src/traits/wf.rs +++ b/compiler/rustc_trait_selection/src/traits/wf.rs @@ -681,23 +681,9 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> { ty::GeneratorWitness(..) | ty::GeneratorWitnessMIR(..) => { // Unspecified in RFC 1214. - // They are always WF when the gnereator passes typeck/borrowck. - walker.skip_current_subtree(); } - ty::Generator(did, args, ..) => { - // Walk ALL the types in the generator: this will - // include the upvar types as well as the yield - // type. Note that this is mildly distinct from - // the closure case, where we have to be careful - // about the signature of the closure. We don't - // have the problem of implied bounds here since - // generators don't take arguments. - let obligations = self.nominal_obligations(did, args); - self.out.extend(obligations); - } - - ty::Closure(did, args) => { + ty::Closure(did, args) | ty::Generator(did, args, ..) => { // Only check the upvar types for WF, not the rest // of the types within. This is needed because we // capture the signature and it may not be WF @@ -719,8 +705,15 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> { // shorthand for something like `where(T: 'a) { // fn(&'a T) }`, as discussed in #25860. walker.skip_current_subtree(); // subtree handled below + + let upvars = match ty.kind() { + ty::Closure(..) => args.as_closure().tupled_upvars_ty(), + ty::Generator(..) => args.as_generator().tupled_upvars_ty(), + _ => unreachable!(), + }; // FIXME(eddyb) add the type to `walker` instead of recursing. - self.compute(args.as_closure().tupled_upvars_ty().into()); + self.compute(upvars.into()); + // Note that we cannot skip the generic types // types. Normally, within the fn // body where they are created, the generics will diff --git a/tests/ui/async-await/generator-wf-check.output_wf.stderr b/tests/ui/async-await/generator-wf-check.output_wf.stderr deleted file mode 100644 index 14ada6b6f81bb..0000000000000 --- a/tests/ui/async-await/generator-wf-check.output_wf.stderr +++ /dev/null @@ -1,17 +0,0 @@ -error[E0310]: the parameter type `T` may not live long enough - --> $DIR/generator-wf-check.rs:24:5 - | -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 ab815700d5dd9..9add62b125e49 100644 --- a/tests/ui/async-await/generator-wf-check.rs +++ b/tests/ui/async-await/generator-wf-check.rs @@ -4,7 +4,7 @@ // edition: 2021 // revisions: output output_wf witness witness_wf //[output] check-pass -//[output_wf] check-fail +//[output_wf] check-pass //[witness] check-fail //[witness_wf] check-fail @@ -22,7 +22,6 @@ 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 b8888f78080ed..0ecef6727e8b7 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:33:22 + --> $DIR/generator-wf-check.rs:32: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:36:9 + --> $DIR/generator-wf-check.rs:35: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 8780c50f4ec36..cab374044ed1a 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:44:22 + --> $DIR/generator-wf-check.rs:43: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:47:9 + --> $DIR/generator-wf-check.rs:46:9 | LL | drop(witness); | ^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds From d06f5091d7a6490070205d6865b7cec2e90cf25f Mon Sep 17 00:00:00 2001 From: Ali MJ Al-Nasrawy Date: Thu, 24 Aug 2023 13:03:06 +0000 Subject: [PATCH 4/5] check output ty is WF except for FnDef --- .../src/type_check/free_region_relations.rs | 35 +++++++-- .../generator-wf-check.output.stderr | 17 +++++ .../generator-wf-check.output_wf.stderr | 18 +++++ tests/ui/async-await/generator-wf-check.rs | 6 +- .../generator-wf-check.witness.stderr | 4 +- .../generator-wf-check.witness_wf.stderr | 4 +- .../erase-error-in-mir-drop-tracking.rs | 7 ++ .../erase-error-in-mir-drop-tracking.stderr | 71 ++++++++++++++++++- 8 files changed, 148 insertions(+), 14 deletions(-) create mode 100644 tests/ui/async-await/generator-wf-check.output.stderr create mode 100644 tests/ui/async-await/generator-wf-check.output_wf.stderr 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`. From 7d787644efce0dd5557096b2ab6228ba967e4f4f Mon Sep 17 00:00:00 2001 From: Ali MJ Al-Nasrawy Date: Thu, 24 Aug 2023 13:36:21 +0000 Subject: [PATCH 5/5] revert previous two commits --- .../src/type_check/free_region_relations.rs | 35 ++------- .../rustc_trait_selection/src/traits/wf.rs | 25 ++++--- .../generator-wf-check.output.stderr | 17 ----- .../generator-wf-check.output_wf.stderr | 7 +- tests/ui/async-await/generator-wf-check.rs | 3 +- .../generator-wf-check.witness.stderr | 4 +- .../generator-wf-check.witness_wf.stderr | 4 +- .../erase-error-in-mir-drop-tracking.rs | 7 -- .../erase-error-in-mir-drop-tracking.stderr | 71 +------------------ 9 files changed, 32 insertions(+), 141 deletions(-) delete mode 100644 tests/ui/async-await/generator-wf-check.output.stderr 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 cc2a9b1311e01..f22851d76b31a 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, ToPredicate, Ty}; +use rustc_middle::ty::{self, RegionVid, Ty}; use rustc_span::{Span, DUMMY_SP}; use rustc_trait_selection::traits::query::type_op::{self, TypeOp}; use std::rc::Rc; @@ -232,21 +232,14 @@ 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 (i, ty) in unnormalized_input_output_tys.enumerate() { + for ty in unnormalized_input_output_tys { 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 - if use_implied_bounds { - let constraints_unnorm = self.add_implied_bounds(ty); - if let Some(c) = constraints_unnorm { - constraints.push(c) - } + 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)) @@ -272,7 +265,7 @@ impl<'tcx> UniversalRegionRelationsBuilder<'_, 'tcx> { // } // ``` // Both &Self::Bar and &() are WF - if use_implied_bounds && ty != norm_ty { + if ty != norm_ty { let constraints_norm = self.add_implied_bounds(norm_ty); if let Some(c) = constraints_norm { constraints.push(c) @@ -282,22 +275,6 @@ 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/compiler/rustc_trait_selection/src/traits/wf.rs b/compiler/rustc_trait_selection/src/traits/wf.rs index df721c3fd1f68..beb5afe3a1117 100644 --- a/compiler/rustc_trait_selection/src/traits/wf.rs +++ b/compiler/rustc_trait_selection/src/traits/wf.rs @@ -681,9 +681,23 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> { ty::GeneratorWitness(..) | ty::GeneratorWitnessMIR(..) => { // Unspecified in RFC 1214. + // They are always WF when the gnereator passes typeck/borrowck. + walker.skip_current_subtree(); } - ty::Closure(did, args) | ty::Generator(did, args, ..) => { + ty::Generator(did, args, ..) => { + // Walk ALL the types in the generator: this will + // include the upvar types as well as the yield + // type. Note that this is mildly distinct from + // the closure case, where we have to be careful + // about the signature of the closure. We don't + // have the problem of implied bounds here since + // generators don't take arguments. + let obligations = self.nominal_obligations(did, args); + self.out.extend(obligations); + } + + ty::Closure(did, args) => { // Only check the upvar types for WF, not the rest // of the types within. This is needed because we // capture the signature and it may not be WF @@ -705,15 +719,8 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> { // shorthand for something like `where(T: 'a) { // fn(&'a T) }`, as discussed in #25860. walker.skip_current_subtree(); // subtree handled below - - let upvars = match ty.kind() { - ty::Closure(..) => args.as_closure().tupled_upvars_ty(), - ty::Generator(..) => args.as_generator().tupled_upvars_ty(), - _ => unreachable!(), - }; // FIXME(eddyb) add the type to `walker` instead of recursing. - self.compute(upvars.into()); - + self.compute(args.as_closure().tupled_upvars_ty().into()); // Note that we cannot skip the generic types // types. Normally, within the fn // body where they are created, the generics will diff --git a/tests/ui/async-await/generator-wf-check.output.stderr b/tests/ui/async-await/generator-wf-check.output.stderr deleted file mode 100644 index 804bcc05d7e61..0000000000000 --- a/tests/ui/async-await/generator-wf-check.output.stderr +++ /dev/null @@ -1,17 +0,0 @@ -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 index f6527bcba84d3..14ada6b6f81bb 100644 --- a/tests/ui/async-await/generator-wf-check.output_wf.stderr +++ b/tests/ui/async-await/generator-wf-check.output_wf.stderr @@ -1,12 +1,11 @@ error[E0310]: the parameter type `T` may not live long enough - --> $DIR/generator-wf-check.rs:25:8 + --> $DIR/generator-wf-check.rs:24:5 | -LL | wf(async { - | ________^ +LL | / wf(async { LL | | LL | | None::> LL | | }); - | |_____^ ...so that the type `T` will meet its required lifetime bounds + | |______^ ...so that the type `T` will meet its required lifetime bounds | help: consider adding an explicit lifetime bound... | diff --git a/tests/ui/async-await/generator-wf-check.rs b/tests/ui/async-await/generator-wf-check.rs index efc3a390b10d5..ab815700d5dd9 100644 --- a/tests/ui/async-await/generator-wf-check.rs +++ b/tests/ui/async-await/generator-wf-check.rs @@ -3,7 +3,7 @@ // edition: 2021 // revisions: output output_wf witness witness_wf -//[output] check-fail +//[output] check-pass //[output_wf] check-fail //[witness] check-fail //[witness_wf] check-fail @@ -15,7 +15,6 @@ fn wf(_: T) {} #[cfg(output)] fn test_output() { async { - //[output]~^ 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 3c9246702474d..b8888f78080ed 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:34:22 + --> $DIR/generator-wf-check.rs:33: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:37:9 + --> $DIR/generator-wf-check.rs:36: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 a0fb98dc1f09b..8780c50f4ec36 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:45:22 + --> $DIR/generator-wf-check.rs:44: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:48:9 + --> $DIR/generator-wf-check.rs:47: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 92cdcbda7c315..addbe5d658aee 100644 --- a/tests/ui/borrowck/erase-error-in-mir-drop-tracking.rs +++ b/tests/ui/borrowck/erase-error-in-mir-drop-tracking.rs @@ -18,13 +18,6 @@ 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 b44538e650528..53abe3dc9521d 100644 --- a/tests/ui/borrowck/erase-error-in-mir-drop-tracking.stderr +++ b/tests/ui/borrowck/erase-error-in-mir-drop-tracking.stderr @@ -19,73 +19,6 @@ error: `C` does not live long enough LL | async move { c.connect().await } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -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 +error: aborting due to 2 previous errors -Some errors have detailed explanations: E0261, E0310. -For more information about an error, try `rustc --explain E0261`. +For more information about this error, try `rustc --explain E0261`.