Rollup merge of #140498 - compiler-errors:check-fn-tweaks, r=oli-obk
Misc tweaks to HIR typeck (mostly w.r.t. checking calls) Just some cleanups. r? oli-obk
This commit is contained in:
commit
21df9db1f6
6 changed files with 92 additions and 140 deletions
|
|
@ -14,7 +14,7 @@ use rustc_middle::ty::adjustment::{
|
|||
use rustc_middle::ty::{self, GenericArgsRef, Ty, TyCtxt, TypeVisitableExt};
|
||||
use rustc_middle::{bug, span_bug};
|
||||
use rustc_span::def_id::LocalDefId;
|
||||
use rustc_span::{Ident, Span, sym};
|
||||
use rustc_span::{Span, sym};
|
||||
use rustc_trait_selection::error_reporting::traits::DefIdOrName;
|
||||
use rustc_trait_selection::infer::InferCtxtExt as _;
|
||||
use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt as _;
|
||||
|
|
@ -87,14 +87,29 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
|
||||
let output = match result {
|
||||
None => {
|
||||
// this will report an error since original_callee_ty is not a fn
|
||||
self.confirm_builtin_call(
|
||||
call_expr,
|
||||
callee_expr,
|
||||
original_callee_ty,
|
||||
arg_exprs,
|
||||
expected,
|
||||
)
|
||||
// Check all of the arg expressions, but with no expectations
|
||||
// since we don't have a signature to compare them to.
|
||||
for arg in arg_exprs {
|
||||
self.check_expr(arg);
|
||||
}
|
||||
|
||||
if let hir::ExprKind::Path(hir::QPath::Resolved(_, path)) = &callee_expr.kind
|
||||
&& let [segment] = path.segments
|
||||
{
|
||||
self.dcx().try_steal_modify_and_emit_err(
|
||||
segment.ident.span,
|
||||
StashKey::CallIntoMethod,
|
||||
|err| {
|
||||
// Try suggesting `foo(a)` -> `a.foo()` if possible.
|
||||
self.suggest_call_as_method(
|
||||
err, segment, arg_exprs, call_expr, expected,
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
let guar = self.report_invalid_callee(call_expr, callee_expr, expr_ty, arg_exprs);
|
||||
Ty::new_error(self.tcx, guar)
|
||||
}
|
||||
|
||||
Some(CallStep::Builtin(callee_ty)) => {
|
||||
|
|
@ -296,9 +311,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
Ty::new_tup_from_iter(self.tcx, arg_exprs.iter().map(|e| self.next_ty_var(e.span)))
|
||||
});
|
||||
|
||||
if let Some(ok) = self.lookup_method_in_trait(
|
||||
if let Some(ok) = self.lookup_method_for_operator(
|
||||
self.misc(call_expr.span),
|
||||
Ident::with_dummy_span(method_name),
|
||||
method_name,
|
||||
trait_def_id,
|
||||
adjusted_ty,
|
||||
opt_input_type,
|
||||
|
|
@ -461,32 +476,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
}
|
||||
(fn_sig, Some(def_id))
|
||||
}
|
||||
|
||||
// FIXME(const_trait_impl): these arms should error because we can't enforce them
|
||||
ty::FnPtr(sig_tys, hdr) => (sig_tys.with(hdr), None),
|
||||
_ => {
|
||||
for arg in arg_exprs {
|
||||
self.check_expr(arg);
|
||||
}
|
||||
|
||||
if let hir::ExprKind::Path(hir::QPath::Resolved(_, path)) = &callee_expr.kind
|
||||
&& let [segment] = path.segments
|
||||
{
|
||||
self.dcx().try_steal_modify_and_emit_err(
|
||||
segment.ident.span,
|
||||
StashKey::CallIntoMethod,
|
||||
|err| {
|
||||
// Try suggesting `foo(a)` -> `a.foo()` if possible.
|
||||
self.suggest_call_as_method(
|
||||
err, segment, arg_exprs, call_expr, expected,
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
let err = self.report_invalid_callee(call_expr, callee_expr, callee_ty, arg_exprs);
|
||||
|
||||
return Ty::new_error(self.tcx, err);
|
||||
}
|
||||
_ => unreachable!(),
|
||||
};
|
||||
|
||||
// Replace any late-bound regions that appear in the function
|
||||
|
|
@ -908,19 +902,23 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
call_expr: &'tcx hir::Expr<'tcx>,
|
||||
arg_exprs: &'tcx [hir::Expr<'tcx>],
|
||||
expected: Expectation<'tcx>,
|
||||
method_callee: MethodCallee<'tcx>,
|
||||
method: MethodCallee<'tcx>,
|
||||
) -> Ty<'tcx> {
|
||||
let output_type = self.check_method_argument_types(
|
||||
self.check_argument_types(
|
||||
call_expr.span,
|
||||
call_expr,
|
||||
Ok(method_callee),
|
||||
arg_exprs,
|
||||
TupleArgumentsFlag::TupleArguments,
|
||||
&method.sig.inputs()[1..],
|
||||
method.sig.output(),
|
||||
expected,
|
||||
arg_exprs,
|
||||
method.sig.c_variadic,
|
||||
TupleArgumentsFlag::TupleArguments,
|
||||
Some(method.def_id),
|
||||
);
|
||||
|
||||
self.write_method_call_and_enforce_effects(call_expr.hir_id, call_expr.span, method_callee);
|
||||
output_type
|
||||
self.write_method_call_and_enforce_effects(call_expr.hir_id, call_expr.span, method);
|
||||
|
||||
method.sig.output()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -40,7 +40,6 @@ use tracing::{debug, instrument, trace};
|
|||
use {rustc_ast as ast, rustc_hir as hir};
|
||||
|
||||
use crate::Expectation::{self, ExpectCastableToType, ExpectHasType, NoExpectation};
|
||||
use crate::TupleArgumentsFlag::DontTupleArguments;
|
||||
use crate::coercion::{CoerceMany, DynamicCoerceMany};
|
||||
use crate::errors::{
|
||||
AddressOfTemporaryTaken, BaseExpressionDoubleDot, BaseExpressionDoubleDotAddExpr,
|
||||
|
|
@ -51,8 +50,8 @@ use crate::errors::{
|
|||
YieldExprOutsideOfCoroutine,
|
||||
};
|
||||
use crate::{
|
||||
BreakableCtxt, CoroutineTypes, Diverges, FnCtxt, Needs, cast, fatally_break_rust,
|
||||
report_unexpected_variant_res, type_error_struct,
|
||||
BreakableCtxt, CoroutineTypes, Diverges, FnCtxt, Needs, TupleArgumentsFlag, cast,
|
||||
fatally_break_rust, report_unexpected_variant_res, type_error_struct,
|
||||
};
|
||||
|
||||
impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
|
|
@ -1591,28 +1590,45 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
// no need to check for bot/err -- callee does that
|
||||
let rcvr_t = self.structurally_resolve_type(rcvr.span, rcvr_t);
|
||||
|
||||
let method = match self.lookup_method(rcvr_t, segment, segment.ident.span, expr, rcvr, args)
|
||||
{
|
||||
match self.lookup_method(rcvr_t, segment, segment.ident.span, expr, rcvr, args) {
|
||||
Ok(method) => {
|
||||
// We could add a "consider `foo::<params>`" suggestion here, but I wasn't able to
|
||||
// trigger this codepath causing `structurally_resolve_type` to emit an error.
|
||||
self.write_method_call_and_enforce_effects(expr.hir_id, expr.span, method);
|
||||
Ok(method)
|
||||
|
||||
self.check_argument_types(
|
||||
segment.ident.span,
|
||||
expr,
|
||||
&method.sig.inputs()[1..],
|
||||
method.sig.output(),
|
||||
expected,
|
||||
args,
|
||||
method.sig.c_variadic,
|
||||
TupleArgumentsFlag::DontTupleArguments,
|
||||
Some(method.def_id),
|
||||
);
|
||||
|
||||
method.sig.output()
|
||||
}
|
||||
Err(error) => {
|
||||
Err(self.report_method_error(expr.hir_id, rcvr_t, error, expected, false))
|
||||
}
|
||||
};
|
||||
let guar = self.report_method_error(expr.hir_id, rcvr_t, error, expected, false);
|
||||
|
||||
// Call the generic checker.
|
||||
self.check_method_argument_types(
|
||||
segment.ident.span,
|
||||
expr,
|
||||
method,
|
||||
args,
|
||||
DontTupleArguments,
|
||||
expected,
|
||||
)
|
||||
let err_inputs = self.err_args(args.len(), guar);
|
||||
let err_output = Ty::new_error(self.tcx, guar);
|
||||
|
||||
self.check_argument_types(
|
||||
segment.ident.span,
|
||||
expr,
|
||||
&err_inputs,
|
||||
err_output,
|
||||
NoExpectation,
|
||||
args,
|
||||
false,
|
||||
TupleArgumentsFlag::DontTupleArguments,
|
||||
None,
|
||||
);
|
||||
|
||||
err_output
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Checks use `x.use`.
|
||||
|
|
|
|||
|
|
@ -33,7 +33,6 @@ use crate::fn_ctxt::arg_matrix::{ArgMatrix, Compatibility, Error, ExpectedIdx, P
|
|||
use crate::fn_ctxt::infer::FnCall;
|
||||
use crate::gather_locals::Declaration;
|
||||
use crate::inline_asm::InlineAsmCtxt;
|
||||
use crate::method::MethodCallee;
|
||||
use crate::method::probe::IsSuggestion;
|
||||
use crate::method::probe::Mode::MethodCall;
|
||||
use crate::method::probe::ProbeScope::TraitsInScope;
|
||||
|
|
@ -127,61 +126,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
pub(in super::super) fn check_method_argument_types(
|
||||
&self,
|
||||
sp: Span,
|
||||
expr: &'tcx hir::Expr<'tcx>,
|
||||
method: Result<MethodCallee<'tcx>, ErrorGuaranteed>,
|
||||
args_no_rcvr: &'tcx [hir::Expr<'tcx>],
|
||||
tuple_arguments: TupleArgumentsFlag,
|
||||
expected: Expectation<'tcx>,
|
||||
) -> Ty<'tcx> {
|
||||
let has_error = match method {
|
||||
Ok(method) => method.args.error_reported().and(method.sig.error_reported()),
|
||||
Err(guar) => Err(guar),
|
||||
};
|
||||
if let Err(guar) = has_error {
|
||||
let err_inputs = self.err_args(
|
||||
method.map_or(args_no_rcvr.len(), |method| method.sig.inputs().len() - 1),
|
||||
guar,
|
||||
);
|
||||
let err_output = Ty::new_error(self.tcx, guar);
|
||||
|
||||
let err_inputs = match tuple_arguments {
|
||||
DontTupleArguments => err_inputs,
|
||||
TupleArguments => vec![Ty::new_tup(self.tcx, &err_inputs)],
|
||||
};
|
||||
|
||||
self.check_argument_types(
|
||||
sp,
|
||||
expr,
|
||||
&err_inputs,
|
||||
err_output,
|
||||
NoExpectation,
|
||||
args_no_rcvr,
|
||||
false,
|
||||
tuple_arguments,
|
||||
method.ok().map(|method| method.def_id),
|
||||
);
|
||||
return err_output;
|
||||
}
|
||||
|
||||
let method = method.unwrap();
|
||||
self.check_argument_types(
|
||||
sp,
|
||||
expr,
|
||||
&method.sig.inputs()[1..],
|
||||
method.sig.output(),
|
||||
expected,
|
||||
args_no_rcvr,
|
||||
method.sig.c_variadic,
|
||||
tuple_arguments,
|
||||
Some(method.def_id),
|
||||
);
|
||||
|
||||
method.sig.output()
|
||||
}
|
||||
|
||||
/// Generic function that factors out common logic from function calls,
|
||||
/// method calls and overloaded operators.
|
||||
pub(in super::super) fn check_argument_types(
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ use rustc_middle::ty::{
|
|||
self, GenericArgs, GenericArgsRef, GenericParamDefKind, Ty, TypeVisitableExt,
|
||||
};
|
||||
use rustc_middle::{bug, span_bug};
|
||||
use rustc_span::{ErrorGuaranteed, Ident, Span};
|
||||
use rustc_span::{ErrorGuaranteed, Ident, Span, Symbol};
|
||||
use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt;
|
||||
use rustc_trait_selection::traits::{self, NormalizeExt};
|
||||
use tracing::{debug, instrument};
|
||||
|
|
@ -329,10 +329,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
/// an obligation for a particular trait with the given self type and checks
|
||||
/// whether that trait is implemented.
|
||||
#[instrument(level = "debug", skip(self))]
|
||||
pub(super) fn lookup_method_in_trait(
|
||||
pub(super) fn lookup_method_for_operator(
|
||||
&self,
|
||||
cause: ObligationCause<'tcx>,
|
||||
m_name: Ident,
|
||||
method_name: Symbol,
|
||||
trait_def_id: DefId,
|
||||
self_ty: Ty<'tcx>,
|
||||
opt_rhs_ty: Option<Ty<'tcx>>,
|
||||
|
|
@ -374,13 +374,20 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
// Trait must have a method named `m_name` and it should not have
|
||||
// type parameters or early-bound regions.
|
||||
let tcx = self.tcx;
|
||||
let Some(method_item) = self.associated_value(trait_def_id, m_name) else {
|
||||
// We use `Ident::with_dummy_span` since no built-in operator methods have
|
||||
// any macro-specific hygeine, so the span's context doesn't really matter.
|
||||
let Some(method_item) =
|
||||
self.associated_value(trait_def_id, Ident::with_dummy_span(method_name))
|
||||
else {
|
||||
bug!("expected associated item for operator trait")
|
||||
};
|
||||
|
||||
let def_id = method_item.def_id;
|
||||
if !method_item.is_fn() {
|
||||
span_bug!(tcx.def_span(def_id), "expected `{m_name}` to be an associated function");
|
||||
span_bug!(
|
||||
tcx.def_span(def_id),
|
||||
"expected `{method_name}` to be an associated function"
|
||||
);
|
||||
}
|
||||
|
||||
debug!("lookup_in_trait_adjusted: method_item={:?}", method_item);
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ use rustc_middle::ty::print::with_no_trimmed_paths;
|
|||
use rustc_middle::ty::{self, IsSuggestable, Ty, TyCtxt, TypeVisitableExt};
|
||||
use rustc_session::errors::ExprParenthesesNeeded;
|
||||
use rustc_span::source_map::Spanned;
|
||||
use rustc_span::{Ident, Span, Symbol, sym};
|
||||
use rustc_span::{Span, Symbol, sym};
|
||||
use rustc_trait_selection::infer::InferCtxtExt;
|
||||
use rustc_trait_selection::traits::{FulfillmentError, Obligation, ObligationCtxt};
|
||||
use tracing::debug;
|
||||
|
|
@ -975,7 +975,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
lhs_ty, opname, trait_did
|
||||
);
|
||||
|
||||
let opname = Ident::with_dummy_span(opname);
|
||||
let (opt_rhs_expr, opt_rhs_ty) = opt_rhs.unzip();
|
||||
let cause = self.cause(
|
||||
span,
|
||||
|
|
@ -990,7 +989,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
);
|
||||
|
||||
let method =
|
||||
self.lookup_method_in_trait(cause.clone(), opname, trait_did, lhs_ty, opt_rhs_ty);
|
||||
self.lookup_method_for_operator(cause.clone(), opname, trait_did, lhs_ty, opt_rhs_ty);
|
||||
match method {
|
||||
Some(ok) => {
|
||||
let method = self.register_infer_ok_obligations(ok);
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ use rustc_middle::ty::adjustment::{
|
|||
PointerCoercion,
|
||||
};
|
||||
use rustc_middle::ty::{self, Ty};
|
||||
use rustc_span::{Ident, Span, sym};
|
||||
use rustc_span::{Span, sym};
|
||||
use tracing::debug;
|
||||
use {rustc_ast as ast, rustc_hir as hir};
|
||||
|
||||
|
|
@ -211,13 +211,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
return None;
|
||||
};
|
||||
|
||||
self.lookup_method_in_trait(
|
||||
self.misc(span),
|
||||
Ident::with_dummy_span(imm_op),
|
||||
imm_tr,
|
||||
base_ty,
|
||||
opt_rhs_ty,
|
||||
)
|
||||
self.lookup_method_for_operator(self.misc(span), imm_op, imm_tr, base_ty, opt_rhs_ty)
|
||||
}
|
||||
|
||||
fn try_mutable_overloaded_place_op(
|
||||
|
|
@ -237,13 +231,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
return None;
|
||||
};
|
||||
|
||||
self.lookup_method_in_trait(
|
||||
self.misc(span),
|
||||
Ident::with_dummy_span(mut_op),
|
||||
mut_tr,
|
||||
base_ty,
|
||||
opt_rhs_ty,
|
||||
)
|
||||
self.lookup_method_for_operator(self.misc(span), mut_op, mut_tr, base_ty, opt_rhs_ty)
|
||||
}
|
||||
|
||||
/// Convert auto-derefs, indices, etc of an expression from `Deref` and `Index`
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue