From a5d103ff90f4ad90b1f13f5b5de83a3eb758d9e2 Mon Sep 17 00:00:00 2001 From: csmoe Date: Tue, 5 May 2020 23:26:33 +0800 Subject: [PATCH] record upvar into GeneratorInteriorTypeCause --- .../traits/error_reporting/suggestions.rs | 35 +++++++++--------- .../check/generator_interior.rs | 36 ++++++++++++++++--- src/test/ui/async-await/issue-70818.rs | 6 ++-- 3 files changed, 54 insertions(+), 23 deletions(-) diff --git a/src/librustc_trait_selection/traits/error_reporting/suggestions.rs b/src/librustc_trait_selection/traits/error_reporting/suggestions.rs index cd1c75dc5f2..9525910e39c 100644 --- a/src/librustc_trait_selection/traits/error_reporting/suggestions.rs +++ b/src/librustc_trait_selection/traits/error_reporting/suggestions.rs @@ -1454,26 +1454,27 @@ fn note_obligation_cause_for_async_await( format!("{} occurs here, with `{}` maybe used later", await_or_yield, snippet), ); - span.push_span_label( - target_span, - format!("has type `{}` which {}", target_ty, trait_explanation), - ); - - // If available, use the scope span to annotate the drop location. - if let Some(scope_span) = scope_span { span.push_span_label( - source_map.end_point(*scope_span), - format!("`{}` is later dropped here", snippet), + target_span, + format!("has type `{}` which {}", target_ty, trait_explanation), ); - } - err.span_note( - span, - &format!( - "{} {} as this value is used across {}", - future_or_generator, trait_explanation, an_await_or_yield - ), - ); + // If available, use the scope span to annotate the drop location. + if let Some(scope_span) = scope_span { + span.push_span_label( + source_map.end_point(*scope_span), + format!("`{}` is later dropped here", snippet), + ); + } + + err.span_note( + span, + &format!( + "{} {} as this value is used across {}", + future_or_generator, trait_explanation, an_await_or_yield + ), + ); + } } if let Some(expr_id) = expr { diff --git a/src/librustc_typeck/check/generator_interior.rs b/src/librustc_typeck/check/generator_interior.rs index ce376a08ea6..aa4abcd7224 100644 --- a/src/librustc_typeck/check/generator_interior.rs +++ b/src/librustc_typeck/check/generator_interior.rs @@ -16,6 +16,7 @@ struct InteriorVisitor<'a, 'tcx> { fcx: &'a FnCtxt<'a, 'tcx>, + closure_def_id: DefId, types: FxHashMap, usize>, region_scope_tree: &'tcx region::ScopeTree, expr_count: usize, @@ -30,6 +31,7 @@ fn record( scope: Option, expr: Option<&'tcx Expr<'tcx>>, source_span: Span, + is_upvar: bool, ) { use rustc_span::DUMMY_SP; @@ -96,7 +98,7 @@ fn record( span: source_span, ty: &ty, scope_span, - yield_span: yield_data.span, + yield_span: Some(yield_data.span), expr: expr.map(|e| e.hir_id), }) .or_insert(entries); @@ -117,6 +119,20 @@ fn record( unresolved_type, unresolved_type_span ); self.prev_unresolved_span = unresolved_type_span; + } else { + if is_upvar { + let entries = self.types.len(); + let scope_span = scope.map(|s| s.span(self.fcx.tcx, self.region_scope_tree)); + self.types + .entry(ty::GeneratorInteriorTypeCause { + span: source_span, + ty: &ty, + scope_span, + yield_span: None, + expr: expr.map(|e| e.hir_id), + }) + .or_insert(entries); + } } } } @@ -130,8 +146,12 @@ pub fn resolve_interior<'a, 'tcx>( kind: hir::GeneratorKind, ) { let body = fcx.tcx.hir().body(body_id); + + let closure_def_id = fcx.tcx.hir().body_owner_def_id(body_id).to_def_id(); + let mut visitor = InteriorVisitor { fcx, + closure_def_id, types: FxHashMap::default(), region_scope_tree: fcx.tcx.region_scope_tree(def_id), expr_count: 0, @@ -223,7 +243,7 @@ fn visit_pat(&mut self, pat: &'tcx Pat<'tcx>) { if let PatKind::Binding(..) = pat.kind { let scope = self.region_scope_tree.var_scope(pat.hir_id.local_id); let ty = self.fcx.tables.borrow().pat_ty(pat); - self.record(ty, Some(scope), None, pat.span); + self.record(ty, Some(scope), None, pat.span, false); } } @@ -264,7 +284,7 @@ fn visit_expr(&mut self, expr: &'tcx Expr<'tcx>) { // If there are adjustments, then record the final type -- // this is the actual value that is being produced. if let Some(adjusted_ty) = self.fcx.tables.borrow().expr_ty_adjusted_opt(expr) { - self.record(adjusted_ty, scope, Some(expr), expr.span); + self.record(adjusted_ty, scope, Some(expr), expr.span, false); } // Also record the unadjusted type (which is the only type if @@ -292,9 +312,17 @@ fn visit_expr(&mut self, expr: &'tcx Expr<'tcx>) { // The type table might not have information for this expression // if it is in a malformed scope. (#66387) if let Some(ty) = self.fcx.tables.borrow().expr_ty_opt(expr) { - self.record(ty, scope, Some(expr), expr.span); + self.record(ty, scope, Some(expr), expr.span, false); } else { self.fcx.tcx.sess.delay_span_bug(expr.span, "no type for node"); } + + if let Some(upvars) = self.fcx.tcx.upvars(self.closure_def_id) { + for (upvar_id, upvar) in upvars.iter() { + let upvar_ty = self.fcx.tables.borrow().node_type(*upvar_id); + debug!("type of upvar: {:?}", upvar_ty); + self.record(upvar_ty, scope, Some(expr), upvar.span, true); + } + } } } diff --git a/src/test/ui/async-await/issue-70818.rs b/src/test/ui/async-await/issue-70818.rs index b914c9b17ab..9bbaacd2f11 100644 --- a/src/test/ui/async-await/issue-70818.rs +++ b/src/test/ui/async-await/issue-70818.rs @@ -1,5 +1,7 @@ // edition 2018 -fn d(t: T) -> impl std::future::Future + Send { //~ Error `T` cannot be sent between threads safely - async { t } +fn foo(ty: T) -> impl std::future::Future + Send { //~ Error `T` cannot be sent between threads safely + async { ty } } + +fn main() {} -- 2.44.0