Skip to content

Commit 88a37ac

Browse files
Yeet MethodCallComponents
1 parent 4e0fb98 commit 88a37ac

File tree

5 files changed

+90
-90
lines changed

5 files changed

+90
-90
lines changed

compiler/rustc_hir_typeck/src/expr.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ use crate::errors::{
1313
YieldExprOutsideOfCoroutine,
1414
};
1515
use crate::fatally_break_rust;
16-
use crate::method::{MethodCallComponents, SelfSource};
16+
use crate::method::SelfSource;
1717
use crate::type_error_struct;
1818
use crate::Expectation::{self, ExpectCastableToType, ExpectHasType, NoExpectation};
1919
use crate::{
@@ -512,7 +512,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
512512
) -> Ty<'tcx> {
513513
let tcx = self.tcx;
514514
let (res, opt_ty, segs) =
515-
self.resolve_ty_and_res_fully_qualified_call(qpath, expr.hir_id, expr.span);
515+
self.resolve_ty_and_res_fully_qualified_call(qpath, expr.hir_id, expr.span, Some(args));
516516
let ty = match res {
517517
Res::Err => {
518518
self.suggest_assoc_method_call(segs);
@@ -1332,7 +1332,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
13321332
segment.ident,
13331333
SelfSource::MethodCall(rcvr),
13341334
error,
1335-
Some(MethodCallComponents { receiver: rcvr, args, full_expr: expr }),
1335+
Some(args),
13361336
expected,
13371337
false,
13381338
) {

compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -797,6 +797,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
797797
qpath: &'tcx QPath<'tcx>,
798798
hir_id: hir::HirId,
799799
span: Span,
800+
args: Option<&'tcx [hir::Expr<'tcx>]>,
800801
) -> (Res, Option<RawTy<'tcx>>, &'tcx [hir::PathSegment<'tcx>]) {
801802
debug!(
802803
"resolve_ty_and_res_fully_qualified_call: qpath={:?} hir_id={:?} span={:?}",
@@ -898,7 +899,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
898899
item_name,
899900
SelfSource::QPath(qself),
900901
error,
901-
None,
902+
args,
902903
Expectation::NoExpectation,
903904
trait_missing_method && span.edition().at_least_rust_2021(), // emits missing method for trait only after edition 2021
904905
) {

compiler/rustc_hir_typeck/src/method/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ mod prelude2021;
77
pub mod probe;
88
mod suggest;
99

10-
pub use self::suggest::{MethodCallComponents, SelfSource};
10+
pub use self::suggest::SelfSource;
1111
pub use self::MethodError::*;
1212

1313
use crate::errors::OpMethodGenericParams;

compiler/rustc_hir_typeck/src/method/suggest.rs

+80-81
Original file line numberDiff line numberDiff line change
@@ -50,15 +50,6 @@ use rustc_hir::intravisit::Visitor;
5050
use std::cmp::{self, Ordering};
5151
use std::iter;
5252

53-
/// After identifying that `full_expr` is a method call, we use this type to keep the expression's
54-
/// components readily available to us to point at the right place in diagnostics.
55-
#[derive(Debug, Clone, Copy)]
56-
pub struct MethodCallComponents<'tcx> {
57-
pub receiver: &'tcx hir::Expr<'tcx>,
58-
pub args: &'tcx [hir::Expr<'tcx>],
59-
pub full_expr: &'tcx hir::Expr<'tcx>,
60-
}
61-
6253
impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
6354
fn is_fn_ty(&self, ty: Ty<'tcx>, span: Span) -> bool {
6455
let tcx = self.tcx;
@@ -124,7 +115,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
124115
item_name: Ident,
125116
source: SelfSource<'tcx>,
126117
error: MethodError<'tcx>,
127-
args: Option<MethodCallComponents<'tcx>>,
118+
args: Option<&'tcx [hir::Expr<'tcx>]>,
128119
expected: Expectation<'tcx>,
129120
trait_missing_method: bool,
130121
) -> Option<DiagnosticBuilder<'_, ErrorGuaranteed>> {
@@ -167,6 +158,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
167158
self.note_candidates_on_method_error(
168159
rcvr_ty,
169160
item_name,
161+
source,
170162
args,
171163
span,
172164
&mut err,
@@ -266,23 +258,23 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
266258
fn suggest_missing_writer(
267259
&self,
268260
rcvr_ty: Ty<'tcx>,
269-
args: MethodCallComponents<'tcx>,
261+
rcvr_expr: &hir::Expr<'tcx>,
270262
) -> DiagnosticBuilder<'_, ErrorGuaranteed> {
271263
let (ty_str, _ty_file) = self.tcx.short_ty_string(rcvr_ty);
272264
let mut err = struct_span_err!(
273265
self.tcx.sess,
274-
args.receiver.span,
266+
rcvr_expr.span,
275267
E0599,
276268
"cannot write into `{}`",
277269
ty_str
278270
);
279271
err.span_note(
280-
args.receiver.span,
272+
rcvr_expr.span,
281273
"must implement `io::Write`, `fmt::Write`, or have a `write_fmt` method",
282274
);
283-
if let ExprKind::Lit(_) = args.receiver.kind {
275+
if let ExprKind::Lit(_) = rcvr_expr.kind {
284276
err.span_help(
285-
args.receiver.span.shrink_to_lo(),
277+
rcvr_expr.span.shrink_to_lo(),
286278
"a writer is needed before this format string",
287279
);
288280
};
@@ -296,7 +288,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
296288
rcvr_ty: Ty<'tcx>,
297289
item_name: Ident,
298290
source: SelfSource<'tcx>,
299-
args: Option<MethodCallComponents<'tcx>>,
291+
args: Option<&'tcx [hir::Expr<'tcx>]>,
300292
sugg_span: Span,
301293
no_match_data: &mut NoMatchData<'tcx>,
302294
expected: Expectation<'tcx>,
@@ -377,23 +369,25 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
377369
tcx.is_diagnostic_item(sym::write_macro, def_id)
378370
|| tcx.is_diagnostic_item(sym::writeln_macro, def_id)
379371
}) && item_name.name == Symbol::intern("write_fmt");
380-
let mut err = if is_write && let Some(args) = args {
381-
self.suggest_missing_writer(rcvr_ty, args)
382-
} else {
383-
tcx.sess.create_err(NoAssociatedItem {
384-
span,
385-
item_kind,
386-
item_name,
387-
ty_prefix: if trait_missing_method {
388-
// FIXME(mu001999) E0599 maybe not suitable here because it is for types
389-
Cow::from("trait")
390-
} else {
391-
rcvr_ty.prefix_string(self.tcx)
392-
},
393-
ty_str: ty_str_reported,
394-
trait_missing_method,
395-
})
396-
};
372+
let mut err =
373+
if is_write && let SelfSource::MethodCall(rcvr_expr) = source
374+
{
375+
self.suggest_missing_writer(rcvr_ty, rcvr_expr)
376+
} else {
377+
tcx.sess.create_err(NoAssociatedItem {
378+
span,
379+
item_kind,
380+
item_name,
381+
ty_prefix: if trait_missing_method {
382+
// FIXME(mu001999) E0599 maybe not suitable here because it is for types
383+
Cow::from("trait")
384+
} else {
385+
rcvr_ty.prefix_string(self.tcx)
386+
},
387+
ty_str: ty_str_reported,
388+
trait_missing_method,
389+
})
390+
};
397391
if tcx.sess.source_map().is_multiline(sugg_span) {
398392
err.span_label(sugg_span.with_hi(span.lo()), "");
399393
}
@@ -409,7 +403,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
409403
err.downgrade_to_delayed_bug();
410404
}
411405

412-
self.find_builder_fn(&mut err, rcvr_ty, source);
406+
if matches!(source, SelfSource::QPath(_)) && args.is_some() {
407+
self.find_builder_fn(&mut err, rcvr_ty);
408+
}
409+
413410
if tcx.ty_is_opaque_future(rcvr_ty) && item_name.name == sym::poll {
414411
err.help(format!(
415412
"method `poll` found on `Pin<&mut {ty_str}>`, \
@@ -523,6 +520,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
523520
self.note_candidates_on_method_error(
524521
rcvr_ty,
525522
item_name,
523+
source,
526524
args,
527525
span,
528526
&mut err,
@@ -533,6 +531,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
533531
self.note_candidates_on_method_error(
534532
rcvr_ty,
535533
item_name,
534+
source,
536535
args,
537536
span,
538537
&mut err,
@@ -976,7 +975,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
976975
unsatisfied_bounds = true;
977976
}
978977
} else if let ty::Adt(def, targs) = rcvr_ty.kind()
979-
&& let Some(args) = args
978+
&& let SelfSource::MethodCall(rcvr_expr) = source
980979
{
981980
// This is useful for methods on arbitrary self types that might have a simple
982981
// mutability difference, like calling a method on `Pin<&mut Self>` that is on
@@ -999,8 +998,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
999998
rcvr_ty,
1000999
&item_segment,
10011000
span,
1002-
args.full_expr,
1003-
args.receiver,
1001+
tcx.hir().get_parent(rcvr_expr.hir_id).expect_expr(),
1002+
rcvr_expr,
10041003
) {
10051004
err.span_note(
10061005
tcx.def_span(method.def_id),
@@ -1169,7 +1168,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
11691168
span,
11701169
rcvr_ty,
11711170
item_name,
1172-
args.map(|MethodCallComponents { args, .. }| args.len() + 1),
1171+
args.map(|args| args.len() + 1),
11731172
source,
11741173
no_match_data.out_of_scope_traits.clone(),
11751174
&unsatisfied_predicates,
@@ -1250,7 +1249,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
12501249
&self,
12511250
rcvr_ty: Ty<'tcx>,
12521251
item_name: Ident,
1253-
args: Option<MethodCallComponents<'tcx>>,
1252+
self_source: SelfSource<'tcx>,
1253+
args: Option<&'tcx [hir::Expr<'tcx>]>,
12541254
span: Span,
12551255
err: &mut Diagnostic,
12561256
sources: &mut Vec<CandidateSource>,
@@ -1339,6 +1339,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
13391339
if let Some(sugg) = print_disambiguation_help(
13401340
item_name,
13411341
args,
1342+
self_source,
13421343
err,
13431344
path,
13441345
ty,
@@ -1378,6 +1379,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
13781379
if let Some(sugg) = print_disambiguation_help(
13791380
item_name,
13801381
args,
1382+
self_source,
13811383
err,
13821384
path,
13831385
rcvr_ty,
@@ -1410,18 +1412,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
14101412

14111413
/// Look at all the associated functions without receivers in the type's inherent impls
14121414
/// to look for builders that return `Self`, `Option<Self>` or `Result<Self, _>`.
1413-
fn find_builder_fn(&self, err: &mut Diagnostic, rcvr_ty: Ty<'tcx>, source: SelfSource<'tcx>) {
1415+
fn find_builder_fn(&self, err: &mut Diagnostic, rcvr_ty: Ty<'tcx>) {
14141416
let ty::Adt(adt_def, _) = rcvr_ty.kind() else {
14151417
return;
14161418
};
1417-
let SelfSource::QPath(ty) = source else {
1418-
return;
1419-
};
1420-
let hir = self.tcx.hir();
1421-
if let Some(Node::Pat(_)) = hir.find(hir.parent_id(ty.hir_id)) {
1422-
// Do not suggest a fn call when a pattern is expected.
1423-
return;
1424-
}
14251419
let mut items = self
14261420
.tcx
14271421
.inherent_impls(adt_def.did())
@@ -1504,7 +1498,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
15041498
rcvr_ty: Ty<'tcx>,
15051499
source: SelfSource<'tcx>,
15061500
item_name: Ident,
1507-
args: Option<MethodCallComponents<'tcx>>,
1501+
args: Option<&'tcx [hir::Expr<'tcx>]>,
15081502
sugg_span: Span,
15091503
) {
15101504
let mut has_unsuggestable_args = false;
@@ -1578,38 +1572,40 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
15781572
None
15791573
};
15801574
let mut applicability = Applicability::MachineApplicable;
1581-
let args = if let Some(MethodCallComponents { receiver, args, .. }) = args {
1582-
// The first arg is the same kind as the receiver
1583-
let explicit_args = if first_arg.is_some() {
1584-
std::iter::once(receiver).chain(args.iter()).collect::<Vec<_>>()
1575+
let args = if let SelfSource::MethodCall(receiver) = source
1576+
&& let Some(args) = args
1577+
{
1578+
// The first arg is the same kind as the receiver
1579+
let explicit_args = if first_arg.is_some() {
1580+
std::iter::once(receiver).chain(args.iter()).collect::<Vec<_>>()
1581+
} else {
1582+
// There is no `Self` kind to infer the arguments from
1583+
if has_unsuggestable_args {
1584+
applicability = Applicability::HasPlaceholders;
1585+
}
1586+
args.iter().collect()
1587+
};
1588+
format!(
1589+
"({}{})",
1590+
first_arg.unwrap_or(""),
1591+
explicit_args
1592+
.iter()
1593+
.map(|arg| self
1594+
.tcx
1595+
.sess
1596+
.source_map()
1597+
.span_to_snippet(arg.span)
1598+
.unwrap_or_else(|_| {
1599+
applicability = Applicability::HasPlaceholders;
1600+
"_".to_owned()
1601+
}))
1602+
.collect::<Vec<_>>()
1603+
.join(", "),
1604+
)
15851605
} else {
1586-
// There is no `Self` kind to infer the arguments from
1587-
if has_unsuggestable_args {
1588-
applicability = Applicability::HasPlaceholders;
1589-
}
1590-
args.iter().collect()
1606+
applicability = Applicability::HasPlaceholders;
1607+
"(...)".to_owned()
15911608
};
1592-
format!(
1593-
"({}{})",
1594-
first_arg.unwrap_or(""),
1595-
explicit_args
1596-
.iter()
1597-
.map(|arg| self
1598-
.tcx
1599-
.sess
1600-
.source_map()
1601-
.span_to_snippet(arg.span)
1602-
.unwrap_or_else(|_| {
1603-
applicability = Applicability::HasPlaceholders;
1604-
"_".to_owned()
1605-
}))
1606-
.collect::<Vec<_>>()
1607-
.join(", "),
1608-
)
1609-
} else {
1610-
applicability = Applicability::HasPlaceholders;
1611-
"(...)".to_owned()
1612-
};
16131609
err.span_suggestion(
16141610
sugg_span,
16151611
"use associated function syntax instead",
@@ -3268,7 +3264,8 @@ pub fn all_traits(tcx: TyCtxt<'_>) -> Vec<TraitInfo> {
32683264

32693265
fn print_disambiguation_help<'tcx>(
32703266
item_name: Ident,
3271-
args: Option<MethodCallComponents<'tcx>>,
3267+
args: Option<&'tcx [hir::Expr<'tcx>]>,
3268+
source: SelfSource<'tcx>,
32723269
err: &mut Diagnostic,
32733270
trait_name: String,
32743271
rcvr_ty: Ty<'_>,
@@ -3281,7 +3278,9 @@ fn print_disambiguation_help<'tcx>(
32813278
fn_has_self_parameter: bool,
32823279
) -> Option<String> {
32833280
Some(
3284-
if let (ty::AssocKind::Fn, Some(MethodCallComponents { receiver, args, .. })) = (kind, args)
3281+
if matches!(kind, ty::AssocKind::Fn)
3282+
&& let SelfSource::MethodCall(receiver) = source
3283+
&& let Some(args) = args
32853284
{
32863285
let args = format!(
32873286
"({}{})",

compiler/rustc_hir_typeck/src/pat.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -166,9 +166,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
166166
fn check_pat(&self, pat: &'tcx Pat<'tcx>, expected: Ty<'tcx>, pat_info: PatInfo<'tcx, '_>) {
167167
let PatInfo { binding_mode: def_bm, top_info: ti, .. } = pat_info;
168168
let path_res = match &pat.kind {
169-
PatKind::Path(qpath) => {
170-
Some(self.resolve_ty_and_res_fully_qualified_call(qpath, pat.hir_id, pat.span))
171-
}
169+
PatKind::Path(qpath) => Some(
170+
self.resolve_ty_and_res_fully_qualified_call(qpath, pat.hir_id, pat.span, None),
171+
),
172172
_ => None,
173173
};
174174
let adjust_mode = self.calc_adjust_mode(pat, path_res.map(|(res, ..)| res));
@@ -1060,7 +1060,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
10601060

10611061
// Resolve the path and check the definition for errors.
10621062
let (res, opt_ty, segments) =
1063-
self.resolve_ty_and_res_fully_qualified_call(qpath, pat.hir_id, pat.span);
1063+
self.resolve_ty_and_res_fully_qualified_call(qpath, pat.hir_id, pat.span, None);
10641064
if res == Res::Err {
10651065
let e = tcx.sess.delay_span_bug(pat.span, "`Res::Err` but no error emitted");
10661066
self.set_tainted_by_errors(e);

0 commit comments

Comments
 (0)