Skip to content

Commit 7246d31

Browse files
Inline expected_inputs_for_expected_output into check_argument_types
1 parent 83695e0 commit 7246d31

File tree

3 files changed

+48
-66
lines changed

3 files changed

+48
-66
lines changed

compiler/rustc_hir_typeck/src/callee.rs

+4-17
Original file line numberDiff line numberDiff line change
@@ -502,18 +502,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
502502
let fn_sig = self.instantiate_binder_with_fresh_vars(call_expr.span, infer::FnCall, fn_sig);
503503
let fn_sig = self.normalize(call_expr.span, fn_sig);
504504

505-
// Call the generic checker.
506-
let expected_arg_tys = self.expected_inputs_for_expected_output(
507-
call_expr.span,
508-
expected,
509-
fn_sig.output(),
510-
fn_sig.inputs(),
511-
);
512505
self.check_argument_types(
513506
call_expr.span,
514507
call_expr,
515508
fn_sig.inputs(),
516-
expected_arg_tys,
509+
fn_sig.output(),
510+
expected,
517511
arg_exprs,
518512
fn_sig.c_variadic,
519513
TupleArgumentsFlag::DontTupleArguments,
@@ -865,19 +859,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
865859
// don't know the full details yet (`Fn` vs `FnMut` etc), but we
866860
// do know the types expected for each argument and the return
867861
// type.
868-
869-
let expected_arg_tys = self.expected_inputs_for_expected_output(
870-
call_expr.span,
871-
expected,
872-
fn_sig.output(),
873-
fn_sig.inputs(),
874-
);
875-
876862
self.check_argument_types(
877863
call_expr.span,
878864
call_expr,
879865
fn_sig.inputs(),
880-
expected_arg_tys,
866+
fn_sig.output(),
867+
expected,
881868
arg_exprs,
882869
fn_sig.c_variadic,
883870
TupleArgumentsFlag::TupleArguments,

compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs

-36
Original file line numberDiff line numberDiff line change
@@ -688,42 +688,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
688688
vec![ty_error; len]
689689
}
690690

691-
/// Unifies the output type with the expected type early, for more coercions
692-
/// and forward type information on the input expressions.
693-
#[instrument(skip(self, call_span), level = "debug")]
694-
pub(crate) fn expected_inputs_for_expected_output(
695-
&self,
696-
call_span: Span,
697-
expected_ret: Expectation<'tcx>,
698-
formal_ret: Ty<'tcx>,
699-
formal_args: &[Ty<'tcx>],
700-
) -> Option<Vec<Ty<'tcx>>> {
701-
let formal_ret = self.resolve_vars_with_obligations(formal_ret);
702-
let ret_ty = expected_ret.only_has_type(self)?;
703-
704-
let expect_args = self
705-
.fudge_inference_if_ok(|| {
706-
let ocx = ObligationCtxt::new(self);
707-
708-
// Attempt to apply a subtyping relationship between the formal
709-
// return type (likely containing type variables if the function
710-
// is polymorphic) and the expected return type.
711-
// No argument expectations are produced if unification fails.
712-
let origin = self.misc(call_span);
713-
ocx.sup(&origin, self.param_env, ret_ty, formal_ret)?;
714-
if !ocx.select_where_possible().is_empty() {
715-
return Err(TypeError::Mismatch);
716-
}
717-
718-
// Record all the argument types, with the args
719-
// produced from the above subtyping unification.
720-
Ok(Some(formal_args.iter().map(|&ty| self.resolve_vars_if_possible(ty)).collect()))
721-
})
722-
.unwrap_or_default();
723-
debug!(?formal_args, ?formal_ret, ?expect_args, ?expected_ret);
724-
expect_args
725-
}
726-
727691
pub(crate) fn resolve_lang_item_path(
728692
&self,
729693
lang_item: hir::LangItem,

compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs

+44-13
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ use rustc_hir_analysis::hir_ty_lowering::HirTyLowerer;
1717
use rustc_index::IndexVec;
1818
use rustc_infer::infer::{DefineOpaqueTypes, InferOk, TypeTrace};
1919
use rustc_middle::ty::adjustment::AllowTwoPhase;
20+
use rustc_middle::ty::error::TypeError;
2021
use rustc_middle::ty::visit::TypeVisitableExt;
2122
use rustc_middle::ty::{self, IsSuggestable, Ty, TyCtxt};
2223
use rustc_middle::{bug, span_bug};
@@ -25,7 +26,7 @@ use rustc_span::symbol::{kw, Ident};
2526
use rustc_span::{sym, Span, DUMMY_SP};
2627
use rustc_trait_selection::error_reporting::infer::{FailureCode, ObligationCauseExt};
2728
use rustc_trait_selection::infer::InferCtxtExt;
28-
use rustc_trait_selection::traits::{self, ObligationCauseCode, SelectionContext};
29+
use rustc_trait_selection::traits::{self, ObligationCauseCode, ObligationCtxt, SelectionContext};
2930
use {rustc_ast as ast, rustc_hir as hir};
3031

3132
use crate::coercion::CoerceMany;
@@ -123,6 +124,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
123124
};
124125
if let Err(guar) = has_error {
125126
let err_inputs = self.err_args(args_no_rcvr.len(), guar);
127+
let err_output = Ty::new_error(self.tcx, guar);
126128

127129
let err_inputs = match tuple_arguments {
128130
DontTupleArguments => err_inputs,
@@ -133,28 +135,23 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
133135
sp,
134136
expr,
135137
&err_inputs,
136-
None,
138+
err_output,
139+
NoExpectation,
137140
args_no_rcvr,
138141
false,
139142
tuple_arguments,
140143
method.ok().map(|method| method.def_id),
141144
);
142-
return Ty::new_error(self.tcx, guar);
145+
return err_output;
143146
}
144147

145148
let method = method.unwrap();
146-
// HACK(eddyb) ignore self in the definition (see above).
147-
let expected_input_tys = self.expected_inputs_for_expected_output(
148-
sp,
149-
expected,
150-
method.sig.output(),
151-
&method.sig.inputs()[1..],
152-
);
153149
self.check_argument_types(
154150
sp,
155151
expr,
156152
&method.sig.inputs()[1..],
157-
expected_input_tys,
153+
method.sig.output(),
154+
expected,
158155
args_no_rcvr,
159156
method.sig.c_variadic,
160157
tuple_arguments,
@@ -174,8 +171,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
174171
call_expr: &'tcx hir::Expr<'tcx>,
175172
// Types (as defined in the *signature* of the target function)
176173
formal_input_tys: &[Ty<'tcx>],
177-
// More specific expected types, after unifying with caller output types
178-
expected_input_tys: Option<Vec<Ty<'tcx>>>,
174+
formal_output: Ty<'tcx>,
175+
// Expected output from the parent expression or statement
176+
expectation: Expectation<'tcx>,
179177
// The expressions for each provided argument
180178
provided_args: &'tcx [hir::Expr<'tcx>],
181179
// Whether the function is variadic, for example when imported from C
@@ -209,6 +207,39 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
209207
);
210208
}
211209

210+
// First, let's unify the formal method signature with the expectation eagerly.
211+
// We use this to guide coercion inference; it's output is "fudged" which means
212+
// any remaining type variables are assigned to new, unrelated variables. This
213+
// is because the inference guidance here is only speculative.
214+
let expected_input_tys: Option<Vec<_>> = expectation
215+
.only_has_type(self)
216+
.and_then(|expected_output| {
217+
self.fudge_inference_if_ok(|| {
218+
let ocx = ObligationCtxt::new(self);
219+
220+
// Attempt to apply a subtyping relationship between the formal
221+
// return type (likely containing type variables if the function
222+
// is polymorphic) and the expected return type.
223+
// No argument expectations are produced if unification fails.
224+
let origin = self.misc(call_span);
225+
ocx.sup(&origin, self.param_env, expected_output, formal_output)?;
226+
if !ocx.select_where_possible().is_empty() {
227+
return Err(TypeError::Mismatch);
228+
}
229+
230+
// Record all the argument types, with the args
231+
// produced from the above subtyping unification.
232+
Ok(Some(
233+
formal_input_tys
234+
.iter()
235+
.map(|&ty| self.resolve_vars_if_possible(ty))
236+
.collect(),
237+
))
238+
})
239+
.ok()
240+
})
241+
.unwrap_or_default();
242+
212243
let mut err_code = E0061;
213244

214245
// If the arguments should be wrapped in a tuple (ex: closures), unwrap them here

0 commit comments

Comments
 (0)