Skip to content

Commit 16156fb

Browse files
committed
Auto merge of rust-lang#83674 - Dylan-DPC:rollup-bcuc1hl, r=Dylan-DPC
Rollup of 7 pull requests Successful merges: - rust-lang#83568 (update comment at MaybeUninit::uninit_array) - rust-lang#83571 (Constantify some slice methods) - rust-lang#83579 (Improve pointer arithmetic docs) - rust-lang#83645 (Wrap non-pre code blocks) - rust-lang#83656 (Add a regression test for issue-82865) - rust-lang#83662 (Update books) - rust-lang#83667 (Suggest box/pin/arc ing receiver on method calls) Failed merges: r? `@ghost` `@rustbot` modify labels: rollup
2 parents 689e847 + 5b46778 commit 16156fb

33 files changed

+287
-233
lines changed

compiler/rustc_typeck/src/check/expr.rs

+16-57
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ use crate::astconv::AstConv as _;
66
use crate::check::cast;
77
use crate::check::coercion::CoerceMany;
88
use crate::check::fatally_break_rust;
9-
use crate::check::method::{probe, MethodError, SelfSource};
9+
use crate::check::method::SelfSource;
1010
use crate::check::report_unexpected_variant_res;
1111
use crate::check::BreakableCtxt;
1212
use crate::check::Diverges;
@@ -30,7 +30,6 @@ use rustc_errors::{pluralize, struct_span_err, Applicability, DiagnosticBuilder,
3030
use rustc_hir as hir;
3131
use rustc_hir::def::{CtorKind, DefKind, Res};
3232
use rustc_hir::def_id::DefId;
33-
use rustc_hir::lang_items::LangItem;
3433
use rustc_hir::{ExprKind, QPath};
3534
use rustc_infer::infer;
3635
use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
@@ -461,7 +460,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
461460
self.resolve_lang_item_path(lang_item, expr.span, expr.hir_id).1
462461
}
463462

464-
fn check_expr_path(&self, qpath: &hir::QPath<'_>, expr: &'tcx hir::Expr<'tcx>) -> Ty<'tcx> {
463+
fn check_expr_path(
464+
&self,
465+
qpath: &'tcx hir::QPath<'tcx>,
466+
expr: &'tcx hir::Expr<'tcx>,
467+
) -> Ty<'tcx> {
465468
let tcx = self.tcx;
466469
let (res, opt_ty, segs) = self.resolve_ty_and_res_ufcs(qpath, expr.hir_id, expr.span);
467470
let ty = match res {
@@ -947,7 +950,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
947950
}
948951
Err(error) => {
949952
if segment.ident.name != kw::Empty {
950-
self.report_extended_method_error(segment, span, args, rcvr_t, error);
953+
if let Some(mut err) = self.report_method_error(
954+
span,
955+
rcvr_t,
956+
segment.ident,
957+
SelfSource::MethodCall(&args[0]),
958+
error,
959+
Some(args),
960+
) {
961+
err.emit();
962+
}
951963
}
952964
Err(())
953965
}
@@ -964,59 +976,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
964976
)
965977
}
966978

967-
fn report_extended_method_error(
968-
&self,
969-
segment: &hir::PathSegment<'_>,
970-
span: Span,
971-
args: &'tcx [hir::Expr<'tcx>],
972-
rcvr_t: Ty<'tcx>,
973-
error: MethodError<'tcx>,
974-
) {
975-
let rcvr = &args[0];
976-
let try_alt_rcvr = |err: &mut DiagnosticBuilder<'_>, new_rcvr_t| {
977-
if let Some(new_rcvr_t) = new_rcvr_t {
978-
if let Ok(pick) = self.lookup_probe(
979-
span,
980-
segment.ident,
981-
new_rcvr_t,
982-
rcvr,
983-
probe::ProbeScope::AllTraits,
984-
) {
985-
debug!("try_alt_rcvr: pick candidate {:?}", pick);
986-
// Make sure the method is defined for the *actual* receiver:
987-
// we don't want to treat `Box<Self>` as a receiver if
988-
// it only works because of an autoderef to `&self`
989-
if pick.autoderefs == 0 {
990-
err.span_label(
991-
pick.item.ident.span,
992-
&format!("the method is available for `{}` here", new_rcvr_t),
993-
);
994-
}
995-
}
996-
}
997-
};
998-
999-
if let Some(mut err) = self.report_method_error(
1000-
span,
1001-
rcvr_t,
1002-
segment.ident,
1003-
SelfSource::MethodCall(rcvr),
1004-
error,
1005-
Some(args),
1006-
) {
1007-
if let ty::Adt(..) = rcvr_t.kind() {
1008-
// Try alternative arbitrary self types that could fulfill this call.
1009-
// FIXME: probe for all types that *could* be arbitrary self-types, not
1010-
// just this list.
1011-
try_alt_rcvr(&mut err, self.tcx.mk_lang_item(rcvr_t, LangItem::OwnedBox));
1012-
try_alt_rcvr(&mut err, self.tcx.mk_lang_item(rcvr_t, LangItem::Pin));
1013-
try_alt_rcvr(&mut err, self.tcx.mk_diagnostic_item(rcvr_t, sym::Arc));
1014-
try_alt_rcvr(&mut err, self.tcx.mk_diagnostic_item(rcvr_t, sym::Rc));
1015-
}
1016-
err.emit();
1017-
}
1018-
}
1019-
1020979
fn check_expr_cast(
1021980
&self,
1022981
e: &'tcx hir::Expr<'tcx>,

compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -905,12 +905,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
905905

906906
/// Resolves an associated value path into a base type and associated constant, or method
907907
/// resolution. The newly resolved definition is written into `type_dependent_defs`.
908-
pub fn resolve_ty_and_res_ufcs<'b>(
908+
pub fn resolve_ty_and_res_ufcs(
909909
&self,
910-
qpath: &'b QPath<'b>,
910+
qpath: &'tcx QPath<'tcx>,
911911
hir_id: hir::HirId,
912912
span: Span,
913-
) -> (Res, Option<Ty<'tcx>>, &'b [hir::PathSegment<'b>]) {
913+
) -> (Res, Option<Ty<'tcx>>, &'tcx [hir::PathSegment<'tcx>]) {
914914
debug!("resolve_ty_and_res_ufcs: qpath={:?} hir_id={:?} span={:?}", qpath, hir_id, span);
915915
let (ty, qself, item_segment) = match *qpath {
916916
QPath::Resolved(ref opt_qself, ref path) => {

compiler/rustc_typeck/src/check/method/mod.rs

+2
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ pub struct MethodCallee<'tcx> {
4545
pub sig: ty::FnSig<'tcx>,
4646
}
4747

48+
#[derive(Debug)]
4849
pub enum MethodError<'tcx> {
4950
// Did not find an applicable method, but we did find various near-misses that may work.
5051
NoMatch(NoMatchData<'tcx>),
@@ -66,6 +67,7 @@ pub enum MethodError<'tcx> {
6667

6768
// Contains a list of static methods that may apply, a list of unsatisfied trait predicates which
6869
// could lead to matches if satisfied, and a list of not-in-scope traits which may work.
70+
#[derive(Debug)]
6971
pub struct NoMatchData<'tcx> {
7072
pub static_candidates: Vec<CandidateSource>,
7173
pub unsatisfied_predicates: Vec<(ty::Predicate<'tcx>, Option<ty::Predicate<'tcx>>)>,

compiler/rustc_typeck/src/check/method/suggest.rs

+78-9
Original file line numberDiff line numberDiff line change
@@ -68,12 +68,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
6868
}
6969
}
7070

71-
pub fn report_method_error<'b>(
71+
pub fn report_method_error(
7272
&self,
7373
span: Span,
7474
rcvr_ty: Ty<'tcx>,
7575
item_name: Ident,
76-
source: SelfSource<'b>,
76+
source: SelfSource<'tcx>,
7777
error: MethodError<'tcx>,
7878
args: Option<&'tcx [hir::Expr<'tcx>]>,
7979
) -> Option<DiagnosticBuilder<'_>> {
@@ -323,8 +323,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
323323
err.span_suggestion(
324324
lit.span,
325325
&format!(
326-
"you must specify a concrete type for \
327-
this numeric value, like `{}`",
326+
"you must specify a concrete type for this numeric value, \
327+
like `{}`",
328328
concrete_type
329329
),
330330
format!("{}_{}", snippet, concrete_type),
@@ -975,17 +975,78 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
975975
}
976976
}
977977

978-
fn suggest_traits_to_import<'b>(
978+
fn suggest_traits_to_import(
979979
&self,
980980
err: &mut DiagnosticBuilder<'_>,
981981
span: Span,
982982
rcvr_ty: Ty<'tcx>,
983983
item_name: Ident,
984-
source: SelfSource<'b>,
984+
source: SelfSource<'tcx>,
985985
valid_out_of_scope_traits: Vec<DefId>,
986986
unsatisfied_predicates: &[(ty::Predicate<'tcx>, Option<ty::Predicate<'tcx>>)],
987987
) {
988-
if self.suggest_valid_traits(err, valid_out_of_scope_traits) {
988+
let mut alt_rcvr_sugg = false;
989+
if let SelfSource::MethodCall(rcvr) = source {
990+
info!(?span, ?item_name, ?rcvr_ty, ?rcvr);
991+
if let ty::Adt(..) = rcvr_ty.kind() {
992+
// Try alternative arbitrary self types that could fulfill this call.
993+
// FIXME: probe for all types that *could* be arbitrary self-types, not
994+
// just this list.
995+
for (rcvr_ty, post) in &[
996+
(rcvr_ty, ""),
997+
(self.tcx.mk_mut_ref(&ty::ReErased, rcvr_ty), "&mut "),
998+
(self.tcx.mk_imm_ref(&ty::ReErased, rcvr_ty), "&"),
999+
] {
1000+
for (rcvr_ty, pre) in &[
1001+
(self.tcx.mk_lang_item(rcvr_ty, LangItem::OwnedBox), "Box::new"),
1002+
(self.tcx.mk_lang_item(rcvr_ty, LangItem::Pin), "Pin::new"),
1003+
(self.tcx.mk_diagnostic_item(rcvr_ty, sym::Arc), "Arc::new"),
1004+
(self.tcx.mk_diagnostic_item(rcvr_ty, sym::Rc), "Rc::new"),
1005+
] {
1006+
if let Some(new_rcvr_t) = *rcvr_ty {
1007+
if let Ok(pick) = self.lookup_probe(
1008+
span,
1009+
item_name,
1010+
new_rcvr_t,
1011+
rcvr,
1012+
crate::check::method::probe::ProbeScope::AllTraits,
1013+
) {
1014+
debug!("try_alt_rcvr: pick candidate {:?}", pick);
1015+
// Make sure the method is defined for the *actual* receiver:
1016+
// we don't want to treat `Box<Self>` as a receiver if
1017+
// it only works because of an autoderef to `&self`
1018+
if pick.autoderefs == 0
1019+
// We don't want to suggest a container type when the missing method is
1020+
// `.clone()`, otherwise we'd suggest `Arc::new(foo).clone()`, which is
1021+
// far from what the user really wants.
1022+
&& Some(pick.item.container.id()) != self.tcx.lang_items().clone_trait()
1023+
{
1024+
err.span_label(
1025+
pick.item.ident.span,
1026+
&format!(
1027+
"the method is available for `{}` here",
1028+
new_rcvr_t
1029+
),
1030+
);
1031+
err.multipart_suggestion(
1032+
"consider wrapping the receiver expression with the \
1033+
appropriate type",
1034+
vec![
1035+
(rcvr.span.shrink_to_lo(), format!("{}({}", pre, post)),
1036+
(rcvr.span.shrink_to_hi(), ")".to_string()),
1037+
],
1038+
Applicability::MaybeIncorrect,
1039+
);
1040+
// We don't care about the other suggestions.
1041+
alt_rcvr_sugg = true;
1042+
}
1043+
}
1044+
}
1045+
}
1046+
}
1047+
}
1048+
}
1049+
if !alt_rcvr_sugg && self.suggest_valid_traits(err, valid_out_of_scope_traits) {
9891050
return;
9901051
}
9911052

@@ -1075,6 +1136,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
10751136
"the method might not be found because of this arbitrary self type",
10761137
);
10771138
}
1139+
if alt_rcvr_sugg {
1140+
return;
1141+
}
10781142

10791143
if !candidates.is_empty() {
10801144
// Sort from most relevant to least relevant.
@@ -1284,7 +1348,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
12841348

12851349
/// Checks whether there is a local type somewhere in the chain of
12861350
/// autoderefs of `rcvr_ty`.
1287-
fn type_derefs_to_local(&self, span: Span, rcvr_ty: Ty<'tcx>, source: SelfSource<'_>) -> bool {
1351+
fn type_derefs_to_local(
1352+
&self,
1353+
span: Span,
1354+
rcvr_ty: Ty<'tcx>,
1355+
source: SelfSource<'tcx>,
1356+
) -> bool {
12881357
fn is_local(ty: Ty<'_>) -> bool {
12891358
match ty.kind() {
12901359
ty::Adt(def, _) => def.did.is_local(),
@@ -1310,7 +1379,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
13101379
}
13111380
}
13121381

1313-
#[derive(Copy, Clone)]
1382+
#[derive(Copy, Clone, Debug)]
13141383
pub enum SelfSource<'a> {
13151384
QPath(&'a hir::Ty<'a>),
13161385
MethodCall(&'a hir::Expr<'a> /* rcvr */),

compiler/rustc_typeck/src/check/pat.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -861,7 +861,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
861861
fn check_pat_tuple_struct(
862862
&self,
863863
pat: &'tcx Pat<'tcx>,
864-
qpath: &hir::QPath<'_>,
864+
qpath: &'tcx hir::QPath<'tcx>,
865865
subpats: &'tcx [&'tcx Pat<'tcx>],
866866
ddpos: Option<usize>,
867867
expected: Ty<'tcx>,

library/core/src/mem/maybe_uninit.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -319,9 +319,9 @@ impl<T> MaybeUninit<T> {
319319
/// Create a new array of `MaybeUninit<T>` items, in an uninitialized state.
320320
///
321321
/// Note: in a future Rust version this method may become unnecessary
322-
/// when array literal syntax allows
323-
/// [repeating const expressions](https://github.com/rust-lang/rust/issues/49147).
324-
/// The example below could then use `let mut buf = [MaybeUninit::<u8>::uninit(); 32];`.
322+
/// when Rust allows
323+
/// [inline const expressions](https://github.com/rust-lang/rust/issues/76001).
324+
/// The example below could then use `let mut buf = [const { MaybeUninit::<u8>::uninit() }; 32];`.
325325
///
326326
/// # Examples
327327
///

0 commit comments

Comments
 (0)