Auto merge of #129317 - compiler-errors:expectation-subtyping, r=lcnr · rust-lang/rust-clippy@bd53aa3 (original) (raw)
`@@ -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 tracing::debug;
`
30
31
`use {rustc_ast as ast, rustc_hir as hir};
`
31
32
``
`@@ -124,6 +125,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
`
124
125
`};
`
125
126
`if let Err(guar) = has_error {
`
126
127
`let err_inputs = self.err_args(args_no_rcvr.len(), guar);
`
``
128
`+
let err_output = Ty::new_error(self.tcx, guar);
`
127
129
``
128
130
`let err_inputs = match tuple_arguments {
`
129
131
`DontTupleArguments => err_inputs,
`
`@@ -134,28 +136,23 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
`
134
136
` sp,
`
135
137
` expr,
`
136
138
`&err_inputs,
`
137
``
`-
None,
`
``
139
`+
err_output,
`
``
140
`+
NoExpectation,
`
138
141
` args_no_rcvr,
`
139
142
`false,
`
140
143
` tuple_arguments,
`
141
144
` method.ok().map(|method| method.def_id),
`
142
145
`);
`
143
``
`-
return Ty::new_error(self.tcx, guar);
`
``
146
`+
return err_output;
`
144
147
`}
`
145
148
``
146
149
`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
``
`-
);
`
154
150
`self.check_argument_types(
`
155
151
` sp,
`
156
152
` expr,
`
157
153
`&method.sig.inputs()[1..],
`
158
``
`-
expected_input_tys,
`
``
154
`+
method.sig.output(),
`
``
155
`+
expected,
`
159
156
` args_no_rcvr,
`
160
157
` method.sig.c_variadic,
`
161
158
` tuple_arguments,
`
`@@ -175,8 +172,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
`
175
172
`call_expr: &'tcx hir::Expr<'tcx>,
`
176
173
`// Types (as defined in the signature of the target function)
`
177
174
`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>,
`
180
178
`// The expressions for each provided argument
`
181
179
`provided_args: &'tcx [hir::Expr<'tcx>],
`
182
180
`// Whether the function is variadic, for example when imported from C
`
`@@ -210,6 +208,40 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
`
210
208
`);
`
211
209
`}
`
212
210
``
``
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
+
213
245
`let mut err_code = E0061;
`
214
246
``
215
247
`// If the arguments should be wrapped in a tuple (ex: closures), unwrap them here
`
`@@ -292,21 +324,20 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
`
292
324
``
293
325
`let coerce_error =
`
294
326
`self.coerce(provided_arg, checked_ty, coerced_ty, AllowTwoPhase::Yes, None).err();
`
295
``
-
296
327
`if coerce_error.is_some() {
`
297
328
`return Compatibility::Incompatible(coerce_error);
`
298
329
`}
`
299
330
``
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(
`
303
334
`DefineOpaqueTypes::Yes,
`
304
335
` formal_input_ty,
`
305
336
` coerced_ty,
`
306
337
`);
`
307
338
``
308
339
`// If neither check failed, the types are compatible
`
309
``
`-
match supertype_error {
`
``
340
`+
match formal_ty_error {
`
310
341
`Ok(InferOk { obligations, value: () }) => {
`
311
342
`self.register_predicates(obligations);
`
312
343
`Compatibility::Compatible
`