Auto merge of #101261 - TaKO8Ki:separate-receiver-from-arguments-in-hir, r=cjgillot
Separate the receiver from arguments in HIR Related to #100232 cc `@cjgillot`
This commit is contained in:
commit
b44197abb0
140 changed files with 815 additions and 720 deletions
|
@ -590,7 +590,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
let closure_params_len = closure_fn_decl.inputs.len();
|
||||
let (
|
||||
Some(Node::Expr(hir::Expr {
|
||||
kind: hir::ExprKind::MethodCall(method_path, method_expr, _),
|
||||
kind: hir::ExprKind::MethodCall(method_path, receiver, ..),
|
||||
..
|
||||
})),
|
||||
1,
|
||||
|
@ -598,7 +598,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
return None;
|
||||
};
|
||||
|
||||
let self_ty = self.typeck_results.borrow().expr_ty(&method_expr[0]);
|
||||
let self_ty = self.typeck_results.borrow().expr_ty(receiver);
|
||||
let name = method_path.ident.name;
|
||||
let is_as_ref_able = match self_ty.peel_refs().kind() {
|
||||
ty::Adt(def, _) => {
|
||||
|
@ -767,22 +767,21 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
};
|
||||
if self.can_coerce(ref_ty, expected) {
|
||||
let mut sugg_sp = sp;
|
||||
if let hir::ExprKind::MethodCall(ref segment, ref args, _) = expr.kind {
|
||||
if let hir::ExprKind::MethodCall(ref segment, receiver, args, _) = expr.kind {
|
||||
let clone_trait =
|
||||
self.tcx.require_lang_item(LangItem::Clone, Some(segment.ident.span));
|
||||
if let ([arg], Some(true), sym::clone) = (
|
||||
&args[..],
|
||||
self.typeck_results.borrow().type_dependent_def_id(expr.hir_id).map(
|
||||
if args.is_empty()
|
||||
&& self.typeck_results.borrow().type_dependent_def_id(expr.hir_id).map(
|
||||
|did| {
|
||||
let ai = self.tcx.associated_item(did);
|
||||
ai.trait_container(self.tcx) == Some(clone_trait)
|
||||
},
|
||||
),
|
||||
segment.ident.name,
|
||||
) {
|
||||
) == Some(true)
|
||||
&& segment.ident.name == sym::clone
|
||||
{
|
||||
// If this expression had a clone call when suggesting borrowing
|
||||
// we want to suggest removing it because it'd now be unnecessary.
|
||||
sugg_sp = arg.span;
|
||||
sugg_sp = receiver.span;
|
||||
}
|
||||
}
|
||||
if let Ok(src) = sm.span_to_snippet(sugg_sp) {
|
||||
|
|
|
@ -324,8 +324,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
}
|
||||
ExprKind::Block(body, _) => self.check_block_with_expected(&body, expected),
|
||||
ExprKind::Call(callee, args) => self.check_call(expr, &callee, args, expected),
|
||||
ExprKind::MethodCall(segment, args, _) => {
|
||||
self.check_method_call(expr, segment, args, expected)
|
||||
ExprKind::MethodCall(segment, receiver, args, _) => {
|
||||
self.check_method_call(expr, segment, receiver, args, expected)
|
||||
}
|
||||
ExprKind::Cast(e, t) => self.check_expr_cast(e, t, expr),
|
||||
ExprKind::Type(e, t) => {
|
||||
|
@ -1195,13 +1195,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
&self,
|
||||
expr: &'tcx hir::Expr<'tcx>,
|
||||
segment: &hir::PathSegment<'_>,
|
||||
rcvr: &'tcx hir::Expr<'tcx>,
|
||||
args: &'tcx [hir::Expr<'tcx>],
|
||||
expected: Expectation<'tcx>,
|
||||
) -> Ty<'tcx> {
|
||||
let rcvr = &args[0];
|
||||
let rcvr_t = self.check_expr(&rcvr);
|
||||
// no need to check for bot/err -- callee does that
|
||||
let rcvr_t = self.structurally_resolved_type(args[0].span, rcvr_t);
|
||||
let rcvr_t = self.structurally_resolved_type(rcvr.span, rcvr_t);
|
||||
let span = segment.ident.span;
|
||||
|
||||
let method = match self.lookup_method(rcvr_t, segment, span, expr, rcvr, args) {
|
||||
|
@ -1218,9 +1218,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
span,
|
||||
rcvr_t,
|
||||
segment.ident,
|
||||
SelfSource::MethodCall(&args[0]),
|
||||
SelfSource::MethodCall(rcvr),
|
||||
error,
|
||||
Some(args),
|
||||
Some((rcvr, args)),
|
||||
) {
|
||||
err.emit();
|
||||
}
|
||||
|
@ -1230,14 +1230,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
};
|
||||
|
||||
// Call the generic checker.
|
||||
self.check_method_argument_types(
|
||||
span,
|
||||
expr,
|
||||
method,
|
||||
&args[1..],
|
||||
DontTupleArguments,
|
||||
expected,
|
||||
)
|
||||
self.check_method_argument_types(span, expr, method, &args, DontTupleArguments, expected)
|
||||
}
|
||||
|
||||
fn check_expr_cast(
|
||||
|
|
|
@ -987,7 +987,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
if found != self.tcx.types.unit {
|
||||
return;
|
||||
}
|
||||
if let ExprKind::MethodCall(path_segment, [rcvr, ..], _) = expr.kind {
|
||||
if let ExprKind::MethodCall(path_segment, rcvr, ..) = expr.kind {
|
||||
if self
|
||||
.typeck_results
|
||||
.borrow()
|
||||
|
|
|
@ -478,7 +478,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
}
|
||||
}
|
||||
hir::ExprKind::Call(hir::Expr { span, .. }, _) => (call_span, *span, None, false),
|
||||
hir::ExprKind::MethodCall(path_segment, _, span) => {
|
||||
hir::ExprKind::MethodCall(path_segment, _, _, span) => {
|
||||
let ident_span = path_segment.ident.span;
|
||||
let ident_span = if let Some(args) = path_segment.args {
|
||||
ident_span.with_hi(args.span_ext.hi())
|
||||
|
@ -530,13 +530,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
.collect();
|
||||
let callee_expr = match &call_expr.peel_blocks().kind {
|
||||
hir::ExprKind::Call(callee, _) => Some(*callee),
|
||||
hir::ExprKind::MethodCall(_, callee, _) => {
|
||||
hir::ExprKind::MethodCall(_, receiver, ..) => {
|
||||
if let Some((DefKind::AssocFn, def_id)) =
|
||||
self.typeck_results.borrow().type_dependent_def(call_expr.hir_id)
|
||||
&& let Some(assoc) = tcx.opt_associated_item(def_id)
|
||||
&& assoc.fn_has_self_parameter
|
||||
{
|
||||
Some(&callee[0])
|
||||
Some(*receiver)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
|
@ -1805,6 +1805,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
param,
|
||||
*call_hir_id,
|
||||
callee.span,
|
||||
None,
|
||||
args,
|
||||
)
|
||||
{
|
||||
|
@ -1823,7 +1824,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
}
|
||||
}
|
||||
}
|
||||
hir::ExprKind::MethodCall(segment, args, ..) => {
|
||||
hir::ExprKind::MethodCall(segment, receiver, args, ..) => {
|
||||
for param in [param_to_point_at, fallback_param_to_point_at, self_param_to_point_at]
|
||||
.into_iter()
|
||||
.flatten()
|
||||
|
@ -1834,6 +1835,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
param,
|
||||
hir_id,
|
||||
segment.ident.span,
|
||||
Some(receiver),
|
||||
args,
|
||||
) {
|
||||
return true;
|
||||
|
@ -1901,7 +1903,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
param_to_point_at: ty::GenericArg<'tcx>,
|
||||
call_hir_id: hir::HirId,
|
||||
callee_span: Span,
|
||||
args: &[hir::Expr<'tcx>],
|
||||
receiver: Option<&'tcx hir::Expr<'tcx>>,
|
||||
args: &'tcx [hir::Expr<'tcx>],
|
||||
) -> bool {
|
||||
let sig = self.tcx.fn_sig(def_id).skip_binder();
|
||||
let args_referencing_param: Vec<_> = sig
|
||||
|
@ -1910,9 +1913,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
.enumerate()
|
||||
.filter(|(_, ty)| find_param_in_ty(**ty, param_to_point_at))
|
||||
.collect();
|
||||
|
||||
// If there's one field that references the given generic, great!
|
||||
if let [(idx, _)] = args_referencing_param.as_slice() && let Some(arg) = args.get(*idx) {
|
||||
if let [(idx, _)] = args_referencing_param.as_slice()
|
||||
&& let Some(arg) = receiver
|
||||
.map_or(args.get(*idx), |rcvr| if *idx == 0 { Some(rcvr) } else { args.get(*idx - 1) }) {
|
||||
error.obligation.cause.span = arg.span.find_ancestor_in_same_ctxt(error.obligation.cause.span).unwrap_or(arg.span);
|
||||
error.obligation.cause.map_code(|parent_code| {
|
||||
ObligationCauseCode::FunctionArgumentObligation {
|
||||
|
|
|
@ -1049,7 +1049,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
found_ty: Ty<'tcx>,
|
||||
expr: &hir::Expr<'_>,
|
||||
) {
|
||||
let hir::ExprKind::MethodCall(segment, &[ref callee_expr], _) = expr.kind else { return; };
|
||||
let hir::ExprKind::MethodCall(segment, callee_expr, &[], _) = expr.kind else { return; };
|
||||
let Some(clone_trait_did) = self.tcx.lang_items().clone_trait() else { return; };
|
||||
let ty::Ref(_, pointee_ty, _) = found_ty.kind() else { return };
|
||||
let results = self.typeck_results.borrow();
|
||||
|
|
|
@ -434,7 +434,8 @@ impl<'a, 'tcx> Visitor<'tcx> for DropRangeVisitor<'a, 'tcx> {
|
|||
|
||||
self.handle_uninhabited_return(expr);
|
||||
}
|
||||
ExprKind::MethodCall(_, exprs, _) => {
|
||||
ExprKind::MethodCall(_, receiver, exprs, _) => {
|
||||
self.visit_expr(receiver);
|
||||
for expr in exprs {
|
||||
self.visit_expr(expr);
|
||||
}
|
||||
|
|
|
@ -160,7 +160,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
if precise {
|
||||
let args = args
|
||||
.iter()
|
||||
.skip(1)
|
||||
.map(|arg| {
|
||||
let span = arg.span.find_ancestor_inside(sp).unwrap_or_default();
|
||||
format!(
|
||||
|
|
|
@ -95,7 +95,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
item_name: Ident,
|
||||
source: SelfSource<'tcx>,
|
||||
error: MethodError<'tcx>,
|
||||
args: Option<&'tcx [hir::Expr<'tcx>]>,
|
||||
args: Option<(&'tcx hir::Expr<'tcx>, &'tcx [hir::Expr<'tcx>])>,
|
||||
) -> Option<DiagnosticBuilder<'_, ErrorGuaranteed>> {
|
||||
// Avoid suggestions when we don't know what's going on.
|
||||
if rcvr_ty.references_error() {
|
||||
|
@ -998,7 +998,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
span,
|
||||
rcvr_ty,
|
||||
item_name,
|
||||
args.map(|args| args.len()),
|
||||
args.map(|(_, args)| args.len() + 1),
|
||||
source,
|
||||
out_of_scope_traits,
|
||||
&unsatisfied_predicates,
|
||||
|
@ -2310,7 +2310,7 @@ pub fn all_traits(tcx: TyCtxt<'_>) -> Vec<TraitInfo> {
|
|||
|
||||
fn print_disambiguation_help<'tcx>(
|
||||
item_name: Ident,
|
||||
args: Option<&'tcx [hir::Expr<'tcx>]>,
|
||||
args: Option<(&'tcx hir::Expr<'tcx>, &'tcx [hir::Expr<'tcx>])>,
|
||||
err: &mut Diagnostic,
|
||||
trait_name: String,
|
||||
rcvr_ty: Ty<'_>,
|
||||
|
@ -2322,7 +2322,7 @@ fn print_disambiguation_help<'tcx>(
|
|||
fn_has_self_parameter: bool,
|
||||
) {
|
||||
let mut applicability = Applicability::MachineApplicable;
|
||||
let (span, sugg) = if let (ty::AssocKind::Fn, Some(args)) = (kind, args) {
|
||||
let (span, sugg) = if let (ty::AssocKind::Fn, Some((receiver, args))) = (kind, args) {
|
||||
let args = format!(
|
||||
"({}{})",
|
||||
if rcvr_ty.is_region_ptr() {
|
||||
|
@ -2330,7 +2330,8 @@ fn print_disambiguation_help<'tcx>(
|
|||
} else {
|
||||
""
|
||||
},
|
||||
args.iter()
|
||||
std::iter::once(receiver)
|
||||
.chain(args.iter())
|
||||
.map(|arg| source_map.span_to_snippet(arg.span).unwrap_or_else(|_| {
|
||||
applicability = Applicability::HasPlaceholders;
|
||||
"_".to_owned()
|
||||
|
|
|
@ -233,8 +233,9 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> {
|
|||
self.consume_exprs(args);
|
||||
}
|
||||
|
||||
hir::ExprKind::MethodCall(.., args, _) => {
|
||||
hir::ExprKind::MethodCall(.., receiver, args, _) => {
|
||||
// callee.m(args)
|
||||
self.consume_expr(receiver);
|
||||
self.consume_exprs(args);
|
||||
}
|
||||
|
||||
|
|
|
@ -755,13 +755,13 @@ impl<'a, 'tcx> WrongNumberOfGenericArgs<'a, 'tcx> {
|
|||
num_assoc_fn_excess_args: usize,
|
||||
num_trait_generics_except_self: usize,
|
||||
) {
|
||||
if let hir::ExprKind::MethodCall(_, args, _) = expr.kind {
|
||||
assert_eq!(args.len(), 1);
|
||||
if let hir::ExprKind::MethodCall(_, receiver, args, ..) = expr.kind {
|
||||
assert_eq!(args.len(), 0);
|
||||
if num_assoc_fn_excess_args == num_trait_generics_except_self {
|
||||
if let Some(gen_args) = self.gen_args.span_ext()
|
||||
&& let Ok(gen_args) = self.tcx.sess.source_map().span_to_snippet(gen_args)
|
||||
&& let Ok(args) = self.tcx.sess.source_map().span_to_snippet(args[0].span) {
|
||||
let sugg = format!("{}::{}::{}({})", self.tcx.item_name(trait_), gen_args, self.tcx.item_name(self.def_id), args);
|
||||
&& let Ok(receiver) = self.tcx.sess.source_map().span_to_snippet(receiver.span) {
|
||||
let sugg = format!("{}::{}::{}({})", self.tcx.item_name(trait_), gen_args, self.tcx.item_name(self.def_id), receiver);
|
||||
err.span_suggestion(expr.span, msg, sugg, Applicability::MaybeIncorrect);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue