Skip to content

Commit 77652b9

Browse files
committed
Auto merge of #96785 - GuillaumeGomez:rollup-rgiwa57, r=GuillaumeGomez
Rollup of 10 pull requests Successful merges: - #96557 (Allow inline consts to reference generic params) - #96590 (rustdoc: when running a function-signature search, tweak the tab bar) - #96650 (Collect function instance used in `global_asm!` sym operand) - #96733 (turn `append_place_to_string` from recursion into iteration) - #96748 (Fixes reexports in search) - #96752 (Put the incompatible_closure_captures lint messages in alphabetical order) - #96754 (rustdoc: ensure HTML/JS side implementors don't have dups) - #96772 (Suggest fully qualified path with appropriate params) - #96776 (Fix two minor issues in hir.rs) - #96782 (a small `mirror_expr` cleanup) Failed merges: r? `@ghost` `@rustbot` modify labels: rollup
2 parents d60b4f5 + a0e2c7e commit 77652b9

38 files changed

+625
-252
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

compiler/rustc_hir/src/hir.rs

+2-5
Original file line numberDiff line numberDiff line change
@@ -1441,7 +1441,7 @@ pub enum AsyncGeneratorKind {
14411441
/// An explicit `async` block written by the user.
14421442
Block,
14431443

1444-
/// An explicit `async` block written by the user.
1444+
/// An explicit `async` closure written by the user.
14451445
Closure,
14461446

14471447
/// The `async` block generated as the body of an async function.
@@ -2078,10 +2078,7 @@ pub enum YieldSource {
20782078

20792079
impl YieldSource {
20802080
pub fn is_await(&self) -> bool {
2081-
match self {
2082-
YieldSource::Await { .. } => true,
2083-
YieldSource::Yield => false,
2084-
}
2081+
matches!(self, YieldSource::Await { .. })
20852082
}
20862083
}
20872084

compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs

+22-1
Original file line numberDiff line numberDiff line change
@@ -731,6 +731,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
731731
// | help: specify type like: `<Impl as Into<u32>>::into(foo_impl)`
732732
// |
733733
// = note: cannot satisfy `Impl: Into<_>`
734+
debug!(?segment);
734735
if !impl_candidates.is_empty() && e.span.contains(span)
735736
&& let Some(expr) = exprs.first()
736737
&& let ExprKind::Path(hir::QPath::Resolved(_, path)) = expr.kind
@@ -739,9 +740,29 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
739740
let mut eraser = TypeParamEraser(self.tcx);
740741
let candidate_len = impl_candidates.len();
741742
let mut suggestions: Vec<_> = impl_candidates.iter().map(|candidate| {
743+
let trait_item = self.tcx
744+
.associated_items(candidate.def_id)
745+
.find_by_name_and_kind(
746+
self.tcx,
747+
segment.ident,
748+
ty::AssocKind::Fn,
749+
candidate.def_id
750+
);
751+
let prefix = if let Some(trait_item) = trait_item
752+
&& let Some(trait_m) = trait_item.def_id.as_local()
753+
&& let hir::TraitItemKind::Fn(fn_, _) = &self.tcx.hir().trait_item(hir::TraitItemId { def_id: trait_m }).kind
754+
{
755+
match fn_.decl.implicit_self {
756+
hir::ImplicitSelfKind::ImmRef => "&",
757+
hir::ImplicitSelfKind::MutRef => "&mut ",
758+
_ => "",
759+
}
760+
} else {
761+
""
762+
};
742763
let candidate = candidate.super_fold_with(&mut eraser);
743764
vec![
744-
(expr.span.shrink_to_lo(), format!("{}::{}(", candidate, segment.ident)),
765+
(expr.span.shrink_to_lo(), format!("{}::{}({}", candidate, segment.ident, prefix)),
745766
if exprs.len() == 1 {
746767
(expr.span.shrink_to_hi().with_hi(e.span.hi()), ")".to_string())
747768
} else {

compiler/rustc_middle/src/ty/print/mod.rs

+4
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,10 @@ pub trait Printer<'tcx>: Sized {
136136
match key.disambiguated_data.data {
137137
// Closures' own generics are only captures, don't print them.
138138
DefPathData::ClosureExpr => {}
139+
// This covers both `DefKind::AnonConst` and `DefKind::InlineConst`.
140+
// Anon consts doesn't have their own generics, and inline consts' own
141+
// generics are their inferred types, so don't print them.
142+
DefPathData::AnonConst => {}
139143

140144
// If we have any generic arguments to print, we do that
141145
// on top of the same path, but without its own generics.

0 commit comments

Comments
 (0)