Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 23 additions & 5 deletions compiler/rustc_hir_typeck/src/callee.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,18 @@ use crate::method::TreatNotYetDefinedOpaques;
use crate::method::confirm::ConfirmContext;
use crate::method::probe::{IsSuggestion, Mode};

/// Side-table info for lowering splatted function arguments.
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
pub(crate) enum SplatLoweringInfo<'tcx> {
/// The DefId of the FnDef being called, used to look up the function type.
/// Also used during argument suggestion for non-splatted function calls.
FnDef(DefId),
/// The type of the FnPtr being called.
FnPtr(Ty<'tcx>),
/// Type resolution errored.
Error(ErrorGuaranteed),
}

/// Checks that it is legal to call methods of the trait corresponding
/// to `trait_id` (this only cares about the trait, not the specific
/// method that is called).
Expand Down Expand Up @@ -600,13 +612,19 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
);
let fn_sig = self.normalize(call_expr.span, Unnormalized::new_wip(fn_sig));

// Splatted FnDefs use the DefId to look up the type, FnPtrs need it directly
let fn_id = match def_id {
Some(x) => SplatLoweringInfo::FnDef(x),
None => SplatLoweringInfo::FnPtr(callee_ty),
};

self.check_argument_types_maybe_method_like(
&fn_sig,
call_expr,
arg_exprs,
expected,
TupleArgumentsFlag::with_fn_sig_kind(fn_sig.fn_sig_kind, false),
def_id,
fn_id,
callee_generic_args,
);

Expand Down Expand Up @@ -643,7 +661,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
arg_exprs: &'tcx [hir::Expr<'tcx>],
expected: Expectation<'tcx>,
tuple_arguments_flag: TupleArgumentsFlag,
def_id: Option<DefId>,
fn_id: SplatLoweringInfo<'tcx>,
callee_generic_args: Option<GenericArgsRef<'tcx>>,
) {
let do_check = || {
Expand All @@ -656,7 +674,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
arg_exprs,
fn_sig.c_variadic(),
tuple_arguments_flag,
def_id,
fn_id,
callee_generic_args,
);
};
Expand Down Expand Up @@ -1074,7 +1092,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
arg_exprs,
fn_sig.fn_sig_kind.c_variadic(),
TupleArgumentsFlag::rust_fn_trait_call(),
Some(closure_def_id.to_def_id()),
SplatLoweringInfo::FnDef(closure_def_id.to_def_id()),
None,
);

Expand Down Expand Up @@ -1172,7 +1190,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
arg_exprs,
method.sig.fn_sig_kind.c_variadic(),
TupleArgumentsFlag::rust_fn_trait_call(),
Some(method.def_id),
SplatLoweringInfo::FnDef(method.def_id),
None,
);

Expand Down
11 changes: 6 additions & 5 deletions compiler/rustc_hir_typeck/src/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ use rustc_trait_selection::traits::{self, ObligationCauseCode, ObligationCtxt};
use tracing::{debug, instrument, trace};

use crate::Expectation::{self, ExpectCastableToType, ExpectHasType, NoExpectation};
use crate::callee::SplatLoweringInfo;
use crate::coercion::CoerceMany;
use crate::diagnostics::{
AddressOfTemporaryTaken, BaseExpressionDoubleDot, BaseExpressionDoubleDotAddExpr,
Expand Down Expand Up @@ -1479,7 +1480,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
args,
method.sig.fn_sig_kind.c_variadic(),
method_tuple_args_flag,
Some(method.def_id),
SplatLoweringInfo::FnDef(method.def_id),
Some(method.args),
);

Expand All @@ -1491,22 +1492,22 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let guar = self.report_method_error(expr.hir_id, rcvr_t, error, expected, false);

let err_inputs = self.err_args(args.len(), guar);
let err_output = Ty::new_error(self.tcx, guar);
let err_ty = Ty::new_error(self.tcx, guar);

self.check_argument_types(
segment.ident.span,
expr,
&err_inputs,
err_output,
err_ty,
NoExpectation,
args,
false,
TupleArgumentsFlag::DontTupleArguments,
None,
SplatLoweringInfo::Error(guar),
Some(GenericArgsRef::default()),
);

err_output
err_ty
}
}
}
Expand Down
54 changes: 41 additions & 13 deletions compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ use rustc_trait_selection::traits::{
};
use tracing::{debug, instrument};

use crate::callee::{self, DeferredCallResolution};
use crate::callee::{self, DeferredCallResolution, SplatLoweringInfo};
use crate::diagnostics::{self, CtorIsPrivate};
use crate::method::{self, MethodCallee};
use crate::{BreakableCtxt, Diverges, Expectation, FnCtxt, LoweredTy};
Expand Down Expand Up @@ -238,7 +238,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
pub(crate) fn write_splatted_resolution(
&self,
hir_id: HirId,
r: Result<SplattedDef, ErrorGuaranteed>,
r: Result<SplattedDef<'tcx>, ErrorGuaranteed>,
) {
self.typeck_results.borrow_mut().splatted_defs_mut().insert(hir_id, r);
}
Expand All @@ -260,24 +260,52 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
&self,
hir_id: HirId,
span: Span,
callee_def_id: Option<DefId>,
fn_id: SplatLoweringInfo<'tcx>,
callee_generic_args: Option<GenericArgsRef<'tcx>>,
first_tupled_arg_index: u16,
tupled_args_count: u16,
) {
// FIXME(const_trait_impl): enforce constness using enforce_context_effects() and add
// _and_enforce_effects to this method's name

self.write_splatted_resolution(
hir_id,
Ok(SplattedDef {
def_id: callee_def_id,
arg_index: first_tupled_arg_index,
arg_count: tupled_args_count,
}),
);
if let Some(callee_generic_args) = callee_generic_args {
self.write_args(hir_id, callee_generic_args);
match fn_id {
// We're splatting a FnDef based on its DefId
SplatLoweringInfo::FnDef(def_id) => {
self.write_splatted_resolution(
hir_id,
Ok(SplattedDef::FnDef {
def_id,
arg_index: first_tupled_arg_index,
arg_count: tupled_args_count,
}),
);
if let Some(callee_generic_args) = callee_generic_args {
self.write_args(hir_id, callee_generic_args);
}
}
// We're splatting a FnPtr based on its type
SplatLoweringInfo::FnPtr(fn_ty) => {
// FIXME(splat): do we need to look up both these HirIds?
// They can be different (and are different in some UI tests)
self.write_splatted_resolution(
hir_id,
Ok(SplattedDef::FnPtr {
fn_ptr_type: fn_ty,
arg_index: first_tupled_arg_index,
arg_count: tupled_args_count,
}),
);
// FIXME(splat): is this actually populated and used correctly?
if let Some(callee_generic_args) = callee_generic_args {
self.write_args(hir_id, callee_generic_args);
}
}
SplatLoweringInfo::Error(guar) => {
self.write_splatted_resolution(hir_id, Err(guar));
if let Some(callee_generic_args) = callee_generic_args {
self.write_args(hir_id, callee_generic_args);
}
}
}
}

Expand Down
Loading
Loading