Auto merge of #45938 - vramana:fix-ice-45698, r=arielb1
Fix End-user description not implemented for field access on `TyClosure - [x] Add Tests
This commit is contained in:
commit
fa26421f56
2 changed files with 80 additions and 31 deletions
|
@ -1021,7 +1021,7 @@ impl<'c, 'b, 'a: 'b+'c, 'gcx, 'tcx: 'a> MirBorrowckCtxt<'c, 'b, 'a, 'gcx, 'tcx>
|
||||||
access_lvalue: (ShallowOrDeep, &Lvalue<'tcx>),
|
access_lvalue: (ShallowOrDeep, &Lvalue<'tcx>),
|
||||||
flow_state: &InProgress<'b, 'gcx, 'tcx>,
|
flow_state: &InProgress<'b, 'gcx, 'tcx>,
|
||||||
mut op: F)
|
mut op: F)
|
||||||
where F: FnMut(&mut Self, BorrowIndex, &BorrowData<'tcx>, &Lvalue) -> Control
|
where F: FnMut(&mut Self, BorrowIndex, &BorrowData<'tcx>, &Lvalue<'tcx>) -> Control
|
||||||
{
|
{
|
||||||
let (access, lvalue) = access_lvalue;
|
let (access, lvalue) = access_lvalue;
|
||||||
|
|
||||||
|
@ -1248,7 +1248,7 @@ impl<'c, 'b, 'a: 'b+'c, 'gcx, 'tcx: 'a> MirBorrowckCtxt<'c, 'b, 'a, 'gcx, 'tcx>
|
||||||
fn report_use_of_moved_or_uninitialized(&mut self,
|
fn report_use_of_moved_or_uninitialized(&mut self,
|
||||||
_context: Context,
|
_context: Context,
|
||||||
desired_action: &str,
|
desired_action: &str,
|
||||||
(lvalue, span): (&Lvalue, Span),
|
(lvalue, span): (&Lvalue<'tcx>, Span),
|
||||||
mpi: MovePathIndex,
|
mpi: MovePathIndex,
|
||||||
curr_move_out: &IdxSetBuf<MoveOutIndex>) {
|
curr_move_out: &IdxSetBuf<MoveOutIndex>) {
|
||||||
|
|
||||||
|
@ -1290,8 +1290,8 @@ impl<'c, 'b, 'a: 'b+'c, 'gcx, 'tcx: 'a> MirBorrowckCtxt<'c, 'b, 'a, 'gcx, 'tcx>
|
||||||
|
|
||||||
fn report_move_out_while_borrowed(&mut self,
|
fn report_move_out_while_borrowed(&mut self,
|
||||||
_context: Context,
|
_context: Context,
|
||||||
(lvalue, span): (&Lvalue, Span),
|
(lvalue, span): (&Lvalue<'tcx>, Span),
|
||||||
borrow: &BorrowData) {
|
borrow: &BorrowData<'tcx>) {
|
||||||
self.tcx.cannot_move_when_borrowed(span,
|
self.tcx.cannot_move_when_borrowed(span,
|
||||||
&self.describe_lvalue(lvalue),
|
&self.describe_lvalue(lvalue),
|
||||||
Origin::Mir)
|
Origin::Mir)
|
||||||
|
@ -1305,8 +1305,8 @@ impl<'c, 'b, 'a: 'b+'c, 'gcx, 'tcx: 'a> MirBorrowckCtxt<'c, 'b, 'a, 'gcx, 'tcx>
|
||||||
|
|
||||||
fn report_use_while_mutably_borrowed(&mut self,
|
fn report_use_while_mutably_borrowed(&mut self,
|
||||||
_context: Context,
|
_context: Context,
|
||||||
(lvalue, span): (&Lvalue, Span),
|
(lvalue, span): (&Lvalue<'tcx>, Span),
|
||||||
borrow : &BorrowData) {
|
borrow : &BorrowData<'tcx>) {
|
||||||
|
|
||||||
let mut err = self.tcx.cannot_use_when_mutably_borrowed(
|
let mut err = self.tcx.cannot_use_when_mutably_borrowed(
|
||||||
span, &self.describe_lvalue(lvalue),
|
span, &self.describe_lvalue(lvalue),
|
||||||
|
@ -1382,8 +1382,8 @@ impl<'c, 'b, 'a: 'b+'c, 'gcx, 'tcx: 'a> MirBorrowckCtxt<'c, 'b, 'a, 'gcx, 'tcx>
|
||||||
|
|
||||||
fn report_conflicting_borrow(&mut self,
|
fn report_conflicting_borrow(&mut self,
|
||||||
context: Context,
|
context: Context,
|
||||||
common_prefix: &Lvalue,
|
common_prefix: &Lvalue<'tcx>,
|
||||||
(lvalue, span): (&Lvalue, Span),
|
(lvalue, span): (&Lvalue<'tcx>, Span),
|
||||||
gen_borrow_kind: BorrowKind,
|
gen_borrow_kind: BorrowKind,
|
||||||
issued_borrow: &BorrowData,
|
issued_borrow: &BorrowData,
|
||||||
end_issued_loan_span: Option<Span>) {
|
end_issued_loan_span: Option<Span>) {
|
||||||
|
@ -1453,7 +1453,7 @@ impl<'c, 'b, 'a: 'b+'c, 'gcx, 'tcx: 'a> MirBorrowckCtxt<'c, 'b, 'a, 'gcx, 'tcx>
|
||||||
|
|
||||||
fn report_illegal_mutation_of_borrowed(&mut self,
|
fn report_illegal_mutation_of_borrowed(&mut self,
|
||||||
_: Context,
|
_: Context,
|
||||||
(lvalue, span): (&Lvalue, Span),
|
(lvalue, span): (&Lvalue<'tcx>, Span),
|
||||||
loan: &BorrowData) {
|
loan: &BorrowData) {
|
||||||
let mut err = self.tcx.cannot_assign_to_borrowed(
|
let mut err = self.tcx.cannot_assign_to_borrowed(
|
||||||
span, self.retrieve_borrow_span(loan), &self.describe_lvalue(lvalue), Origin::Mir);
|
span, self.retrieve_borrow_span(loan), &self.describe_lvalue(lvalue), Origin::Mir);
|
||||||
|
@ -1463,7 +1463,7 @@ impl<'c, 'b, 'a: 'b+'c, 'gcx, 'tcx: 'a> MirBorrowckCtxt<'c, 'b, 'a, 'gcx, 'tcx>
|
||||||
|
|
||||||
fn report_illegal_reassignment(&mut self,
|
fn report_illegal_reassignment(&mut self,
|
||||||
_context: Context,
|
_context: Context,
|
||||||
(lvalue, span): (&Lvalue, Span),
|
(lvalue, span): (&Lvalue<'tcx>, Span),
|
||||||
assigned_span: Span) {
|
assigned_span: Span) {
|
||||||
self.tcx.cannot_reassign_immutable(span,
|
self.tcx.cannot_reassign_immutable(span,
|
||||||
&self.describe_lvalue(lvalue),
|
&self.describe_lvalue(lvalue),
|
||||||
|
@ -1474,7 +1474,9 @@ impl<'c, 'b, 'a: 'b+'c, 'gcx, 'tcx: 'a> MirBorrowckCtxt<'c, 'b, 'a, 'gcx, 'tcx>
|
||||||
.emit();
|
.emit();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn report_assignment_to_static(&mut self, _context: Context, (lvalue, span): (&Lvalue, Span)) {
|
fn report_assignment_to_static(&mut self,
|
||||||
|
_context: Context,
|
||||||
|
(lvalue, span): (&Lvalue<'tcx>, Span)) {
|
||||||
let mut err = self.tcx.cannot_assign_static(
|
let mut err = self.tcx.cannot_assign_static(
|
||||||
span, &self.describe_lvalue(lvalue), Origin::Mir);
|
span, &self.describe_lvalue(lvalue), Origin::Mir);
|
||||||
err.emit();
|
err.emit();
|
||||||
|
@ -1483,14 +1485,17 @@ impl<'c, 'b, 'a: 'b+'c, 'gcx, 'tcx: 'a> MirBorrowckCtxt<'c, 'b, 'a, 'gcx, 'tcx>
|
||||||
|
|
||||||
impl<'c, 'b, 'a: 'b+'c, 'gcx, 'tcx: 'a> MirBorrowckCtxt<'c, 'b, 'a, 'gcx, 'tcx> {
|
impl<'c, 'b, 'a: 'b+'c, 'gcx, 'tcx: 'a> MirBorrowckCtxt<'c, 'b, 'a, 'gcx, 'tcx> {
|
||||||
// End-user visible description of `lvalue`
|
// End-user visible description of `lvalue`
|
||||||
fn describe_lvalue(&self, lvalue: &Lvalue) -> String {
|
fn describe_lvalue(&self, lvalue: &Lvalue<'tcx>) -> String {
|
||||||
let mut buf = String::new();
|
let mut buf = String::new();
|
||||||
self.append_lvalue_to_string(lvalue, &mut buf, None);
|
self.append_lvalue_to_string(lvalue, &mut buf, None);
|
||||||
buf
|
buf
|
||||||
}
|
}
|
||||||
|
|
||||||
// Appends end-user visible description of `lvalue` to `buf`.
|
// Appends end-user visible description of `lvalue` to `buf`.
|
||||||
fn append_lvalue_to_string(&self, lvalue: &Lvalue, buf: &mut String, autoderef: Option<bool>) {
|
fn append_lvalue_to_string(&self,
|
||||||
|
lvalue: &Lvalue<'tcx>,
|
||||||
|
buf: &mut String,
|
||||||
|
autoderef: Option<bool>) {
|
||||||
match *lvalue {
|
match *lvalue {
|
||||||
Lvalue::Local(local) => {
|
Lvalue::Local(local) => {
|
||||||
self.append_local_to_string(local, buf, "_");
|
self.append_local_to_string(local, buf, "_");
|
||||||
|
@ -1500,41 +1505,50 @@ impl<'c, 'b, 'a: 'b+'c, 'gcx, 'tcx: 'a> MirBorrowckCtxt<'c, 'b, 'a, 'gcx, 'tcx>
|
||||||
}
|
}
|
||||||
Lvalue::Projection(ref proj) => {
|
Lvalue::Projection(ref proj) => {
|
||||||
let mut autoderef = autoderef.unwrap_or(false);
|
let mut autoderef = autoderef.unwrap_or(false);
|
||||||
let (prefix, suffix, index_operand) = match proj.elem {
|
|
||||||
|
match proj.elem {
|
||||||
ProjectionElem::Deref => {
|
ProjectionElem::Deref => {
|
||||||
if autoderef {
|
if autoderef {
|
||||||
("", format!(""), None)
|
self.append_lvalue_to_string(&proj.base, buf, Some(autoderef));
|
||||||
} else {
|
} else {
|
||||||
("(*", format!(")"), None)
|
buf.push_str(&"(*");
|
||||||
|
self.append_lvalue_to_string(&proj.base, buf, Some(autoderef));
|
||||||
|
buf.push_str(&")");
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
ProjectionElem::Downcast(..) =>
|
ProjectionElem::Downcast(..) => {
|
||||||
("", format!(""), None), // (dont emit downcast info)
|
self.append_lvalue_to_string(&proj.base, buf, Some(autoderef));
|
||||||
|
},
|
||||||
ProjectionElem::Field(field, _ty) => {
|
ProjectionElem::Field(field, _ty) => {
|
||||||
autoderef = true;
|
autoderef = true;
|
||||||
("", format!(".{}", self.describe_field(&proj.base, field.index())), None)
|
let is_projection_from_ty_closure = proj.base.ty(self.mir, self.tcx)
|
||||||
|
.to_ty(self.tcx).is_closure();
|
||||||
|
|
||||||
|
let field_name = self.describe_field(&proj.base, field.index());
|
||||||
|
if is_projection_from_ty_closure {
|
||||||
|
buf.push_str(&format!("{}", field_name));
|
||||||
|
} else {
|
||||||
|
self.append_lvalue_to_string(&proj.base, buf, Some(autoderef));
|
||||||
|
buf.push_str(&format!(".{}", field_name));
|
||||||
|
}
|
||||||
},
|
},
|
||||||
ProjectionElem::Index(index) => {
|
ProjectionElem::Index(index) => {
|
||||||
autoderef = true;
|
autoderef = true;
|
||||||
("", format!(""), Some(index))
|
|
||||||
|
self.append_lvalue_to_string(&proj.base, buf, Some(autoderef));
|
||||||
|
buf.push_str("[");
|
||||||
|
self.append_local_to_string(index, buf, "..");
|
||||||
|
buf.push_str("]");
|
||||||
},
|
},
|
||||||
ProjectionElem::ConstantIndex { .. } | ProjectionElem::Subslice { .. } => {
|
ProjectionElem::ConstantIndex { .. } | ProjectionElem::Subslice { .. } => {
|
||||||
autoderef = true;
|
autoderef = true;
|
||||||
// Since it isn't possible to borrow an element on a particular index and
|
// Since it isn't possible to borrow an element on a particular index and
|
||||||
// then use another while the borrow is held, don't output indices details
|
// then use another while the borrow is held, don't output indices details
|
||||||
// to avoid confusing the end-user
|
// to avoid confusing the end-user
|
||||||
("", format!("[..]"), None)
|
self.append_lvalue_to_string(&proj.base, buf, Some(autoderef));
|
||||||
|
buf.push_str(&"[..]");
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
buf.push_str(prefix);
|
|
||||||
self.append_lvalue_to_string(&proj.base, buf, Some(autoderef));
|
|
||||||
if let Some(index) = index_operand {
|
|
||||||
buf.push_str("[");
|
|
||||||
self.append_local_to_string(index, buf, "..");
|
|
||||||
buf.push_str("]");
|
|
||||||
} else {
|
|
||||||
buf.push_str(&suffix);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1549,6 +1563,7 @@ impl<'c, 'b, 'a: 'b+'c, 'gcx, 'tcx: 'a> MirBorrowckCtxt<'c, 'b, 'a, 'gcx, 'tcx>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FIXME Instead of passing usize, Field should be passed
|
||||||
// End-user visible description of the `field_index`nth field of `base`
|
// End-user visible description of the `field_index`nth field of `base`
|
||||||
fn describe_field(&self, base: &Lvalue, field_index: usize) -> String {
|
fn describe_field(&self, base: &Lvalue, field_index: usize) -> String {
|
||||||
match *base {
|
match *base {
|
||||||
|
@ -1600,6 +1615,16 @@ impl<'c, 'b, 'a: 'b+'c, 'gcx, 'tcx: 'a> MirBorrowckCtxt<'c, 'b, 'a, 'gcx, 'tcx>
|
||||||
},
|
},
|
||||||
ty::TyArray(ty, _) | ty::TySlice(ty) => {
|
ty::TyArray(ty, _) | ty::TySlice(ty) => {
|
||||||
self.describe_field_from_ty(&ty, field_index)
|
self.describe_field_from_ty(&ty, field_index)
|
||||||
|
},
|
||||||
|
ty::TyClosure(closure_def_id, _) => {
|
||||||
|
// Convert the def-id into a node-id. node-ids are only valid for
|
||||||
|
// the local code in the current crate, so this returns an `Option` in case
|
||||||
|
// the closure comes from another crate. But in that case we wouldn't
|
||||||
|
// be borrowck'ing it, so we can just unwrap:
|
||||||
|
let node_id = self.tcx.hir.as_local_node_id(closure_def_id).unwrap();
|
||||||
|
let freevar = self.tcx.with_freevars(node_id, |fv| fv[field_index]);
|
||||||
|
|
||||||
|
self.tcx.hir.name(freevar.var_id()).to_string()
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
// Might need a revision when the fields in trait RFC is implemented
|
// Might need a revision when the fields in trait RFC is implemented
|
||||||
|
|
|
@ -327,4 +327,28 @@ fn main() {
|
||||||
_ => panic!("other case")
|
_ => panic!("other case")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// Field from upvar
|
||||||
|
{
|
||||||
|
let mut x = 0;
|
||||||
|
|| {
|
||||||
|
let y = &mut x;
|
||||||
|
&mut x; //[ast]~ ERROR cannot borrow `**x` as mutable more than once at a time
|
||||||
|
//[mir]~^ ERROR cannot borrow `**x` as mutable more than once at a time (Ast)
|
||||||
|
//[mir]~| ERROR cannot borrow `(*x)` as mutable more than once at a time (Mir)
|
||||||
|
*y = 1;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
// Field from upvar nested
|
||||||
|
{
|
||||||
|
let mut x = 0;
|
||||||
|
|| {
|
||||||
|
|| {
|
||||||
|
let y = &mut x;
|
||||||
|
&mut x; //[ast]~ ERROR cannot borrow `**x` as mutable more than once at a time
|
||||||
|
//[mir]~^ ERROR cannot borrow `**x` as mutable more than once at a time (Ast)
|
||||||
|
//[mir]~| ERROR cannot borrow `(*x)` as mutable more than once at a time (Mir)
|
||||||
|
*y = 1;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue