@@ -17,6 +17,7 @@ use rustc_hir_analysis::hir_ty_lowering::HirTyLowerer;
1717use rustc_index:: IndexVec ;
1818use rustc_infer:: infer:: { DefineOpaqueTypes , InferOk , TypeTrace } ;
1919use rustc_middle:: ty:: adjustment:: AllowTwoPhase ;
20+ use rustc_middle:: ty:: error:: TypeError ;
2021use rustc_middle:: ty:: visit:: TypeVisitableExt ;
2122use rustc_middle:: ty:: { self , IsSuggestable , Ty , TyCtxt } ;
2223use rustc_middle:: { bug, span_bug} ;
@@ -25,7 +26,7 @@ use rustc_span::symbol::{kw, Ident};
2526use rustc_span:: { sym, Span , DUMMY_SP } ;
2627use rustc_trait_selection:: error_reporting:: infer:: { FailureCode , ObligationCauseExt } ;
2728use rustc_trait_selection:: infer:: InferCtxtExt ;
28- use rustc_trait_selection:: traits:: { self , ObligationCauseCode , SelectionContext } ;
29+ use rustc_trait_selection:: traits:: { self , ObligationCauseCode , ObligationCtxt , SelectionContext } ;
2930use tracing:: debug;
3031use { rustc_ast as ast, rustc_hir as hir} ;
3132
@@ -124,6 +125,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
124125 } ;
125126 if let Err ( guar) = has_error {
126127 let err_inputs = self . err_args ( args_no_rcvr. len ( ) , guar) ;
128+ let err_output = Ty :: new_error ( self . tcx , guar) ;
127129
128130 let err_inputs = match tuple_arguments {
129131 DontTupleArguments => err_inputs,
@@ -134,28 +136,23 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
134136 sp,
135137 expr,
136138 & err_inputs,
137- None ,
139+ err_output,
140+ NoExpectation ,
138141 args_no_rcvr,
139142 false ,
140143 tuple_arguments,
141144 method. ok ( ) . map ( |method| method. def_id ) ,
142145 ) ;
143- return Ty :: new_error ( self . tcx , guar ) ;
146+ return err_output ;
144147 }
145148
146149 let method = method. unwrap ( ) ;
147- // HACK(eddyb) ignore self in the definition (see above).
148- let expected_input_tys = self . expected_inputs_for_expected_output (
149- sp,
150- expected,
151- method. sig . output ( ) ,
152- & method. sig . inputs ( ) [ 1 ..] ,
153- ) ;
154150 self . check_argument_types (
155151 sp,
156152 expr,
157153 & method. sig . inputs ( ) [ 1 ..] ,
158- expected_input_tys,
154+ method. sig . output ( ) ,
155+ expected,
159156 args_no_rcvr,
160157 method. sig . c_variadic ,
161158 tuple_arguments,
@@ -175,8 +172,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
175172 call_expr : & ' tcx hir:: Expr < ' tcx > ,
176173 // Types (as defined in the *signature* of the target function)
177174 formal_input_tys : & [ Ty < ' tcx > ] ,
178- // More specific expected types, after unifying with caller output types
179- expected_input_tys : Option < Vec < Ty < ' tcx > > > ,
175+ formal_output : Ty < ' tcx > ,
176+ // Expected output from the parent expression or statement
177+ expectation : Expectation < ' tcx > ,
180178 // The expressions for each provided argument
181179 provided_args : & ' tcx [ hir:: Expr < ' tcx > ] ,
182180 // Whether the function is variadic, for example when imported from C
@@ -210,6 +208,40 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
210208 ) ;
211209 }
212210
211+ // First, let's unify the formal method signature with the expectation eagerly.
212+ // We use this to guide coercion inference; it's output is "fudged" which means
213+ // any remaining type variables are assigned to new, unrelated variables. This
214+ // is because the inference guidance here is only speculative.
215+ let formal_output = self . resolve_vars_with_obligations ( formal_output) ;
216+ let expected_input_tys: Option < Vec < _ > > = expectation
217+ . only_has_type ( self )
218+ . and_then ( |expected_output| {
219+ self . fudge_inference_if_ok ( || {
220+ let ocx = ObligationCtxt :: new ( self ) ;
221+
222+ // Attempt to apply a subtyping relationship between the formal
223+ // return type (likely containing type variables if the function
224+ // is polymorphic) and the expected return type.
225+ // No argument expectations are produced if unification fails.
226+ let origin = self . misc ( call_span) ;
227+ ocx. sup ( & origin, self . param_env , expected_output, formal_output) ?;
228+ if !ocx. select_where_possible ( ) . is_empty ( ) {
229+ return Err ( TypeError :: Mismatch ) ;
230+ }
231+
232+ // Record all the argument types, with the args
233+ // produced from the above subtyping unification.
234+ Ok ( Some (
235+ formal_input_tys
236+ . iter ( )
237+ . map ( |& ty| self . resolve_vars_if_possible ( ty) )
238+ . collect ( ) ,
239+ ) )
240+ } )
241+ . ok ( )
242+ } )
243+ . unwrap_or_default ( ) ;
244+
213245 let mut err_code = E0061 ;
214246
215247 // If the arguments should be wrapped in a tuple (ex: closures), unwrap them here
@@ -292,21 +324,20 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
292324
293325 let coerce_error =
294326 self . coerce ( provided_arg, checked_ty, coerced_ty, AllowTwoPhase :: Yes , None ) . err ( ) ;
295-
296327 if coerce_error. is_some ( ) {
297328 return Compatibility :: Incompatible ( coerce_error) ;
298329 }
299330
300- // 3. Check if the formal type is a supertype of the checked one
301- // and register any such obligations for future type checks
302- let supertype_error = self . at ( & self . misc ( provided_arg. span ) , self . param_env ) . sup (
331+ // 3. Check if the formal type is actually equal to the checked one
332+ // and register any such obligations for future type checks.
333+ let formal_ty_error = self . at ( & self . misc ( provided_arg. span ) , self . param_env ) . eq (
303334 DefineOpaqueTypes :: Yes ,
304335 formal_input_ty,
305336 coerced_ty,
306337 ) ;
307338
308339 // If neither check failed, the types are compatible
309- match supertype_error {
340+ match formal_ty_error {
310341 Ok ( InferOk { obligations, value : ( ) } ) => {
311342 self . register_predicates ( obligations) ;
312343 Compatibility :: Compatible
0 commit comments