Skip to content

Commit 00a6797

Browse files
committed
Auto merge of #43108 - pnkfelix:mir-borrowck3c, r=arielb1
MIR borrow check (under debug flag) Here is the current state of MIR borrow check. It consists of (1.) some refactoring, (2.) a dataflow analysis to identify the borrows themselves, and (3.) a mir "transform" that does the borrow check itself based on the aforementioned dataflow results. (There's also a drive-by fix to dataflow that I can factor into a separate PR if necessary. Interestingly I could not find a way to observe the bug outside of MIR borrowck.) To be clear, this branch is not ready to be used as the default borrow check. Thus the code is guarded: To get mir-borrowck to run, you need to either supply an attribute `#[rustc_mir_borrowck]` or a debug flag `-Z borrowck-mir`. Here are the main issues with the current MIR borrowck as it stands in this PR: * No Notes emitted yet, just errors. (So the feedback is definitely inferior compared to AST borrowck today) * Lvalue rendering differs between Ast and Mir. (Mostly minor, but replacement of field names with indices is very bad; big priority for me to fix ASAP.) * Lots of ICEs (presumably because some MIR operations used here have well-formedness assumptions that are violated in borrowck-broken code) * Conflates lots of cases that are distinguished by AST-borrowck * Conflates "uninitialized" with "moved" (special case of previous bullet, one that I think should be fixed ASAP) (I am hoping to fix as many of the above issues as I can in the near term, but I also would like to land this even if they are *not* all fixed, because the rebasing effort is getting to be a real drag.)
2 parents c886246 + 8738a08 commit 00a6797

File tree

22 files changed

+2940
-1098
lines changed

22 files changed

+2940
-1098
lines changed

src/Cargo.lock

+1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/librustc/session/config.rs

+2
Original file line numberDiff line numberDiff line change
@@ -918,6 +918,8 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options,
918918
"when debug-printing compiler state, do not include spans"), // o/w tests have closure@path
919919
identify_regions: bool = (false, parse_bool, [UNTRACKED],
920920
"make unnamed regions display as '# (where # is some non-ident unique id)"),
921+
borrowck_mir: bool = (false, parse_bool, [UNTRACKED],
922+
"implicitly treat functions as if they have `#[rustc_mir_borrowck]` attribute"),
921923
time_passes: bool = (false, parse_bool, [UNTRACKED],
922924
"measure time of each rustc pass"),
923925
count_llvm_insns: bool = (false, parse_bool,

src/librustc_borrowck/borrowck/check_loans.rs

+22-37
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ use rustc::ty::{self, TyCtxt};
2929
use syntax::ast;
3030
use syntax_pos::Span;
3131
use rustc::hir;
32+
use rustc_mir::util::borrowck_errors::{BorrowckErrors, Origin};
3233

3334
use std::rc::Rc;
3435

@@ -465,10 +466,8 @@ impl<'a, 'tcx> CheckLoanCtxt<'a, 'tcx> {
465466

466467
let mut err = match (new_loan.kind, old_loan.kind) {
467468
(ty::MutBorrow, ty::MutBorrow) => {
468-
let mut err = struct_span_err!(self.bccx, new_loan.span, E0499,
469-
"cannot borrow `{}`{} as mutable \
470-
more than once at a time",
471-
nl, new_loan_msg);
469+
let mut err = self.bccx.cannot_mutably_borrow_multiply(
470+
new_loan.span, &nl, &new_loan_msg, Origin::Ast);
472471

473472
if new_loan.span == old_loan.span {
474473
// Both borrows are happening in the same place
@@ -496,10 +495,8 @@ impl<'a, 'tcx> CheckLoanCtxt<'a, 'tcx> {
496495
}
497496

498497
(ty::UniqueImmBorrow, ty::UniqueImmBorrow) => {
499-
let mut err = struct_span_err!(self.bccx, new_loan.span, E0524,
500-
"two closures require unique access to `{}` \
501-
at the same time",
502-
nl);
498+
let mut err = self.bccx.cannot_uniquely_borrow_by_two_closures(
499+
new_loan.span, &nl, Origin::Ast);
503500
err.span_label(
504501
old_loan.span,
505502
"first closure is constructed here");
@@ -513,10 +510,8 @@ impl<'a, 'tcx> CheckLoanCtxt<'a, 'tcx> {
513510
}
514511

515512
(ty::UniqueImmBorrow, _) => {
516-
let mut err = struct_span_err!(self.bccx, new_loan.span, E0500,
517-
"closure requires unique access to `{}` \
518-
but {} is already borrowed{}",
519-
nl, ol_pronoun, old_loan_msg);
513+
let mut err = self.bccx.cannot_uniquely_borrow_by_one_closure(
514+
new_loan.span, &nl, &ol_pronoun, &old_loan_msg, Origin::Ast);
520515
err.span_label(
521516
new_loan.span,
522517
format!("closure construction occurs here{}", new_loan_msg));
@@ -530,10 +525,9 @@ impl<'a, 'tcx> CheckLoanCtxt<'a, 'tcx> {
530525
}
531526

532527
(_, ty::UniqueImmBorrow) => {
533-
let mut err = struct_span_err!(self.bccx, new_loan.span, E0501,
534-
"cannot borrow `{}`{} as {} because \
535-
previous closure requires unique access",
536-
nl, new_loan_msg, new_loan.kind.to_user_str());
528+
let new_loan_str = &new_loan.kind.to_user_str();
529+
let mut err = self.bccx.cannot_reborrow_already_uniquely_borrowed(
530+
new_loan.span, &nl, &new_loan_msg, new_loan_str, Origin::Ast);
537531
err.span_label(
538532
new_loan.span,
539533
format!("borrow occurs here{}", new_loan_msg));
@@ -547,15 +541,10 @@ impl<'a, 'tcx> CheckLoanCtxt<'a, 'tcx> {
547541
}
548542

549543
(..) => {
550-
let mut err = struct_span_err!(self.bccx, new_loan.span, E0502,
551-
"cannot borrow `{}`{} as {} because \
552-
{} is also borrowed as {}{}",
553-
nl,
554-
new_loan_msg,
555-
new_loan.kind.to_user_str(),
556-
ol_pronoun,
557-
old_loan.kind.to_user_str(),
558-
old_loan_msg);
544+
let mut err = self.bccx.cannot_reborrow_already_borrowed(
545+
new_loan.span,
546+
&nl, &new_loan_msg, &new_loan.kind.to_user_str(),
547+
&ol_pronoun, &old_loan.kind.to_user_str(), &old_loan_msg, Origin::Ast);
559548
err.span_label(
560549
new_loan.span,
561550
format!("{} borrow occurs here{}",
@@ -645,9 +634,8 @@ impl<'a, 'tcx> CheckLoanCtxt<'a, 'tcx> {
645634
match self.analyze_restrictions_on_use(id, copy_path, ty::ImmBorrow) {
646635
UseOk => { }
647636
UseWhileBorrowed(loan_path, loan_span) => {
648-
struct_span_err!(self.bccx, span, E0503,
649-
"cannot use `{}` because it was mutably borrowed",
650-
&self.bccx.loan_path_to_string(copy_path))
637+
let desc = self.bccx.loan_path_to_string(copy_path);
638+
self.bccx.cannot_use_when_mutably_borrowed(span, &desc, Origin::Ast)
651639
.span_label(loan_span,
652640
format!("borrow of `{}` occurs here",
653641
&self.bccx.loan_path_to_string(&loan_path))
@@ -673,9 +661,8 @@ impl<'a, 'tcx> CheckLoanCtxt<'a, 'tcx> {
673661
UseWhileBorrowed(loan_path, loan_span) => {
674662
let mut err = match move_kind {
675663
move_data::Captured => {
676-
let mut err = struct_span_err!(self.bccx, span, E0504,
677-
"cannot move `{}` into closure because it is borrowed",
678-
&self.bccx.loan_path_to_string(move_path));
664+
let mut err = self.bccx.cannot_move_into_closure(
665+
span, &self.bccx.loan_path_to_string(move_path), Origin::Ast);
679666
err.span_label(
680667
loan_span,
681668
format!("borrow of `{}` occurs here",
@@ -690,9 +677,8 @@ impl<'a, 'tcx> CheckLoanCtxt<'a, 'tcx> {
690677
move_data::Declared |
691678
move_data::MoveExpr |
692679
move_data::MovePat => {
693-
let mut err = struct_span_err!(self.bccx, span, E0505,
694-
"cannot move out of `{}` because it is borrowed",
695-
&self.bccx.loan_path_to_string(move_path));
680+
let desc = self.bccx.loan_path_to_string(move_path);
681+
let mut err = self.bccx.cannot_move_when_borrowed(span, &desc, Origin::Ast);
696682
err.span_label(
697683
loan_span,
698684
format!("borrow of `{}` occurs here",
@@ -874,9 +860,8 @@ impl<'a, 'tcx> CheckLoanCtxt<'a, 'tcx> {
874860
span: Span,
875861
loan_path: &LoanPath<'tcx>,
876862
loan: &Loan) {
877-
struct_span_err!(self.bccx, span, E0506,
878-
"cannot assign to `{}` because it is borrowed",
879-
self.bccx.loan_path_to_string(loan_path))
863+
self.bccx.cannot_assign_to_borrowed(
864+
span, &self.bccx.loan_path_to_string(loan_path), Origin::Ast)
880865
.span_label(loan.span,
881866
format!("borrow of `{}` occurs here",
882867
self.bccx.loan_path_to_string(loan_path)))

src/librustc_borrowck/borrowck/mod.rs

+31-12
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,8 @@ use rustc::middle::free_region::RegionRelations;
3737
use rustc::ty::{self, TyCtxt};
3838
use rustc::ty::maps::Providers;
3939

40+
use rustc_mir::util::borrowck_errors::{BorrowckErrors, Origin};
41+
4042
use std::fmt;
4143
use std::rc::Rc;
4244
use std::hash::{Hash, Hasher};
@@ -218,6 +220,25 @@ pub struct BorrowckCtxt<'a, 'tcx: 'a> {
218220
owner_def_id: DefId,
219221
}
220222

223+
impl<'b, 'tcx: 'b> BorrowckErrors for BorrowckCtxt<'b, 'tcx> {
224+
fn struct_span_err_with_code<'a, S: Into<MultiSpan>>(&'a self,
225+
sp: S,
226+
msg: &str,
227+
code: &str)
228+
-> DiagnosticBuilder<'a>
229+
{
230+
self.tcx.sess.struct_span_err_with_code(sp, msg, code)
231+
}
232+
233+
fn struct_span_err<'a, S: Into<MultiSpan>>(&'a self,
234+
sp: S,
235+
msg: &str)
236+
-> DiagnosticBuilder<'a>
237+
{
238+
self.tcx.sess.struct_span_err(sp, msg)
239+
}
240+
}
241+
221242
///////////////////////////////////////////////////////////////////////////
222243
// Loans and loan paths
223244

@@ -549,14 +570,13 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> {
549570
move_data::Declared => {
550571
// If this is an uninitialized variable, just emit a simple warning
551572
// and return.
552-
struct_span_err!(
553-
self.tcx.sess, use_span, E0381,
554-
"{} of possibly uninitialized variable: `{}`",
555-
verb,
556-
self.loan_path_to_string(lp))
557-
.span_label(use_span, format!("use of possibly uninitialized `{}`",
558-
self.loan_path_to_string(lp)))
559-
.emit();
573+
self.cannot_act_on_uninitialized_variable(use_span,
574+
verb,
575+
&self.loan_path_to_string(lp),
576+
Origin::Ast)
577+
.span_label(use_span, format!("use of possibly uninitialized `{}`",
578+
self.loan_path_to_string(lp)))
579+
.emit();
560580
return;
561581
}
562582
_ => {
@@ -683,10 +703,9 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> {
683703
lp: &LoanPath<'tcx>,
684704
assign:
685705
&move_data::Assignment) {
686-
let mut err = struct_span_err!(
687-
self.tcx.sess, span, E0384,
688-
"re-assignment of immutable variable `{}`",
689-
self.loan_path_to_string(lp));
706+
let mut err = self.cannot_reassign_immutable(span,
707+
&self.loan_path_to_string(lp),
708+
Origin::Ast);
690709
err.span_label(span, "re-assignment of immutable variable");
691710
if span != assign.span {
692711
err.span_label(assign.span, format!("first assignment to `{}`",

0 commit comments

Comments
 (0)