@@ -17,6 +17,7 @@ use rustc_hir_analysis::hir_ty_lowering::HirTyLowerer;
17
17
use rustc_index:: IndexVec ;
18
18
use rustc_infer:: infer:: { DefineOpaqueTypes , InferOk , TypeTrace } ;
19
19
use rustc_middle:: ty:: adjustment:: AllowTwoPhase ;
20
+ use rustc_middle:: ty:: error:: TypeError ;
20
21
use rustc_middle:: ty:: visit:: TypeVisitableExt ;
21
22
use rustc_middle:: ty:: { self , IsSuggestable , Ty , TyCtxt } ;
22
23
use rustc_middle:: { bug, span_bug} ;
@@ -25,7 +26,7 @@ use rustc_span::symbol::{kw, Ident};
25
26
use rustc_span:: { sym, Span , DUMMY_SP } ;
26
27
use rustc_trait_selection:: error_reporting:: infer:: { FailureCode , ObligationCauseExt } ;
27
28
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 } ;
29
30
use { rustc_ast as ast, rustc_hir as hir} ;
30
31
31
32
use crate :: coercion:: CoerceMany ;
@@ -123,6 +124,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
123
124
} ;
124
125
if let Err ( guar) = has_error {
125
126
let err_inputs = self . err_args ( args_no_rcvr. len ( ) , guar) ;
127
+ let err_output = Ty :: new_error ( self . tcx , guar) ;
126
128
127
129
let err_inputs = match tuple_arguments {
128
130
DontTupleArguments => err_inputs,
@@ -133,28 +135,23 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
133
135
sp,
134
136
expr,
135
137
& err_inputs,
136
- None ,
138
+ err_output,
139
+ NoExpectation ,
137
140
args_no_rcvr,
138
141
false ,
139
142
tuple_arguments,
140
143
method. ok ( ) . map ( |method| method. def_id ) ,
141
144
) ;
142
- return Ty :: new_error ( self . tcx , guar ) ;
145
+ return err_output ;
143
146
}
144
147
145
148
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
- ) ;
153
149
self . check_argument_types (
154
150
sp,
155
151
expr,
156
152
& method. sig . inputs ( ) [ 1 ..] ,
157
- expected_input_tys,
153
+ method. sig . output ( ) ,
154
+ expected,
158
155
args_no_rcvr,
159
156
method. sig . c_variadic ,
160
157
tuple_arguments,
@@ -174,8 +171,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
174
171
call_expr : & ' tcx hir:: Expr < ' tcx > ,
175
172
// Types (as defined in the *signature* of the target function)
176
173
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 > ,
179
177
// The expressions for each provided argument
180
178
provided_args : & ' tcx [ hir:: Expr < ' tcx > ] ,
181
179
// Whether the function is variadic, for example when imported from C
@@ -209,6 +207,47 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
209
207
) ;
210
208
}
211
209
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
+ //
215
+ // We only do this if the formals have non-region infer vars, since this is only
216
+ // meant to guide inference.
217
+ let formal_output = self . resolve_vars_with_obligations ( formal_output) ;
218
+ let expected_input_tys: Option < Vec < _ > > = if formal_input_tys. has_non_region_infer ( ) {
219
+ expectation
220
+ . only_has_type ( self )
221
+ . and_then ( |expected_output| {
222
+ self . fudge_inference_if_ok ( || {
223
+ let ocx = ObligationCtxt :: new ( self ) ;
224
+
225
+ // Attempt to apply a subtyping relationship between the formal
226
+ // return type (likely containing type variables if the function
227
+ // is polymorphic) and the expected return type.
228
+ // No argument expectations are produced if unification fails.
229
+ let origin = self . misc ( call_span) ;
230
+ ocx. sup ( & origin, self . param_env , expected_output, formal_output) ?;
231
+ if !ocx. select_where_possible ( ) . is_empty ( ) {
232
+ return Err ( TypeError :: Mismatch ) ;
233
+ }
234
+
235
+ // Record all the argument types, with the args
236
+ // produced from the above subtyping unification.
237
+ Ok ( Some (
238
+ formal_input_tys
239
+ . iter ( )
240
+ . map ( |& ty| self . resolve_vars_if_possible ( ty) )
241
+ . collect ( ) ,
242
+ ) )
243
+ } )
244
+ . ok ( )
245
+ } )
246
+ . unwrap_or_default ( )
247
+ } else {
248
+ None
249
+ } ;
250
+
212
251
let mut err_code = E0061 ;
213
252
214
253
// If the arguments should be wrapped in a tuple (ex: closures), unwrap them here
@@ -291,21 +330,20 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
291
330
292
331
let coerce_error =
293
332
self . coerce ( provided_arg, checked_ty, coerced_ty, AllowTwoPhase :: Yes , None ) . err ( ) ;
294
-
295
333
if coerce_error. is_some ( ) {
296
334
return Compatibility :: Incompatible ( coerce_error) ;
297
335
}
298
336
299
- // 3. Check if the formal type is a supertype of the checked one
300
- // and register any such obligations for future type checks
301
- let supertype_error = self . at ( & self . misc ( provided_arg. span ) , self . param_env ) . sup (
337
+ // 3. Check if the formal type is actually equal to the checked one
338
+ // and register any such obligations for future type checks.
339
+ let formal_ty_error = self . at ( & self . misc ( provided_arg. span ) , self . param_env ) . eq (
302
340
DefineOpaqueTypes :: Yes ,
303
341
formal_input_ty,
304
342
coerced_ty,
305
343
) ;
306
344
307
345
// If neither check failed, the types are compatible
308
- match supertype_error {
346
+ match formal_ty_error {
309
347
Ok ( InferOk { obligations, value : ( ) } ) => {
310
348
self . register_predicates ( obligations) ;
311
349
Compatibility :: Compatible
0 commit comments