diff --git a/src/librustc_trait_selection/traits/error_reporting/suggestions.rs b/src/librustc_trait_selection/traits/error_reporting/suggestions.rs index cd1c75dc5f29..9525910e39c6 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 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { 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), + ); + + // 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 + ), ); } - - 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 ce376a08ea60..aa4abcd72242 100644 --- a/src/librustc_typeck/check/generator_interior.rs +++ b/src/librustc_typeck/check/generator_interior.rs @@ -16,6 +16,7 @@ use rustc_span::Span; 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 @@ impl<'a, 'tcx> InteriorVisitor<'a, 'tcx> { scope: Option, expr: Option<&'tcx Expr<'tcx>>, source_span: Span, + is_upvar: bool, ) { use rustc_span::DUMMY_SP; @@ -96,7 +98,7 @@ impl<'a, 'tcx> InteriorVisitor<'a, 'tcx> { 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 @@ impl<'a, 'tcx> InteriorVisitor<'a, 'tcx> { 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 @@ impl<'a, 'tcx> Visitor<'tcx> for InteriorVisitor<'a, '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 @@ impl<'a, 'tcx> Visitor<'tcx> for InteriorVisitor<'a, '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 @@ impl<'a, 'tcx> Visitor<'tcx> for InteriorVisitor<'a, '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 b914c9b17abd..9bbaacd2f11b 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() {}