From dc183702da942f4a25bff99b2bb6073d1aa7c9f9 Mon Sep 17 00:00:00 2001 From: Roxane Date: Sun, 19 Jul 2020 17:26:51 -0400 Subject: [PATCH 1/4] Replace tuple of infer vars for upvar_tys with single infer var This commit allows us to decide the number of captures required after completing capture ananysis, which is required as part of implementing RFC-2229. Co-authored-by: Aman Arora Co-authored-by: Jenny Wills --- compiler/rustc_middle/src/ty/outlives.rs | 18 ++++++-- compiler/rustc_middle/src/ty/print/pretty.rs | 46 +++++++------------ compiler/rustc_middle/src/ty/sty.rs | 8 ++++ .../rustc_trait_selection/src/opaque_types.rs | 40 +++++++++++----- .../src/traits/error_reporting/suggestions.rs | 10 ++++ .../src/traits/query/dropck_outlives.rs | 2 +- .../src/traits/select/mod.rs | 34 ++++++++++++-- .../rustc_trait_selection/src/traits/wf.rs | 6 +-- compiler/rustc_traits/src/dropck_outlives.rs | 24 ++++++++-- compiler/rustc_typeck/src/check/closure.rs | 17 ++----- compiler/rustc_typeck/src/check/coercion.rs | 23 ++++++++-- compiler/rustc_typeck/src/check/upvar.rs | 8 ++-- src/test/ui/closures/closure-move-sync.stderr | 2 + ...erator-yielding-or-returning-itself.stderr | 4 +- src/test/ui/generator/not-send-sync.stderr | 1 + .../print/generator-print-verbose-2.stderr | 3 +- .../print/generator-print-verbose-3.stderr | 2 +- src/test/ui/generator/static-not-unpin.stderr | 4 +- .../type-mismatch-signature-deduction.stderr | 2 +- .../interior-mutability.stderr | 1 + .../ui/kindck/kindck-nonsendable-1.stderr | 1 + .../ui/mismatched_types/issue-36053-2.stderr | 16 +++---- src/test/ui/no-send-res-ports.stderr | 1 + 23 files changed, 178 insertions(+), 95 deletions(-) diff --git a/compiler/rustc_middle/src/ty/outlives.rs b/compiler/rustc_middle/src/ty/outlives.rs index 4c20141bbe691..708c92af14628 100644 --- a/compiler/rustc_middle/src/ty/outlives.rs +++ b/compiler/rustc_middle/src/ty/outlives.rs @@ -96,15 +96,25 @@ fn compute_components( } ty::Closure(_, ref substs) => { - for upvar_ty in substs.as_closure().upvar_tys() { - compute_components(tcx, upvar_ty, out, visited); + if substs.as_closure().is_valid() { + for upvar_ty in substs.as_closure().upvar_tys() { + compute_components(tcx, upvar_ty, out, visited); + } + } else { + let tupled_ty = substs.as_closure().tupled_upvars_ty(); + compute_components(tcx, tupled_ty, out, visited); } } ty::Generator(_, ref substs, _) => { // Same as the closure case - for upvar_ty in substs.as_generator().upvar_tys() { - compute_components(tcx, upvar_ty, out, visited); + if substs.as_generator().is_valid() { + for upvar_ty in substs.as_generator().upvar_tys() { + compute_components(tcx, upvar_ty, out, visited); + } + } else { + let tupled_ty = substs.as_generator().tupled_upvars_ty(); + compute_components(tcx, tupled_ty, out, visited); } // We ignore regions in the generator interior as we don't diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index e1f02d0f70418..646042d407cbe 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -663,18 +663,13 @@ pub trait PrettyPrinter<'tcx>: } } else { p!(print_def_path(did, substs)); - if substs.as_generator().is_valid() { - // Search for the first inference variable - p!(" upvar_tys=("); - let mut uninferred_ty = - substs.as_generator().upvar_tys().filter(|ty| ty.is_ty_infer()); - if uninferred_ty.next().is_some() { - p!(write("unavailable")); - } else { - self = self.comma_sep(substs.as_generator().upvar_tys())?; - } - p!(")"); + p!(" upvar_tys=("); + if !substs.as_generator().is_valid() { + p!("unavailable"); + } else { + self = self.comma_sep(substs.as_generator().upvar_tys())?; } + p!(")"); } if substs.as_generator().is_valid() { @@ -704,24 +699,17 @@ pub trait PrettyPrinter<'tcx>: } } else { p!(print_def_path(did, substs)); - if substs.as_closure().is_valid() { - // Search for the first inference variable - let mut uninferred_ty = - substs.as_closure().upvar_tys().filter(|ty| ty.is_ty_infer()); - if uninferred_ty.next().is_some() { - // If the upvar substs contain an inference variable we haven't - // finished capture analysis. - p!(" closure_substs=(unavailable)"); - } else { - p!(" closure_kind_ty=", print(substs.as_closure().kind_ty())); - p!( - " closure_sig_as_fn_ptr_ty=", - print(substs.as_closure().sig_as_fn_ptr_ty()) - ); - p!(" upvar_tys=("); - self = self.comma_sep(substs.as_closure().upvar_tys())?; - p!(")"); - } + if !substs.as_closure().is_valid() { + p!(" closure_substs=(unavailable)"); + } else { + p!(" closure_kind_ty=", print(substs.as_closure().kind_ty())); + p!( + " closure_sig_as_fn_ptr_ty=", + print(substs.as_closure().sig_as_fn_ptr_ty()) + ); + p!(" upvar_tys=("); + self = self.comma_sep(substs.as_closure().upvar_tys())?; + p!(")"); } } p!("]"); diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index 1af56972ad083..870cc4eee0505 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -656,6 +656,14 @@ impl<'tcx> UpvarSubsts<'tcx> { }; tupled_upvars_ty.expect_ty().tuple_fields() } + + #[inline] + pub fn tupled_upvars_ty(self) -> Ty<'tcx> { + match self { + UpvarSubsts::Closure(substs) => substs.as_closure().tupled_upvars_ty(), + UpvarSubsts::Generator(substs) => substs.as_generator().tupled_upvars_ty(), + } + } } #[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Ord, Eq, Hash, TyEncodable, TyDecodable)] diff --git a/compiler/rustc_trait_selection/src/opaque_types.rs b/compiler/rustc_trait_selection/src/opaque_types.rs index 610c6fd7e35f8..087f6a0deece7 100644 --- a/compiler/rustc_trait_selection/src/opaque_types.rs +++ b/compiler/rustc_trait_selection/src/opaque_types.rs @@ -441,6 +441,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { for required_region in required_region_bounds { concrete_ty.visit_with(&mut ConstrainOpaqueTypeRegionVisitor { + infcx: self, op: |r| self.sub_regions(infer::CallReturn(span), required_region, r), }); } @@ -509,6 +510,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { } } concrete_ty.visit_with(&mut ConstrainOpaqueTypeRegionVisitor { + infcx: self, op: |r| self.sub_regions(infer::CallReturn(span), least_region, r), }); } @@ -543,6 +545,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { ); concrete_ty.visit_with(&mut ConstrainOpaqueTypeRegionVisitor { + infcx: self, op: |r| { self.member_constraint( opaque_type_def_id, @@ -683,11 +686,12 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { // // We ignore any type parameters because impl trait values are assumed to // capture all the in-scope type parameters. -struct ConstrainOpaqueTypeRegionVisitor { +struct ConstrainOpaqueTypeRegionVisitor<'cx, 'tcx, OP> { + infcx: &'cx InferCtxt<'cx, 'tcx>, op: OP, } -impl<'tcx, OP> TypeVisitor<'tcx> for ConstrainOpaqueTypeRegionVisitor +impl<'cx, 'tcx, OP> TypeVisitor<'tcx> for ConstrainOpaqueTypeRegionVisitor<'cx, 'tcx, OP> where OP: FnMut(ty::Region<'tcx>), { @@ -717,24 +721,36 @@ where ty::Closure(_, ref substs) => { // Skip lifetime parameters of the enclosing item(s) - for upvar_ty in substs.as_closure().upvar_tys() { - upvar_ty.visit_with(self); - } + let ty = self.infcx.shallow_resolve(substs.as_closure().tupled_upvars_ty()); + if let ty::Infer(ty::TyVar(_)) = ty.kind() { + // Not yet resolved. + ty.super_visit_with(self); + } else { + for upvar_ty in substs.as_closure().upvar_tys() { + upvar_ty.visit_with(self); + } - substs.as_closure().sig_as_fn_ptr_ty().visit_with(self); + substs.as_closure().sig_as_fn_ptr_ty().visit_with(self); + } } ty::Generator(_, ref substs, _) => { // Skip lifetime parameters of the enclosing item(s) // Also skip the witness type, because that has no free regions. - for upvar_ty in substs.as_generator().upvar_tys() { - upvar_ty.visit_with(self); - } + let ty = self.infcx.shallow_resolve(substs.as_generator().tupled_upvars_ty()); + if let ty::Infer(ty::TyVar(_)) = ty.kind() { + // Not yet resolved. + ty.super_visit_with(self); + } else { + for upvar_ty in substs.as_generator().upvar_tys() { + upvar_ty.visit_with(self); + } - substs.as_generator().return_ty().visit_with(self); - substs.as_generator().yield_ty().visit_with(self); - substs.as_generator().resume_ty().visit_with(self); + substs.as_generator().return_ty().visit_with(self); + substs.as_generator().yield_ty().visit_with(self); + substs.as_generator().resume_ty().visit_with(self); + } } _ => { ty.super_visit_with(self); diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs index 967374ffdc2c0..5908e73d4833b 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs @@ -1307,6 +1307,9 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { let mut generator = None; let mut outer_generator = None; let mut next_code = Some(&obligation.cause.code); + + let mut seen_upvar_tys_infer_tuple = false; + while let Some(code) = next_code { debug!("maybe_note_obligation_cause_for_async_await: code={:?}", code); match code { @@ -1327,6 +1330,13 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { outer_generator = Some(did); } ty::GeneratorWitness(..) => {} + ty::Tuple(_) if !seen_upvar_tys_infer_tuple => { + // By introducing a tuple of upvar types into the chain of obligations + // of a generator, the first non-generator item is now the tuple itself, + // we shall ignore this. + + seen_upvar_tys_infer_tuple = true; + } _ if generator.is_none() => { trait_ref = Some(derived_obligation.parent_trait_ref.skip_binder()); target_ty = Some(ty); diff --git a/compiler/rustc_trait_selection/src/traits/query/dropck_outlives.rs b/compiler/rustc_trait_selection/src/traits/query/dropck_outlives.rs index 424b3bd67ffad..8212823a6dbc7 100644 --- a/compiler/rustc_trait_selection/src/traits/query/dropck_outlives.rs +++ b/compiler/rustc_trait_selection/src/traits/query/dropck_outlives.rs @@ -110,7 +110,7 @@ pub fn trivial_dropck_outlives<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> bool { // check if *any* of those are trivial. ty::Tuple(ref tys) => tys.iter().all(|t| trivial_dropck_outlives(tcx, t.expect_ty())), ty::Closure(_, ref substs) => { - substs.as_closure().upvar_tys().all(|t| trivial_dropck_outlives(tcx, t)) + trivial_dropck_outlives(tcx, substs.as_closure().tupled_upvars_ty()) } ty::Adt(def, _) => { diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index a142ba58a6904..efe01191e589d 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -1631,7 +1631,13 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { ty::Closure(_, substs) => { // (*) binder moved here - Where(ty::Binder::bind(substs.as_closure().upvar_tys().collect())) + let ty = self.infcx.shallow_resolve(substs.as_closure().tupled_upvars_ty()); + if let ty::Infer(ty::TyVar(_)) = ty.kind() { + // Not yet resolved. + Ambiguous + } else { + Where(ty::Binder::bind(substs.as_closure().upvar_tys().collect())) + } } ty::Adt(..) | ty::Projection(..) | ty::Param(..) | ty::Opaque(..) => { @@ -1700,11 +1706,31 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { tys.iter().map(|k| k.expect_ty()).collect() } - ty::Closure(_, ref substs) => substs.as_closure().upvar_tys().collect(), + ty::Closure(_, ref substs) => { + let ty = self.infcx.shallow_resolve(substs.as_closure().tupled_upvars_ty()); + if let ty::Infer(ty::TyVar(_)) = ty.kind() { + // The inference variable will be replaced by a tuple once capture analysis + // completes. If the tuple meets a bound, so do all the elements within it. + vec![ty] + } else { + substs.as_closure().upvar_tys().collect() + } + } ty::Generator(_, ref substs, _) => { - let witness = substs.as_generator().witness(); - substs.as_generator().upvar_tys().chain(iter::once(witness)).collect() + let upvar_tys_resolved = + self.infcx.shallow_resolve(substs.as_generator().tupled_upvars_ty()); + + if let ty::Infer(ty::TyVar(_)) = upvar_tys_resolved.kind() { + // The inference variable will be replaced by a tuple once capture analysis + // completes, if the tuple meets a bound, so do all the elements within it. + let witness_resolved = + self.infcx.shallow_resolve(substs.as_generator().witness()); + vec![upvar_tys_resolved, witness_resolved] + } else { + let witness = substs.as_generator().witness(); + substs.as_generator().upvar_tys().chain(iter::once(witness)).collect() + } } ty::GeneratorWitness(types) => { diff --git a/compiler/rustc_trait_selection/src/traits/wf.rs b/compiler/rustc_trait_selection/src/traits/wf.rs index d66bfd482069d..496dff6c5b2cf 100644 --- a/compiler/rustc_trait_selection/src/traits/wf.rs +++ b/compiler/rustc_trait_selection/src/traits/wf.rs @@ -592,10 +592,8 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> { // anyway, except via auto trait matching (which // only inspects the upvar types). walker.skip_current_subtree(); // subtree handled below - for upvar_ty in substs.as_closure().upvar_tys() { - // FIXME(eddyb) add the type to `walker` instead of recursing. - self.compute(upvar_ty.into()); - } + // FIXME(eddyb) add the type to `walker` instead of recursing. + self.compute(substs.as_closure().tupled_upvars_ty().into()); } ty::FnPtr(_) => { diff --git a/compiler/rustc_traits/src/dropck_outlives.rs b/compiler/rustc_traits/src/dropck_outlives.rs index 3ee391d6dc714..bbd3a7229a99b 100644 --- a/compiler/rustc_traits/src/dropck_outlives.rs +++ b/compiler/rustc_traits/src/dropck_outlives.rs @@ -210,12 +210,20 @@ fn dtorck_constraint_for_ty<'tcx>( Ok::<_, NoSolution>(()) })?, - ty::Closure(_, substs) => rustc_data_structures::stack::ensure_sufficient_stack(|| { - for ty in substs.as_closure().upvar_tys() { - dtorck_constraint_for_ty(tcx, span, for_ty, depth + 1, ty, constraints)?; + ty::Closure(_, substs) => { + if !substs.as_closure().is_valid() { + // By the time this code runs, all type variables ought to + // be fully resolved. + return Err(NoSolution); } - Ok::<_, NoSolution>(()) - })?, + + rustc_data_structures::stack::ensure_sufficient_stack(|| { + for ty in substs.as_closure().upvar_tys() { + dtorck_constraint_for_ty(tcx, span, for_ty, depth + 1, ty, constraints)?; + } + Ok::<_, NoSolution>(()) + })? + } ty::Generator(_, substs, _movability) => { // rust-lang/rust#49918: types can be constructed, stored @@ -241,6 +249,12 @@ fn dtorck_constraint_for_ty<'tcx>( // derived from lifetimes attached to the upvars and resume // argument, and we *do* incorporate those here. + if !substs.as_generator().is_valid() { + // By the time this code runs, all type variables ought to + // be fully resolved. + return Err(NoSolution); + } + constraints.outlives.extend( substs .as_generator() diff --git a/compiler/rustc_typeck/src/check/closure.rs b/compiler/rustc_typeck/src/check/closure.rs index 8898a5452282c..8bdd933644a33 100644 --- a/compiler/rustc_typeck/src/check/closure.rs +++ b/compiler/rustc_typeck/src/check/closure.rs @@ -81,19 +81,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.tcx.closure_base_def_id(expr_def_id.to_def_id()), ); - let tupled_upvars_ty = - self.tcx.mk_tup(self.tcx.upvars_mentioned(expr_def_id).iter().flat_map(|upvars| { - upvars.iter().map(|(&var_hir_id, _)| { - // Create type variables (for now) to represent the transformed - // types of upvars. These will be unified during the upvar - // inference phase (`upvar.rs`). - self.infcx.next_ty_var(TypeVariableOrigin { - // FIXME(eddyb) distinguish upvar inference variables from the rest. - kind: TypeVariableOriginKind::ClosureSynthetic, - span: self.tcx.hir().span(var_hir_id), - }) - }) - })); + let tupled_upvars_ty = self.infcx.next_ty_var(TypeVariableOrigin { + kind: TypeVariableOriginKind::ClosureSynthetic, + span: self.tcx.hir().span(expr.hir_id), + }); if let Some(GeneratorTypes { resume_ty, yield_ty, interior, movability }) = generator_types { diff --git a/compiler/rustc_typeck/src/check/coercion.rs b/compiler/rustc_typeck/src/check/coercion.rs index 4addee1a4c976..db32a73618125 100644 --- a/compiler/rustc_typeck/src/check/coercion.rs +++ b/compiler/rustc_typeck/src/check/coercion.rs @@ -39,6 +39,7 @@ use crate::astconv::AstConv; use crate::check::FnCtxt; use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder}; use rustc_hir as hir; +use rustc_hir::def_id::DefId; use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; use rustc_infer::infer::{Coercion, InferOk, InferResult}; use rustc_middle::ty::adjustment::{ @@ -221,11 +222,11 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { // unsafe qualifier. self.coerce_from_fn_pointer(a, a_f, b) } - ty::Closure(_, substs_a) => { + ty::Closure(closure_def_id_a, substs_a) => { // Non-capturing closures are coercible to // function pointers or unsafe function pointers. // It cannot convert closures that require unsafe. - self.coerce_closure_to_fn(a, substs_a, b) + self.coerce_closure_to_fn(a, closure_def_id_a, substs_a, b) } _ => { // Otherwise, just use unification rules. @@ -762,6 +763,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { fn coerce_closure_to_fn( &self, a: Ty<'tcx>, + closure_def_id_a: DefId, substs_a: SubstsRef<'tcx>, b: Ty<'tcx>, ) -> CoerceResult<'tcx> { @@ -772,7 +774,18 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { let b = self.shallow_resolve(b); match b.kind() { - ty::FnPtr(fn_ty) if substs_a.as_closure().upvar_tys().next().is_none() => { + // At this point we haven't done capture analysis, which means + // that the ClosureSubsts just contains an inference variable instead + // of tuple of captured types. + // + // All we care here is if any variable is being captured and not the exact paths, + // so we check `upvars_mentioned` for root variables being captured. + ty::FnPtr(fn_ty) + if self + .tcx + .upvars_mentioned(closure_def_id_a.expect_local()) + .map_or(true, |u| u.is_empty()) => + { // We coerce the closure, which has fn type // `extern "rust-call" fn((arg0,arg1,...)) -> _` // to @@ -906,8 +919,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // Function items or non-capturing closures of differing IDs or InternalSubsts. let (a_sig, b_sig) = { let is_capturing_closure = |ty| { - if let &ty::Closure(_, substs) = ty { - substs.as_closure().upvar_tys().next().is_some() + if let &ty::Closure(closure_def_id, _substs) = ty { + self.tcx.upvars_mentioned(closure_def_id.expect_local()).is_some() } else { false } diff --git a/compiler/rustc_typeck/src/check/upvar.rs b/compiler/rustc_typeck/src/check/upvar.rs index 2c3be0da5ddd0..1e97bd65a79f4 100644 --- a/compiler/rustc_typeck/src/check/upvar.rs +++ b/compiler/rustc_typeck/src/check/upvar.rs @@ -202,9 +202,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { "analyze_closure: id={:?} substs={:?} final_upvar_tys={:?}", closure_hir_id, substs, final_upvar_tys ); - for (upvar_ty, final_upvar_ty) in substs.upvar_tys().zip(final_upvar_tys) { - self.demand_suptype(span, upvar_ty, final_upvar_ty); - } + + // Build a tuple (U0..Un) of the final upvar types U0..Un + // and unify the upvar tupe type in the closure with it: + let final_tupled_upvars_type = self.tcx.mk_tup(final_upvar_tys.iter()); + self.demand_suptype(span, substs.tupled_upvars_ty(), final_tupled_upvars_type); // If we are also inferred the closure kind here, // process any deferred resolutions. diff --git a/src/test/ui/closures/closure-move-sync.stderr b/src/test/ui/closures/closure-move-sync.stderr index da5e25c0d18fa..285b6543833ae 100644 --- a/src/test/ui/closures/closure-move-sync.stderr +++ b/src/test/ui/closures/closure-move-sync.stderr @@ -11,6 +11,7 @@ LL | F: Send + 'static, | = help: the trait `Sync` is not implemented for `std::sync::mpsc::Receiver<()>` = note: required because of the requirements on the impl of `Send` for `&std::sync::mpsc::Receiver<()>` + = note: required because it appears within the type `(&std::sync::mpsc::Receiver<()>,)` = note: required because it appears within the type `[closure@$DIR/closure-move-sync.rs:6:27: 9:6]` error[E0277]: `Sender<()>` cannot be shared between threads safely @@ -26,6 +27,7 @@ LL | F: Send + 'static, | = help: the trait `Sync` is not implemented for `Sender<()>` = note: required because of the requirements on the impl of `Send` for `&Sender<()>` + = note: required because it appears within the type `(&Sender<()>,)` = note: required because it appears within the type `[closure@$DIR/closure-move-sync.rs:18:19: 18:42]` error: aborting due to 2 previous errors diff --git a/src/test/ui/generator/generator-yielding-or-returning-itself.stderr b/src/test/ui/generator/generator-yielding-or-returning-itself.stderr index 16a5ab2cc86b7..5043a3be91d52 100644 --- a/src/test/ui/generator/generator-yielding-or-returning-itself.stderr +++ b/src/test/ui/generator/generator-yielding-or-returning-itself.stderr @@ -1,4 +1,4 @@ -error[E0271]: type mismatch resolving `<[generator@$DIR/generator-yielding-or-returning-itself.rs:15:34: 19:6 _] as Generator>::Return == [generator@$DIR/generator-yielding-or-returning-itself.rs:15:34: 19:6 _]` +error[E0271]: type mismatch resolving `<[generator@$DIR/generator-yielding-or-returning-itself.rs:15:34: 19:6] as Generator>::Return == [generator@$DIR/generator-yielding-or-returning-itself.rs:15:34: 19:6]` --> $DIR/generator-yielding-or-returning-itself.rs:15:5 | LL | pub fn want_cyclic_generator_return(_: T) @@ -14,7 +14,7 @@ LL | want_cyclic_generator_return(|| { see issue #46062 for more information -error[E0271]: type mismatch resolving `<[generator@$DIR/generator-yielding-or-returning-itself.rs:28:33: 32:6 _] as Generator>::Yield == [generator@$DIR/generator-yielding-or-returning-itself.rs:28:33: 32:6 _]` +error[E0271]: type mismatch resolving `<[generator@$DIR/generator-yielding-or-returning-itself.rs:28:33: 32:6] as Generator>::Yield == [generator@$DIR/generator-yielding-or-returning-itself.rs:28:33: 32:6]` --> $DIR/generator-yielding-or-returning-itself.rs:28:5 | LL | pub fn want_cyclic_generator_yield(_: T) diff --git a/src/test/ui/generator/not-send-sync.stderr b/src/test/ui/generator/not-send-sync.stderr index 2384ed3d24972..f5cfa83f50070 100644 --- a/src/test/ui/generator/not-send-sync.stderr +++ b/src/test/ui/generator/not-send-sync.stderr @@ -9,6 +9,7 @@ LL | assert_send(|| { | = help: the trait `Sync` is not implemented for `Cell` = note: required because of the requirements on the impl of `Send` for `&Cell` + = note: required because it appears within the type `(&Cell,)` = note: required because it appears within the type `[generator@$DIR/not-send-sync.rs:16:17: 20:6 _]` error: generator cannot be shared between threads safely diff --git a/src/test/ui/generator/print/generator-print-verbose-2.stderr b/src/test/ui/generator/print/generator-print-verbose-2.stderr index cc45d5631cb01..f363ed6a3b9a6 100644 --- a/src/test/ui/generator/print/generator-print-verbose-2.stderr +++ b/src/test/ui/generator/print/generator-print-verbose-2.stderr @@ -9,7 +9,8 @@ LL | assert_send(|| { | = help: the trait `Sync` is not implemented for `Cell` = note: required because of the requirements on the impl of `Send` for `&'_#3r Cell` - = note: required because it appears within the type `[main::{closure#1} upvar_tys=(&'_#3r Cell) _#16t]` + = note: required because it appears within the type `(&'_#3r Cell,)` + = note: required because it appears within the type `[main::{closure#1} upvar_tys=(&'_#3r Cell) _#17t]` error: generator cannot be shared between threads safely --> $DIR/generator-print-verbose-2.rs:12:5 diff --git a/src/test/ui/generator/print/generator-print-verbose-3.stderr b/src/test/ui/generator/print/generator-print-verbose-3.stderr index 0ce108dfd6206..d15646259b2c9 100644 --- a/src/test/ui/generator/print/generator-print-verbose-3.stderr +++ b/src/test/ui/generator/print/generator-print-verbose-3.stderr @@ -12,7 +12,7 @@ LL | | }; | |_____^ expected `()`, found generator | = note: expected unit type `()` - found generator `[main::{closure#0} upvar_tys=(unavailable) _#5t]` + found generator `[main::{closure#0} upvar_tys=(unavailable)]` error: aborting due to previous error diff --git a/src/test/ui/generator/static-not-unpin.stderr b/src/test/ui/generator/static-not-unpin.stderr index 216b707bb1657..881064d2f8418 100644 --- a/src/test/ui/generator/static-not-unpin.stderr +++ b/src/test/ui/generator/static-not-unpin.stderr @@ -1,11 +1,11 @@ -error[E0277]: `[static generator@$DIR/static-not-unpin.rs:11:25: 13:6 _]` cannot be unpinned +error[E0277]: `[static generator@$DIR/static-not-unpin.rs:11:25: 13:6]` cannot be unpinned --> $DIR/static-not-unpin.rs:14:18 | LL | fn assert_unpin(_: T) { | ----- required by this bound in `assert_unpin` ... LL | assert_unpin(generator); - | ^^^^^^^^^ the trait `Unpin` is not implemented for `[static generator@$DIR/static-not-unpin.rs:11:25: 13:6 _]` + | ^^^^^^^^^ the trait `Unpin` is not implemented for `[static generator@$DIR/static-not-unpin.rs:11:25: 13:6]` error: aborting due to previous error diff --git a/src/test/ui/generator/type-mismatch-signature-deduction.stderr b/src/test/ui/generator/type-mismatch-signature-deduction.stderr index 8f6f87f78de70..9e111d68a55b7 100644 --- a/src/test/ui/generator/type-mismatch-signature-deduction.stderr +++ b/src/test/ui/generator/type-mismatch-signature-deduction.stderr @@ -7,7 +7,7 @@ LL | 5 = note: expected type `std::result::Result<{integer}, _>` found type `{integer}` -error[E0271]: type mismatch resolving `<[generator@$DIR/type-mismatch-signature-deduction.rs:6:5: 14:6 _] as Generator>::Return == i32` +error[E0271]: type mismatch resolving `<[generator@$DIR/type-mismatch-signature-deduction.rs:6:5: 14:6] as Generator>::Return == i32` --> $DIR/type-mismatch-signature-deduction.rs:5:13 | LL | fn foo() -> impl Generator { diff --git a/src/test/ui/interior-mutability/interior-mutability.stderr b/src/test/ui/interior-mutability/interior-mutability.stderr index dd43da1166445..cddfe6c694666 100644 --- a/src/test/ui/interior-mutability/interior-mutability.stderr +++ b/src/test/ui/interior-mutability/interior-mutability.stderr @@ -12,6 +12,7 @@ LL | pub fn catch_unwind R + UnwindSafe, R>(f: F) -> Result { = help: within `Cell`, the trait `RefUnwindSafe` is not implemented for `UnsafeCell` = note: required because it appears within the type `Cell` = note: required because of the requirements on the impl of `UnwindSafe` for `&Cell` + = note: required because it appears within the type `(&Cell,)` = note: required because it appears within the type `[closure@$DIR/interior-mutability.rs:5:18: 5:35]` error: aborting due to previous error diff --git a/src/test/ui/kindck/kindck-nonsendable-1.stderr b/src/test/ui/kindck/kindck-nonsendable-1.stderr index c7d67a991bffc..f942088eb7ec6 100644 --- a/src/test/ui/kindck/kindck-nonsendable-1.stderr +++ b/src/test/ui/kindck/kindck-nonsendable-1.stderr @@ -10,6 +10,7 @@ LL | bar(move|| foo(x)); | `Rc` cannot be sent between threads safely | = help: within `[closure@$DIR/kindck-nonsendable-1.rs:9:9: 9:22]`, the trait `Send` is not implemented for `Rc` + = note: required because it appears within the type `(Rc,)` = note: required because it appears within the type `[closure@$DIR/kindck-nonsendable-1.rs:9:9: 9:22]` error: aborting due to previous error diff --git a/src/test/ui/mismatched_types/issue-36053-2.stderr b/src/test/ui/mismatched_types/issue-36053-2.stderr index 63c04bcd7badb..0b1fcf58e2e00 100644 --- a/src/test/ui/mismatched_types/issue-36053-2.stderr +++ b/src/test/ui/mismatched_types/issue-36053-2.stderr @@ -1,3 +1,11 @@ +error[E0631]: type mismatch in closure arguments + --> $DIR/issue-36053-2.rs:7:32 + | +LL | once::<&str>("str").fuse().filter(|a: &str| true).count(); + | ^^^^^^ -------------- found signature of `for<'r> fn(&'r str) -> _` + | | + | expected signature of `for<'r> fn(&'r &str) -> _` + error[E0599]: no method named `count` found for struct `Filter>, [closure@$DIR/issue-36053-2.rs:7:39: 7:53]>` in the current scope --> $DIR/issue-36053-2.rs:7:55 | @@ -20,14 +28,6 @@ LL | pub struct Filter { `Filter>, [closure@$DIR/issue-36053-2.rs:7:39: 7:53]>: Iterator` which is required by `&mut Filter>, [closure@$DIR/issue-36053-2.rs:7:39: 7:53]>: Iterator` -error[E0631]: type mismatch in closure arguments - --> $DIR/issue-36053-2.rs:7:32 - | -LL | once::<&str>("str").fuse().filter(|a: &str| true).count(); - | ^^^^^^ -------------- found signature of `for<'r> fn(&'r str) -> _` - | | - | expected signature of `for<'r> fn(&'r &str) -> _` - error: aborting due to 2 previous errors Some errors have detailed explanations: E0599, E0631. diff --git a/src/test/ui/no-send-res-ports.stderr b/src/test/ui/no-send-res-ports.stderr index ef7fb4ad7b266..8842b18158640 100644 --- a/src/test/ui/no-send-res-ports.stderr +++ b/src/test/ui/no-send-res-ports.stderr @@ -19,6 +19,7 @@ LL | F: Send + 'static, = help: within `[closure@$DIR/no-send-res-ports.rs:25:19: 29:6]`, the trait `Send` is not implemented for `Rc<()>` = note: required because it appears within the type `Port<()>` = note: required because it appears within the type `Foo` + = note: required because it appears within the type `(Foo,)` = note: required because it appears within the type `[closure@$DIR/no-send-res-ports.rs:25:19: 29:6]` error: aborting due to previous error From 08d1ab0bf1c01948135548f5404eb625e454160e Mon Sep 17 00:00:00 2001 From: Aman Arora Date: Thu, 1 Oct 2020 21:06:16 -0400 Subject: [PATCH 2/4] Always return tupled_upvar_tys for Closure/Generator consituent tys Depending on if upvar_tys inferred or not, we were returning either an inference variable which later resolves to a tuple or else the upvar tys themselves Co-authored-by: Roxane Fruytier --- .../src/traits/select/mod.rs | 24 ++++--------------- src/test/ui/async-await/issue-68112.stderr | 1 + src/test/ui/generator/issue-68112.stderr | 1 + .../print/generator-print-verbose-1.stderr | 1 + .../ui/impl-trait/auto-trait-leak2.stderr | 2 ++ 5 files changed, 9 insertions(+), 20 deletions(-) diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index efe01191e589d..c21012591b609 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -1708,29 +1708,13 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { ty::Closure(_, ref substs) => { let ty = self.infcx.shallow_resolve(substs.as_closure().tupled_upvars_ty()); - if let ty::Infer(ty::TyVar(_)) = ty.kind() { - // The inference variable will be replaced by a tuple once capture analysis - // completes. If the tuple meets a bound, so do all the elements within it. - vec![ty] - } else { - substs.as_closure().upvar_tys().collect() - } + vec![ty] } ty::Generator(_, ref substs, _) => { - let upvar_tys_resolved = - self.infcx.shallow_resolve(substs.as_generator().tupled_upvars_ty()); - - if let ty::Infer(ty::TyVar(_)) = upvar_tys_resolved.kind() { - // The inference variable will be replaced by a tuple once capture analysis - // completes, if the tuple meets a bound, so do all the elements within it. - let witness_resolved = - self.infcx.shallow_resolve(substs.as_generator().witness()); - vec![upvar_tys_resolved, witness_resolved] - } else { - let witness = substs.as_generator().witness(); - substs.as_generator().upvar_tys().chain(iter::once(witness)).collect() - } + let ty = self.infcx.shallow_resolve(substs.as_generator().tupled_upvars_ty()); + let witness = substs.as_generator().witness(); + vec![ty].into_iter().chain(iter::once(witness)).collect() } ty::GeneratorWitness(types) => { diff --git a/src/test/ui/async-await/issue-68112.stderr b/src/test/ui/async-await/issue-68112.stderr index e97d088cf3ed3..a6c93e91a9eba 100644 --- a/src/test/ui/async-await/issue-68112.stderr +++ b/src/test/ui/async-await/issue-68112.stderr @@ -41,6 +41,7 @@ LL | require_send(send_fut); | = help: the trait `Sync` is not implemented for `RefCell` = note: required because of the requirements on the impl of `Send` for `Arc>` + = note: required because it appears within the type `(Arc>,)` = note: required because it appears within the type `[static generator@$DIR/issue-68112.rs:47:31: 47:36 {}]` = note: required because it appears within the type `from_generator::GenFuture<[static generator@$DIR/issue-68112.rs:47:31: 47:36 {}]>` = note: required because it appears within the type `impl Future` diff --git a/src/test/ui/generator/issue-68112.stderr b/src/test/ui/generator/issue-68112.stderr index 96a8d6d70e016..5793bbd950ec0 100644 --- a/src/test/ui/generator/issue-68112.stderr +++ b/src/test/ui/generator/issue-68112.stderr @@ -29,6 +29,7 @@ LL | require_send(send_gen); | = help: the trait `Sync` is not implemented for `RefCell` = note: required because of the requirements on the impl of `Send` for `Arc>` + = note: required because it appears within the type `(Arc>,)` = note: required because it appears within the type `[generator@$DIR/issue-68112.rs:38:5: 41:6 {()}]` = note: required because it appears within the type `impl Generator` = note: required because it appears within the type `impl Generator` diff --git a/src/test/ui/generator/print/generator-print-verbose-1.stderr b/src/test/ui/generator/print/generator-print-verbose-1.stderr index b5c63584c6c14..9669f4d96b9d1 100644 --- a/src/test/ui/generator/print/generator-print-verbose-1.stderr +++ b/src/test/ui/generator/print/generator-print-verbose-1.stderr @@ -29,6 +29,7 @@ LL | require_send(send_gen); | = help: the trait `Sync` is not implemented for `RefCell` = note: required because of the requirements on the impl of `Send` for `Arc>` + = note: required because it appears within the type `(Arc>,)` = note: required because it appears within the type `[make_gen2>>::{closure#0} upvar_tys=(Arc>) {()}]` = note: required because it appears within the type `Opaque(DefId(0:29 ~ generator_print_verbose_1[317d]::make_gen2::{opaque#0}), [std::sync::Arc>])` = note: required because it appears within the type `Opaque(DefId(0:32 ~ generator_print_verbose_1[317d]::make_non_send_generator2::{opaque#0}), [])` diff --git a/src/test/ui/impl-trait/auto-trait-leak2.stderr b/src/test/ui/impl-trait/auto-trait-leak2.stderr index 6b2b8248a4f21..fc2bc62f3a788 100644 --- a/src/test/ui/impl-trait/auto-trait-leak2.stderr +++ b/src/test/ui/impl-trait/auto-trait-leak2.stderr @@ -11,6 +11,7 @@ LL | send(before()); | ^^^^ `Rc>` cannot be sent between threads safely | = help: within `impl Fn<(i32,)>`, the trait `Send` is not implemented for `Rc>` + = note: required because it appears within the type `(Rc>,)` = note: required because it appears within the type `[closure@$DIR/auto-trait-leak2.rs:7:5: 7:22]` = note: required because it appears within the type `impl Fn<(i32,)>` @@ -27,6 +28,7 @@ LL | fn after() -> impl Fn(i32) { | ------------ within this `impl Fn<(i32,)>` | = help: within `impl Fn<(i32,)>`, the trait `Send` is not implemented for `Rc>` + = note: required because it appears within the type `(Rc>,)` = note: required because it appears within the type `[closure@$DIR/auto-trait-leak2.rs:24:5: 24:22]` = note: required because it appears within the type `impl Fn<(i32,)>` From 3c46fd67f8b4831da9f2e8a536d34f498cf70241 Mon Sep 17 00:00:00 2001 From: Aman Arora Date: Thu, 8 Oct 2020 00:28:53 -0400 Subject: [PATCH 3/4] traits diagnostics: Don't print closure/generator upvar_tys tuple Co-authored-by: Roxane Fruytier --- .../src/traits/error_reporting/suggestions.rs | 24 ++++++++++++++++++- src/test/ui/async-await/issue-68112.stderr | 1 - src/test/ui/closures/closure-move-sync.stderr | 2 -- src/test/ui/generator/issue-68112.stderr | 1 - src/test/ui/generator/not-send-sync.stderr | 1 - .../print/generator-print-verbose-1.stderr | 1 - .../print/generator-print-verbose-2.stderr | 1 - .../ui/impl-trait/auto-trait-leak2.stderr | 2 -- .../interior-mutability.stderr | 1 - .../ui/kindck/kindck-nonsendable-1.stderr | 1 - src/test/ui/no-send-res-ports.stderr | 1 - 11 files changed, 23 insertions(+), 13 deletions(-) diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs index 5908e73d4833b..7e86548f6ab9a 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs @@ -1922,7 +1922,29 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { return; } - err.note(&format!("required because it appears within the type `{}`", ty)); + // If the obligation for a tuple is set directly by a Generator or Closure, + // then the tuple must be the one containing capture types. + let is_upvar_tys_infer_tuple = if !matches!(ty.kind(), ty::Tuple(..)) { + false + } else { + if let ObligationCauseCode::BuiltinDerivedObligation(ref data) = + *data.parent_code + { + let parent_trait_ref = + self.resolve_vars_if_possible(&data.parent_trait_ref); + let ty = parent_trait_ref.skip_binder().self_ty(); + matches!(ty.kind(), ty::Generator(..)) + || matches!(ty.kind(), ty::Closure(..)) + } else { + false + } + }; + + // Don't print the tuple of capture types + if !is_upvar_tys_infer_tuple { + err.note(&format!("required because it appears within the type `{}`", ty)); + } + obligated_types.push(ty); let parent_predicate = parent_trait_ref.without_const().to_predicate(tcx); diff --git a/src/test/ui/async-await/issue-68112.stderr b/src/test/ui/async-await/issue-68112.stderr index a6c93e91a9eba..e97d088cf3ed3 100644 --- a/src/test/ui/async-await/issue-68112.stderr +++ b/src/test/ui/async-await/issue-68112.stderr @@ -41,7 +41,6 @@ LL | require_send(send_fut); | = help: the trait `Sync` is not implemented for `RefCell` = note: required because of the requirements on the impl of `Send` for `Arc>` - = note: required because it appears within the type `(Arc>,)` = note: required because it appears within the type `[static generator@$DIR/issue-68112.rs:47:31: 47:36 {}]` = note: required because it appears within the type `from_generator::GenFuture<[static generator@$DIR/issue-68112.rs:47:31: 47:36 {}]>` = note: required because it appears within the type `impl Future` diff --git a/src/test/ui/closures/closure-move-sync.stderr b/src/test/ui/closures/closure-move-sync.stderr index 285b6543833ae..da5e25c0d18fa 100644 --- a/src/test/ui/closures/closure-move-sync.stderr +++ b/src/test/ui/closures/closure-move-sync.stderr @@ -11,7 +11,6 @@ LL | F: Send + 'static, | = help: the trait `Sync` is not implemented for `std::sync::mpsc::Receiver<()>` = note: required because of the requirements on the impl of `Send` for `&std::sync::mpsc::Receiver<()>` - = note: required because it appears within the type `(&std::sync::mpsc::Receiver<()>,)` = note: required because it appears within the type `[closure@$DIR/closure-move-sync.rs:6:27: 9:6]` error[E0277]: `Sender<()>` cannot be shared between threads safely @@ -27,7 +26,6 @@ LL | F: Send + 'static, | = help: the trait `Sync` is not implemented for `Sender<()>` = note: required because of the requirements on the impl of `Send` for `&Sender<()>` - = note: required because it appears within the type `(&Sender<()>,)` = note: required because it appears within the type `[closure@$DIR/closure-move-sync.rs:18:19: 18:42]` error: aborting due to 2 previous errors diff --git a/src/test/ui/generator/issue-68112.stderr b/src/test/ui/generator/issue-68112.stderr index 5793bbd950ec0..96a8d6d70e016 100644 --- a/src/test/ui/generator/issue-68112.stderr +++ b/src/test/ui/generator/issue-68112.stderr @@ -29,7 +29,6 @@ LL | require_send(send_gen); | = help: the trait `Sync` is not implemented for `RefCell` = note: required because of the requirements on the impl of `Send` for `Arc>` - = note: required because it appears within the type `(Arc>,)` = note: required because it appears within the type `[generator@$DIR/issue-68112.rs:38:5: 41:6 {()}]` = note: required because it appears within the type `impl Generator` = note: required because it appears within the type `impl Generator` diff --git a/src/test/ui/generator/not-send-sync.stderr b/src/test/ui/generator/not-send-sync.stderr index f5cfa83f50070..2384ed3d24972 100644 --- a/src/test/ui/generator/not-send-sync.stderr +++ b/src/test/ui/generator/not-send-sync.stderr @@ -9,7 +9,6 @@ LL | assert_send(|| { | = help: the trait `Sync` is not implemented for `Cell` = note: required because of the requirements on the impl of `Send` for `&Cell` - = note: required because it appears within the type `(&Cell,)` = note: required because it appears within the type `[generator@$DIR/not-send-sync.rs:16:17: 20:6 _]` error: generator cannot be shared between threads safely diff --git a/src/test/ui/generator/print/generator-print-verbose-1.stderr b/src/test/ui/generator/print/generator-print-verbose-1.stderr index 9669f4d96b9d1..b5c63584c6c14 100644 --- a/src/test/ui/generator/print/generator-print-verbose-1.stderr +++ b/src/test/ui/generator/print/generator-print-verbose-1.stderr @@ -29,7 +29,6 @@ LL | require_send(send_gen); | = help: the trait `Sync` is not implemented for `RefCell` = note: required because of the requirements on the impl of `Send` for `Arc>` - = note: required because it appears within the type `(Arc>,)` = note: required because it appears within the type `[make_gen2>>::{closure#0} upvar_tys=(Arc>) {()}]` = note: required because it appears within the type `Opaque(DefId(0:29 ~ generator_print_verbose_1[317d]::make_gen2::{opaque#0}), [std::sync::Arc>])` = note: required because it appears within the type `Opaque(DefId(0:32 ~ generator_print_verbose_1[317d]::make_non_send_generator2::{opaque#0}), [])` diff --git a/src/test/ui/generator/print/generator-print-verbose-2.stderr b/src/test/ui/generator/print/generator-print-verbose-2.stderr index f363ed6a3b9a6..f23949091d912 100644 --- a/src/test/ui/generator/print/generator-print-verbose-2.stderr +++ b/src/test/ui/generator/print/generator-print-verbose-2.stderr @@ -9,7 +9,6 @@ LL | assert_send(|| { | = help: the trait `Sync` is not implemented for `Cell` = note: required because of the requirements on the impl of `Send` for `&'_#3r Cell` - = note: required because it appears within the type `(&'_#3r Cell,)` = note: required because it appears within the type `[main::{closure#1} upvar_tys=(&'_#3r Cell) _#17t]` error: generator cannot be shared between threads safely diff --git a/src/test/ui/impl-trait/auto-trait-leak2.stderr b/src/test/ui/impl-trait/auto-trait-leak2.stderr index fc2bc62f3a788..6b2b8248a4f21 100644 --- a/src/test/ui/impl-trait/auto-trait-leak2.stderr +++ b/src/test/ui/impl-trait/auto-trait-leak2.stderr @@ -11,7 +11,6 @@ LL | send(before()); | ^^^^ `Rc>` cannot be sent between threads safely | = help: within `impl Fn<(i32,)>`, the trait `Send` is not implemented for `Rc>` - = note: required because it appears within the type `(Rc>,)` = note: required because it appears within the type `[closure@$DIR/auto-trait-leak2.rs:7:5: 7:22]` = note: required because it appears within the type `impl Fn<(i32,)>` @@ -28,7 +27,6 @@ LL | fn after() -> impl Fn(i32) { | ------------ within this `impl Fn<(i32,)>` | = help: within `impl Fn<(i32,)>`, the trait `Send` is not implemented for `Rc>` - = note: required because it appears within the type `(Rc>,)` = note: required because it appears within the type `[closure@$DIR/auto-trait-leak2.rs:24:5: 24:22]` = note: required because it appears within the type `impl Fn<(i32,)>` diff --git a/src/test/ui/interior-mutability/interior-mutability.stderr b/src/test/ui/interior-mutability/interior-mutability.stderr index cddfe6c694666..dd43da1166445 100644 --- a/src/test/ui/interior-mutability/interior-mutability.stderr +++ b/src/test/ui/interior-mutability/interior-mutability.stderr @@ -12,7 +12,6 @@ LL | pub fn catch_unwind R + UnwindSafe, R>(f: F) -> Result { = help: within `Cell`, the trait `RefUnwindSafe` is not implemented for `UnsafeCell` = note: required because it appears within the type `Cell` = note: required because of the requirements on the impl of `UnwindSafe` for `&Cell` - = note: required because it appears within the type `(&Cell,)` = note: required because it appears within the type `[closure@$DIR/interior-mutability.rs:5:18: 5:35]` error: aborting due to previous error diff --git a/src/test/ui/kindck/kindck-nonsendable-1.stderr b/src/test/ui/kindck/kindck-nonsendable-1.stderr index f942088eb7ec6..c7d67a991bffc 100644 --- a/src/test/ui/kindck/kindck-nonsendable-1.stderr +++ b/src/test/ui/kindck/kindck-nonsendable-1.stderr @@ -10,7 +10,6 @@ LL | bar(move|| foo(x)); | `Rc` cannot be sent between threads safely | = help: within `[closure@$DIR/kindck-nonsendable-1.rs:9:9: 9:22]`, the trait `Send` is not implemented for `Rc` - = note: required because it appears within the type `(Rc,)` = note: required because it appears within the type `[closure@$DIR/kindck-nonsendable-1.rs:9:9: 9:22]` error: aborting due to previous error diff --git a/src/test/ui/no-send-res-ports.stderr b/src/test/ui/no-send-res-ports.stderr index 8842b18158640..ef7fb4ad7b266 100644 --- a/src/test/ui/no-send-res-ports.stderr +++ b/src/test/ui/no-send-res-ports.stderr @@ -19,7 +19,6 @@ LL | F: Send + 'static, = help: within `[closure@$DIR/no-send-res-ports.rs:25:19: 29:6]`, the trait `Send` is not implemented for `Rc<()>` = note: required because it appears within the type `Port<()>` = note: required because it appears within the type `Foo` - = note: required because it appears within the type `(Foo,)` = note: required because it appears within the type `[closure@$DIR/no-send-res-ports.rs:25:19: 29:6]` error: aborting due to previous error From a64ad51ff7ae2f82d4aed5bc4d3a7c3d3b7c7117 Mon Sep 17 00:00:00 2001 From: Roxane Date: Wed, 14 Oct 2020 00:17:42 -0400 Subject: [PATCH 4/4] Address comments --- compiler/rustc_middle/src/ty/outlives.rs | 20 ++-------- .../rustc_trait_selection/src/opaque_types.rs | 40 +++++++------------ compiler/rustc_traits/src/dropck_outlives.rs | 9 +++++ 3 files changed, 27 insertions(+), 42 deletions(-) diff --git a/compiler/rustc_middle/src/ty/outlives.rs b/compiler/rustc_middle/src/ty/outlives.rs index 708c92af14628..86750d5c08111 100644 --- a/compiler/rustc_middle/src/ty/outlives.rs +++ b/compiler/rustc_middle/src/ty/outlives.rs @@ -96,26 +96,14 @@ fn compute_components( } ty::Closure(_, ref substs) => { - if substs.as_closure().is_valid() { - for upvar_ty in substs.as_closure().upvar_tys() { - compute_components(tcx, upvar_ty, out, visited); - } - } else { - let tupled_ty = substs.as_closure().tupled_upvars_ty(); - compute_components(tcx, tupled_ty, out, visited); - } + let tupled_ty = substs.as_closure().tupled_upvars_ty(); + compute_components(tcx, tupled_ty, out, visited); } ty::Generator(_, ref substs, _) => { // Same as the closure case - if substs.as_generator().is_valid() { - for upvar_ty in substs.as_generator().upvar_tys() { - compute_components(tcx, upvar_ty, out, visited); - } - } else { - let tupled_ty = substs.as_generator().tupled_upvars_ty(); - compute_components(tcx, tupled_ty, out, visited); - } + let tupled_ty = substs.as_generator().tupled_upvars_ty(); + compute_components(tcx, tupled_ty, out, visited); // We ignore regions in the generator interior as we don't // want these to affect region inference diff --git a/compiler/rustc_trait_selection/src/opaque_types.rs b/compiler/rustc_trait_selection/src/opaque_types.rs index 087f6a0deece7..ecaafee77e29f 100644 --- a/compiler/rustc_trait_selection/src/opaque_types.rs +++ b/compiler/rustc_trait_selection/src/opaque_types.rs @@ -441,7 +441,6 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { for required_region in required_region_bounds { concrete_ty.visit_with(&mut ConstrainOpaqueTypeRegionVisitor { - infcx: self, op: |r| self.sub_regions(infer::CallReturn(span), required_region, r), }); } @@ -510,7 +509,6 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { } } concrete_ty.visit_with(&mut ConstrainOpaqueTypeRegionVisitor { - infcx: self, op: |r| self.sub_regions(infer::CallReturn(span), least_region, r), }); } @@ -545,7 +543,6 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { ); concrete_ty.visit_with(&mut ConstrainOpaqueTypeRegionVisitor { - infcx: self, op: |r| { self.member_constraint( opaque_type_def_id, @@ -686,12 +683,11 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { // // We ignore any type parameters because impl trait values are assumed to // capture all the in-scope type parameters. -struct ConstrainOpaqueTypeRegionVisitor<'cx, 'tcx, OP> { - infcx: &'cx InferCtxt<'cx, 'tcx>, +struct ConstrainOpaqueTypeRegionVisitor { op: OP, } -impl<'cx, 'tcx, OP> TypeVisitor<'tcx> for ConstrainOpaqueTypeRegionVisitor<'cx, 'tcx, OP> +impl<'tcx, OP> TypeVisitor<'tcx> for ConstrainOpaqueTypeRegionVisitor where OP: FnMut(ty::Region<'tcx>), { @@ -721,36 +717,28 @@ where ty::Closure(_, ref substs) => { // Skip lifetime parameters of the enclosing item(s) - let ty = self.infcx.shallow_resolve(substs.as_closure().tupled_upvars_ty()); - if let ty::Infer(ty::TyVar(_)) = ty.kind() { - // Not yet resolved. - ty.super_visit_with(self); - } else { - for upvar_ty in substs.as_closure().upvar_tys() { - upvar_ty.visit_with(self); - } + substs.as_closure().tupled_upvars_ty().visit_with(self); - substs.as_closure().sig_as_fn_ptr_ty().visit_with(self); + for upvar_ty in substs.as_closure().upvar_tys() { + upvar_ty.visit_with(self); } + + substs.as_closure().sig_as_fn_ptr_ty().visit_with(self); } ty::Generator(_, ref substs, _) => { // Skip lifetime parameters of the enclosing item(s) // Also skip the witness type, because that has no free regions. - let ty = self.infcx.shallow_resolve(substs.as_generator().tupled_upvars_ty()); - if let ty::Infer(ty::TyVar(_)) = ty.kind() { - // Not yet resolved. - ty.super_visit_with(self); - } else { - for upvar_ty in substs.as_generator().upvar_tys() { - upvar_ty.visit_with(self); - } + substs.as_generator().tupled_upvars_ty().visit_with(self); - substs.as_generator().return_ty().visit_with(self); - substs.as_generator().yield_ty().visit_with(self); - substs.as_generator().resume_ty().visit_with(self); + for upvar_ty in substs.as_generator().upvar_tys() { + upvar_ty.visit_with(self); } + + substs.as_generator().return_ty().visit_with(self); + substs.as_generator().yield_ty().visit_with(self); + substs.as_generator().resume_ty().visit_with(self); } _ => { ty.super_visit_with(self); diff --git a/compiler/rustc_traits/src/dropck_outlives.rs b/compiler/rustc_traits/src/dropck_outlives.rs index bbd3a7229a99b..6cffa6d02a4e3 100644 --- a/compiler/rustc_traits/src/dropck_outlives.rs +++ b/compiler/rustc_traits/src/dropck_outlives.rs @@ -214,6 +214,11 @@ fn dtorck_constraint_for_ty<'tcx>( if !substs.as_closure().is_valid() { // By the time this code runs, all type variables ought to // be fully resolved. + + tcx.sess.delay_span_bug( + span, + &format!("upvar_tys for closure not found. Expected capture information for closure {}", ty,), + ); return Err(NoSolution); } @@ -252,6 +257,10 @@ fn dtorck_constraint_for_ty<'tcx>( if !substs.as_generator().is_valid() { // By the time this code runs, all type variables ought to // be fully resolved. + tcx.sess.delay_span_bug( + span, + &format!("upvar_tys for generator not found. Expected capture information for generator {}", ty,), + ); return Err(NoSolution); }