Skip to content

Commit c3ddd59

Browse files
Rollup merge of #96733 - SparrowLii:place_to_string, r=davidtwco
turn `append_place_to_string` from recursion into iteration This PR fixes the FIXME in the impl of `append_place_to_string` which turns `append_place_to_string` from recursion into iteration, meanwhile simplifying the code relatively.
2 parents c7af4e6 + 8ff0189 commit c3ddd59

File tree

1 file changed

+78
-132
lines changed
  • compiler/rustc_borrowck/src/diagnostics

1 file changed

+78
-132
lines changed

compiler/rustc_borrowck/src/diagnostics/mod.rs

+78-132
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
//! Borrow checker diagnostics.
22
3+
use itertools::Itertools;
34
use rustc_const_eval::util::{call_kind, CallDesugaringKind};
45
use rustc_errors::{Applicability, Diagnostic};
56
use rustc_hir as hir;
@@ -161,158 +162,103 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
161162
}
162163

163164
/// End-user visible description of `place` if one can be found.
164-
/// If the place is a temporary for instance, None will be returned.
165+
/// If the place is a temporary for instance, `None` will be returned.
165166
pub(super) fn describe_place(&self, place_ref: PlaceRef<'tcx>) -> Option<String> {
166167
self.describe_place_with_options(place_ref, IncludingDowncast(false))
167168
}
168169

