Skip to content

Commit aa78919

Browse files
committed
mir-borrowck: print values in error messages in the same way that the AST borrowck
- Print fields with `.name` rather than `.<num>` - Autoderef values if followed by a field or an index
1 parent a8feaee commit aa78919

File tree

1 file changed

+91
-10
lines changed

1 file changed

+91
-10
lines changed

src/librustc_mir/borrow_check.rs

Lines changed: 91 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1053,12 +1053,12 @@ impl<'c, 'b, 'a: 'b+'c, 'gcx, 'tcx: 'a> MirBorrowckCtxt<'c, 'b, 'a, 'gcx, 'tcx>
10531053
// End-user visible description of `lvalue`
10541054
fn describe_lvalue(&self, lvalue: &Lvalue) -> String {
10551055
let mut buf = String::new();
1056-
self.append_lvalue_to_string(lvalue, &mut buf);
1056+
self.append_lvalue_to_string(lvalue, &mut buf, None);
10571057
buf
10581058
}
10591059

10601060
// Appends end-user visible description of `lvalue` to `buf`.
1061-
fn append_lvalue_to_string(&self, lvalue: &Lvalue, buf: &mut String) {
1061+
fn append_lvalue_to_string(&self, lvalue: &Lvalue, buf: &mut String, autoderef: Option<bool>) {
10621062
match *lvalue {
10631063
Lvalue::Local(local) => {
10641064
let local = &self.mir.local_decls[local];
@@ -1071,15 +1071,25 @@ impl<'c, 'b, 'a: 'b+'c, 'gcx, 'tcx: 'a> MirBorrowckCtxt<'c, 'b, 'a, 'gcx, 'tcx>
10711071
buf.push_str(&format!("{}", &self.tcx.item_name(static_.def_id)));
10721072
}
10731073
Lvalue::Projection(ref proj) => {
1074+
let mut autoderef = autoderef.unwrap_or(false);
10741075
let (prefix, suffix, index_operand) = match proj.elem {
1075-
ProjectionElem::Deref =>
1076-
("(*", format!(")"), None),
1076+
ProjectionElem::Deref => {
1077+
if autoderef {
1078+
("", format!(""), None)
1079+
} else {
1080+
("(*", format!(")"), None)
1081+
}
1082+
},
10771083
ProjectionElem::Downcast(..) =>
10781084
("", format!(""), None), // (dont emit downcast info)
1079-
ProjectionElem::Field(field, _ty) =>
1080-
("", format!(".{}", field.index()), None), // FIXME: report name of field
1081-
ProjectionElem::Index(index) =>
1082-
("", format!(""), Some(index)),
1085+
ProjectionElem::Field(field, _ty) => {
1086+
autoderef = true;
1087+
("", format!(".{}", self.describe_field(&proj.base, field.index())), None)
1088+
},
1089+
ProjectionElem::Index(index) => {
1090+
autoderef = true;
1091+
("", format!(""), Some(index))
1092+
},
10831093
ProjectionElem::ConstantIndex { offset, min_length, from_end: true } =>
10841094
("", format!("[{} of {}]", offset, min_length), None),
10851095
ProjectionElem::ConstantIndex { offset, min_length, from_end: false } =>
@@ -1092,10 +1102,10 @@ impl<'c, 'b, 'a: 'b+'c, 'gcx, 'tcx: 'a> MirBorrowckCtxt<'c, 'b, 'a, 'gcx, 'tcx>
10921102
("", format!("[{}:-{}]", from, to), None),
10931103
};
10941104
buf.push_str(prefix);
1095-
self.append_lvalue_to_string(&proj.base, buf);
1105+
self.append_lvalue_to_string(&proj.base, buf, Some(autoderef));
10961106
if let Some(index) = index_operand {
10971107
buf.push_str("[");
1098-
self.append_lvalue_to_string(&Lvalue::Local(index), buf);
1108+
self.append_lvalue_to_string(&Lvalue::Local(index), buf, None);
10991109
buf.push_str("]");
11001110
} else {
11011111
buf.push_str(&suffix);
@@ -1104,6 +1114,77 @@ impl<'c, 'b, 'a: 'b+'c, 'gcx, 'tcx: 'a> MirBorrowckCtxt<'c, 'b, 'a, 'gcx, 'tcx>
11041114
}
11051115
}
11061116

1117+
// End-user visible description of the `field_index`nth field of `base`
1118+
fn describe_field(&self, base: &Lvalue, field_index: usize) -> String {
1119+
match *base {
1120+
Lvalue::Local(local) => {
1121+
let local = &self.mir.local_decls[local];
1122+
self.describe_field_from_ty(&local.ty, field_index)
1123+
},
1124+
Lvalue::Static(ref static_) => {
1125+
self.describe_field_from_ty(&static_.ty, field_index)
1126+
},
1127+
Lvalue::Projection(ref proj) => {
1128+
match proj.elem {
1129+
ProjectionElem::Deref =>
1130+
self.describe_field(&proj.base, field_index),
1131+
ProjectionElem::Downcast(..) => {
1132+
debug!("End-user description not implemented for field of projection {:?}",
1133+
proj);
1134+
format!("<downcast>{}", field_index)
1135+
},
1136+
ProjectionElem::Field(..) => {
1137+
debug!("End-user description not implemented for field of projection {:?}",
1138+
proj);
1139+
format!("<field>{}", field_index)
1140+
},
1141+
ProjectionElem::Index(..) => {
1142+
debug!("End-user description not implemented for field of projection {:?}",
1143+
proj);
1144+
format!("<index>{}", field_index)
1145+
},
1146+
ProjectionElem::ConstantIndex { .. } => {
1147+
debug!("End-user description not implemented for field of projection {:?}",
1148+
proj);
1149+
format!("<constant_index>{}", field_index)
1150+
},
1151+
ProjectionElem::Subslice { .. } => {
1152+
debug!("End-user description not implemented for field of projection {:?}",
1153+
proj);
1154+
format!("<subslice>{}", field_index)
1155+
}
1156+
}
1157+
}
1158+
}
1159+
}
1160+
1161+
// End-user visible description of the `field_index`nth field of `ty`
1162+
fn describe_field_from_ty(&self, ty: &ty::Ty, field_index: usize) -> String {
1163+
if ty.is_box() {
1164+
// If the type is a box, the field is described from the boxed type
1165+
self.describe_field_from_ty(&ty.boxed_ty(), field_index)
1166+
}
1167+
else {
1168+
match ty.sty {
1169+
ty::TyAdt(def, _) => {
1170+
if def.is_enum() {
1171+
format!("{}", field_index)
1172+
}
1173+
else {
1174+
format!("{}", def.struct_variant().fields[field_index].name)
1175+
}
1176+
},
1177+
ty::TyTuple(_, _) => {
1178+
format!("{}", field_index)
1179+
},
1180+
_ => {
1181+
debug!("End-user description not implemented for field of type {:?}", ty.sty);
1182+
format!("<ty>{}", field_index)
1183+
}
1184+
}
1185+
}
1186+
}
1187+
11071188
// Retrieve span of given borrow from the current MIR representation
11081189
fn retrieve_borrow_span(&self, borrow: &BorrowData) -> Span {
11091190
self.mir.basic_blocks()[borrow.location.block]

0 commit comments

Comments
 (0)