Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
050643a
Add Frames iterator for Backtrace
seanchen1991 Jan 13, 2021
61f6fa7
move a bunch of tests
lcnr Jan 28, 2021
fe1fc36
Add some test for ATB issues
jackh726 Jan 28, 2021
6c14aad
Improve handling of spans around macro result parse errors
Aaron1011 Jan 31, 2021
7bc09f7
Remove the remains of the query categories.
Jan 31, 2021
988d93c
Indent the code correctly again after removing the query categories.
Jan 31, 2021
82010e8
rustdoc: Note why `rustdoc::html::markdown` is public
camelid Jan 28, 2021
bf4bdd9
Add lint for 2229 migrations
arora-aman Dec 28, 2020
9989334
Add SAFETY comment for the `TrustedRandomAccess` impl of `iter::Fuse`
sdroege Feb 1, 2021
12b605a
Implement `TrustedLen` for `iter::Fuse<I: TrustedLen>`
sdroege Jan 31, 2021
8e34522
Remove unneeded `mut` variable
LingMan Jan 20, 2021
899b0dd
Fix overflowing text on mobile when sidebar is displayed
GuillaumeGomez Feb 1, 2021
7f8530f
more things are const evaluatable *sparkles*
BoxyUwU Feb 1, 2021
d3e8501
Process mentioned upvars for analysis first pass after ExprUseVisitor
arora-aman Nov 21, 2020
cc5e6db
Migrations first pass
arora-aman Dec 15, 2020
3c71a7b
Tests for 2229 lint
arora-aman Dec 30, 2020
caf06bf
Mark the lint doc as compile_fail
arora-aman Jan 3, 2021
8f15cc1
PR fixup
arora-aman Jan 19, 2021
84f0a0a
New migration
arora-aman Jan 26, 2021
a188791
Rollup merge of #80629 - sexxi-goose:migrations_1, r=nikomatsakis
jonas-schievink Feb 2, 2021
f61ab58
Rollup merge of #81022 - seanchen1991:feat/frames-iter, r=KodrAus
jonas-schievink Feb 2, 2021
e6e76c7
Rollup merge of #81481 - lcnr:cast-tests, r=jackh726
jonas-schievink Feb 2, 2021
a61e6ab
Rollup merge of #81485 - jackh726:atb-issues, r=Mark-Simulacrum
jonas-schievink Feb 2, 2021
30f12a0
Rollup merge of #81492 - camelid:rustdoc-internal-mod-vis, r=Guillaum…
jonas-schievink Feb 2, 2021
efec2bb
Rollup merge of #81577 - BoxyUwU:subexpr_const_evaluatable, r=oli-obk
jonas-schievink Feb 2, 2021
86d0e6d
Rollup merge of #81599 - sdroege:fuse-trusted-len, r=m-ou-se
jonas-schievink Feb 2, 2021
255e076
Rollup merge of #81608 - Aaron1011:macro-res-parse-err, r=davidtwco
jonas-schievink Feb 2, 2021
285524f
Rollup merge of #81609 - Julian-Wollersberger:no-query-categories, r=…
jonas-schievink Feb 2, 2021
d2f96a9
Rollup merge of #81630 - GuillaumeGomez:overflow-sidebar-title-text, …
jonas-schievink Feb 2, 2021
73f859e
Rollup merge of #81631 - LingMan:rem_var, r=davidtwco
jonas-schievink Feb 2, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Migrations first pass
  • Loading branch information
arora-aman committed Feb 1, 2021
commit cc5e6db5f2d25fb1c0371455574db7aecbe0ba0c
132 changes: 131 additions & 1 deletion compiler/rustc_typeck/src/check/upvar.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
//! then mean that all later passes would have to check for these figments
//! and report an error, and it just seems like more mess in the end.)

use super::writeback::Resolver;
use super::FnCtxt;

use crate::expr_use_visitor as euv;
Expand All @@ -40,7 +41,9 @@ use rustc_hir::def_id::LocalDefId;
use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor};
use rustc_infer::infer::UpvarRegion;
use rustc_middle::hir::place::{Place, PlaceBase, PlaceWithHirId, ProjectionKind};
use rustc_middle::ty::fold::TypeFoldable;
use rustc_middle::ty::{self, Ty, TyCtxt, TypeckResults, UpvarSubsts};
use rustc_session::lint;
use rustc_span::sym;
use rustc_span::{MultiSpan, Span, Symbol};

Expand Down Expand Up @@ -97,7 +100,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
&self,
closure_hir_id: hir::HirId,
span: Span,
body: &hir::Body<'_>,
body: &'tcx hir::Body<'tcx>,
capture_clause: hir::CaptureBy,
) {
debug!("analyze_closure(id={:?}, body.id={:?})", closure_hir_id, body.id());
Expand Down Expand Up @@ -157,6 +160,38 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {

self.compute_min_captures(closure_def_id, delegate.capture_information);

let closure_hir_id = self.tcx.hir().local_def_id_to_hir_id(local_def_id);
if should_do_migration_analysis(self.tcx, closure_hir_id) {
let need_migrations = self.compute_2229_migrations_first_pass(
closure_def_id,
span,
capture_clause,
body,
self.typeck_results.borrow().closure_min_captures.get(&closure_def_id),
);

if !need_migrations.is_empty() {
let need_migrations_hir_id =
need_migrations.iter().map(|m| m.0).collect::<Vec<_>>();

let migrations_text =
migration_suggestion_for_2229(self.tcx, &need_migrations_hir_id);

self.tcx.struct_span_lint_hir(
lint::builtin::DISJOINT_CAPTURE_DROP_REORDER,
closure_hir_id,
span,
|lint| {
let mut diagnostics_builder = lint.build(
"drop order affected for closure because of `capture_disjoint_fields`",
);
diagnostics_builder.note(&migrations_text);
diagnostics_builder.emit();
},
);
}
}

// We now fake capture information for all variables that are mentioned within the closure
// We do this after handling migrations so that min_captures computes before
if !self.tcx.features().capture_disjoint_fields {
Expand Down Expand Up @@ -520,6 +555,86 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
typeck_results.closure_min_captures.insert(closure_def_id, root_var_min_capture_list);
}

/// Figures out the list of root variables (and their types) that aren't completely
/// captured by the closure when `capture_disjoint_fields` is enabled and drop order of
/// some path starting at that root variable **might** be affected.
///
/// The output list would include a root variable if:
/// - It would have been moved into the closure when `capture_disjoint_fields` wasn't
/// enabled, **and**
/// - It wasn't completely captured by the closure, **and**
/// - The type of the root variable needs Drop.
fn compute_2229_migrations_first_pass(
&self,
closure_def_id: DefId,
closure_span: Span,
closure_clause: hir::CaptureBy,
body: &'tcx hir::Body<'tcx>,
min_captures: Option<&ty::RootVariableMinCaptureList<'tcx>>,
) -> Vec<(hir::HirId, Ty<'tcx>)> {
fn resolve_ty<T: TypeFoldable<'tcx>>(
fcx: &FnCtxt<'_, 'tcx>,
span: Span,
body: &'tcx hir::Body<'tcx>,
ty: T,
) -> T {
let mut resolver = Resolver::new(fcx, &span, body);
ty.fold_with(&mut resolver)
}

let upvars = if let Some(upvars) = self.tcx.upvars_mentioned(closure_def_id) {
upvars
} else {
return vec![];
};

let mut need_migrations = Vec::new();

for (&var_hir_id, _) in upvars.iter() {
let ty = resolve_ty(self, closure_span, body, self.node_ty(var_hir_id));

if !ty.needs_drop(self.tcx, self.tcx.param_env(closure_def_id.expect_local())) {
continue;
}

let root_var_min_capture_list = if let Some(root_var_min_capture_list) =
min_captures.and_then(|m| m.get(&var_hir_id))
{
root_var_min_capture_list
} else {
// The upvar is mentioned within the closure but no path starting from it is
// used.

match closure_clause {
// Only migrate if closure is a move closure
hir::CaptureBy::Value => need_migrations.push((var_hir_id, ty)),

hir::CaptureBy::Ref => {}
}

continue;
};

let is_moved = root_var_min_capture_list
.iter()
.find(|capture| matches!(capture.info.capture_kind, ty::UpvarCapture::ByValue(_)))
.is_some();

// 1. If we capture more than one path starting at the root variabe then the root variable
// isn't being captured in its entirety
// 2. If we only capture one path starting at the root variable, it's still possible
// that it isn't the root variable completely.
if is_moved
&& ((root_var_min_capture_list.len() > 1)
|| (root_var_min_capture_list[0].place.projections.len() > 0))
{
need_migrations.push((var_hir_id, ty));
}
}

need_migrations
}

fn init_capture_kind(
&self,
capture_clause: hir::CaptureBy,
Expand Down Expand Up @@ -1136,6 +1251,21 @@ fn var_name(tcx: TyCtxt<'_>, var_hir_id: hir::HirId) -> Symbol {
tcx.hir().name(var_hir_id)
}

fn should_do_migration_analysis(tcx: TyCtxt<'_>, closure_id: hir::HirId) -> bool {
let (level, _) =
tcx.lint_level_at_node(lint::builtin::DISJOINT_CAPTURE_DROP_REORDER, closure_id);

!matches!(level, lint::Level::Allow)
}

fn migration_suggestion_for_2229(tcx: TyCtxt<'_>, need_migrations: &Vec<hir::HirId>) -> String {
let need_migrations_strings =
need_migrations.iter().map(|v| format!("{}", var_name(tcx, *v))).collect::<Vec<_>>();
let migrations_list_concat = need_migrations_strings.join(", ");

format!("let ({}) = ({});", migrations_list_concat, migrations_list_concat)
}

/// Helper function to determine if we need to escalate CaptureKind from
/// CaptureInfo A to B and returns the escalated CaptureInfo.
/// (Note: CaptureInfo contains CaptureKind and an expression that led to capture it in that way)
Expand Down
6 changes: 3 additions & 3 deletions compiler/rustc_typeck/src/check/writeback.rs
Original file line number Diff line number Diff line change
Expand Up @@ -650,7 +650,7 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
}
}

trait Locatable {
crate trait Locatable {
fn to_span(&self, tcx: TyCtxt<'_>) -> Span;
}

Expand All @@ -668,7 +668,7 @@ impl Locatable for hir::HirId {

/// The Resolver. This is the type folding engine that detects
/// unresolved types and so forth.
struct Resolver<'cx, 'tcx> {
crate struct Resolver<'cx, 'tcx> {
tcx: TyCtxt<'tcx>,
infcx: &'cx InferCtxt<'cx, 'tcx>,
span: &'cx dyn Locatable,
Expand All @@ -679,7 +679,7 @@ struct Resolver<'cx, 'tcx> {
}

impl<'cx, 'tcx> Resolver<'cx, 'tcx> {
fn new(
crate fn new(
fcx: &'cx FnCtxt<'cx, 'tcx>,
span: &'cx dyn Locatable,
body: &'tcx hir::Body<'tcx>,
Expand Down