169-
/// End-user visible description of `place` if one can be found. If the
170-
/// place is a temporary for instance, None will be returned.
171-
/// `IncludingDowncast` parameter makes the function return `Err` if `ProjectionElem` is
170+
/// End-user visible description of `place` if one can be found. If the place is a temporary
171+
/// for instance, `None` will be returned.
172+
/// `IncludingDowncast` parameter makes the function return `None` if `ProjectionElem` is
172173
/// `Downcast` and `IncludingDowncast` is true
173174
pub(super) fn describe_place_with_options(
174175
&self,
175176
place: PlaceRef<'tcx>,
176177
including_downcast: IncludingDowncast,
177178
) -> Option<String> {
179+
let local = place.local;
180+
let mut autoderef_index = None;
178181
let mut buf = String::new();
179-
match self.append_place_to_string(place, &mut buf, false, &including_downcast) {
180-
Ok(()) => Some(buf),
181-
Err(()) => None,
182-
}
183-
}
184-
185-
/// Appends end-user visible description of `place` to `buf`.
186-
fn append_place_to_string(
187-
&self,
188-
place: PlaceRef<'tcx>,
189-
buf: &mut String,
190-
mut autoderef: bool,
191-
including_downcast: &IncludingDowncast,
192-
) -> Result<(), ()> {
193-
match place {
194-
PlaceRef { local, projection: [] } => {
195-
self.append_local_to_string(local, buf)?;
196-
}
197-
PlaceRef { local, projection: [ProjectionElem::Deref] }
198-
if self.body.local_decls[local].is_ref_for_guard() =>
199-
{
200-
self.append_place_to_string(
201-
PlaceRef { local, projection: &[] },
202-
buf,
203-
autoderef,
204-
&including_downcast,
205-
)?;
206-
}
207-
PlaceRef { local, projection: [ProjectionElem::Deref] }
208-
if self.body.local_decls[local].is_ref_to_static() =>
209-
{
210-
let local_info = &self.body.local_decls[local].local_info;
211-
if let Some(box LocalInfo::StaticRef { def_id, .. }) = *local_info {
212-
buf.push_str(self.infcx.tcx.item_name(def_id).as_str());
213-
} else {
214-
unreachable!();
215-
}
216-
}
217-
PlaceRef { local, projection: [proj_base @ .., elem] } => {
218-
match elem {
219-
ProjectionElem::Deref => {
220-
let upvar_field_projection = self.is_upvar_field_projection(place);
221-
if let Some(field) = upvar_field_projection {
222-
let var_index = field.index();
223-
let name = self.upvars[var_index].place.to_string(self.infcx.tcx);
224-
if self.upvars[var_index].by_ref {
225-
buf.push_str(&name);
226-
} else {
227-
buf.push('*');
228-
buf.push_str(&name);
229-
}
230-
} else {
231-
if autoderef {
232-
// FIXME turn this recursion into iteration
233-
self.append_place_to_string(
234-
PlaceRef { local, projection: proj_base },
235-
buf,
236-
autoderef,
237-
&including_downcast,
238-
)?;
239-
} else {
240-
buf.push('*');
241-
self.append_place_to_string(
242-
PlaceRef { local, projection: proj_base },
243-
buf,
244-
autoderef,
245-
&including_downcast,
246-
)?;
247-
}
182+
let mut ok = self.append_local_to_string(local, &mut buf);
183+
184+
for (index, elem) in place.projection.into_iter().enumerate() {
185+
match elem {
186+
ProjectionElem::Deref => {
187+
if index == 0 {
188+
if self.body.local_decls[local].is_ref_for_guard() {
189+
continue;
248190
}
249-
}
250-
ProjectionElem::Downcast(..) => {
251-
self.append_place_to_string(
252-
PlaceRef { local, projection: proj_base },
253-
buf,
254-
autoderef,
255-
&including_downcast,
256-
)?;
257-
if including_downcast.0 {
258-
return Err(());
191+
if let Some(box LocalInfo::StaticRef { def_id, .. }) =
192+
&self.body.local_decls[local].local_info
193+
{
194+
buf.push_str(self.infcx.tcx.item_name(*def_id).as_str());
195+
ok = Ok(());
196+
continue;
259197
}
260198
}
261-
ProjectionElem::Field(field, _ty) => {
262-
autoderef = true;
263-
264-
// FIXME(project-rfc_2229#36): print capture precisely here.
265-
let upvar_field_projection = self.is_upvar_field_projection(place);
266-
if let Some(field) = upvar_field_projection {
267-
let var_index = field.index();
268-
let name = self.upvars[var_index].place.to_string(self.infcx.tcx);
269-
buf.push_str(&name);
270-
} else {
271-
let field_name = self
272-
.describe_field(PlaceRef { local, projection: proj_base }, *field);
273-
self.append_place_to_string(
274-
PlaceRef { local, projection: proj_base },
275-
buf,
276-
autoderef,
277-
&including_downcast,
278-
)?;
279-
buf.push('.');
280-
buf.push_str(&field_name);
199+
if let Some(field) = self.is_upvar_field_projection(PlaceRef {
200+
local,
201+
projection: place.projection.split_at(index + 1).0,
202+
}) {
203+
let var_index = field.index();
204+
buf = self.upvars[var_index].place.to_string(self.infcx.tcx);
205+
ok = Ok(());
206+
if !self.upvars[var_index].by_ref {
207+
buf.insert(0, '*');
281208
}
282-
}
283-
ProjectionElem::Index(index) => {
284-
autoderef = true;
285-
286-
self.append_place_to_string(
287-
PlaceRef { local, projection: proj_base },
288-
buf,
289-
autoderef,
290-
&including_downcast,
291-
)?;
292-
buf.push('[');
293-
if self.append_local_to_string(*index, buf).is_err() {
294-
buf.push('_');
209+
} else {
210+
if autoderef_index.is_none() {
211+
autoderef_index =
212+
match place.projection.into_iter().rev().find_position(|elem| {
213+
!matches!(
214+
elem,
215+
ProjectionElem::Deref | ProjectionElem::Downcast(..)
216+
)
217+
}) {
218+
Some((index, _)) => Some(place.projection.len() - index),
219+
None => Some(0),
220+
};
221+
}
222+
if index >= autoderef_index.unwrap() {
223+
buf.insert(0, '*');
295224
}
296-
buf.push(']');
297225
}
298-
ProjectionElem::ConstantIndex { .. } | ProjectionElem::Subslice { .. } => {
299-
autoderef = true;
300-
// Since it isn't possible to borrow an element on a particular index and
301-
// then use another while the borrow is held, don't output indices details
302-
// to avoid confusing the end-user
303-
self.append_place_to_string(
304-
PlaceRef { local, projection: proj_base },
305-
buf,
306-
autoderef,
307-
&including_downcast,
308-
)?;
309-
buf.push_str("[..]");
226+
}
227+
ProjectionElem::Downcast(..) if including_downcast.0 => return None,
228+
ProjectionElem::Downcast(..) => (),
229+
ProjectionElem::Field(field, _ty) => {
230+
// FIXME(project-rfc_2229#36): print capture precisely here.
231+
if let Some(field) = self.is_upvar_field_projection(PlaceRef {
232+
local,
233+
projection: place.projection.split_at(index + 1).0,
234+
}) {
235+
buf = self.upvars[field.index()].place.to_string(self.infcx.tcx);
236+
ok = Ok(());
237+
} else {
238+
let field_name = self.describe_field(
239+
PlaceRef { local, projection: place.projection.split_at(index).0 },
240+
*field,
241+
);
242+
buf.push('.');
243+
buf.push_str(&field_name);
310244
}
311-
};
245+
}
246+
ProjectionElem::Index(index) => {
247+
buf.push('[');
248+
if self.append_local_to_string(*index, &mut buf).is_err() {
249+
buf.push('_');
250+
}
251+
buf.push(']');
252+
}
253+
ProjectionElem::ConstantIndex { .. } | ProjectionElem::Subslice { .. } => {
254+
// Since it isn't possible to borrow an element on a particular index and
255+
// then use another while the borrow is held, don't output indices details
256+
// to avoid confusing the end-user
257+
buf.push_str("[..]");
258+
}
312259
}
313260
}
314-
315-
Ok(())
261+
ok.ok().map(|_| buf)
316262
}
317263

318264
/// Appends end-user visible description of the `local` place to `buf`. If `local` doesn't have

0 commit comments

Comments
 (0)