]>
Commit | Line | Data |
---|---|---|
29967ef6 XL |
1 | use crate::astconv::AstConv; |
2 | use crate::check::coercion::CoerceMany; | |
a2a8927a | 3 | use crate::check::gather_locals::Declaration; |
29967ef6 XL |
4 | use crate::check::method::MethodCallee; |
5 | use crate::check::Expectation::*; | |
6 | use crate::check::TupleArgumentsFlag::*; | |
7 | use crate::check::{ | |
8 | potentially_plural_count, struct_span_err, BreakableCtxt, Diverges, Expectation, FnCtxt, | |
9 | LocalTy, Needs, TupleArgumentsFlag, | |
10 | }; | |
04454e1e | 11 | use crate::structured_errors::StructuredDiagnostic; |
29967ef6 XL |
12 | |
13 | use rustc_ast as ast; | |
c295e0f8 | 14 | use rustc_data_structures::sync::Lrc; |
04454e1e | 15 | use rustc_errors::{Applicability, Diagnostic, DiagnosticId, MultiSpan}; |
29967ef6 | 16 | use rustc_hir as hir; |
136023e0 | 17 | use rustc_hir::def::{CtorOf, DefKind, Res}; |
29967ef6 XL |
18 | use rustc_hir::def_id::DefId; |
19 | use rustc_hir::{ExprKind, Node, QPath}; | |
20 | use rustc_middle::ty::adjustment::AllowTwoPhase; | |
21 | use rustc_middle::ty::fold::TypeFoldable; | |
22 | use rustc_middle::ty::{self, Ty}; | |
23 | use rustc_session::Session; | |
17df50a5 | 24 | use rustc_span::symbol::Ident; |
04454e1e | 25 | use rustc_span::{self, Span}; |
29967ef6 XL |
26 | use rustc_trait_selection::traits::{self, ObligationCauseCode, StatementAsExpression}; |
27 | ||
cdc7bbd5 | 28 | use std::iter; |
29967ef6 XL |
29 | use std::slice; |
30 | ||
04454e1e FG |
31 | enum TupleMatchFound { |
32 | None, | |
33 | Single, | |
34 | /// Beginning and end Span | |
35 | Multiple(Span, Span), | |
5099ac24 | 36 | } |
29967ef6 XL |
37 | impl<'a, 'tcx> FnCtxt<'a, 'tcx> { |
38 | pub(in super::super) fn check_casts(&self) { | |
39 | let mut deferred_cast_checks = self.deferred_cast_checks.borrow_mut(); | |
94222f64 | 40 | debug!("FnCtxt::check_casts: {} deferred checks", deferred_cast_checks.len()); |
29967ef6 XL |
41 | for cast in deferred_cast_checks.drain(..) { |
42 | cast.check(self); | |
43 | } | |
44 | } | |
45 | ||
46 | pub(in super::super) fn check_method_argument_types( | |
47 | &self, | |
48 | sp: Span, | |
49 | expr: &'tcx hir::Expr<'tcx>, | |
50 | method: Result<MethodCallee<'tcx>, ()>, | |
51 | args_no_rcvr: &'tcx [hir::Expr<'tcx>], | |
52 | tuple_arguments: TupleArgumentsFlag, | |
53 | expected: Expectation<'tcx>, | |
54 | ) -> Ty<'tcx> { | |
55 | let has_error = match method { | |
56 | Ok(method) => method.substs.references_error() || method.sig.references_error(), | |
57 | Err(_) => true, | |
58 | }; | |
59 | if has_error { | |
60 | let err_inputs = self.err_args(args_no_rcvr.len()); | |
61 | ||
62 | let err_inputs = match tuple_arguments { | |
63 | DontTupleArguments => err_inputs, | |
a2a8927a | 64 | TupleArguments => vec![self.tcx.intern_tup(&err_inputs)], |
29967ef6 XL |
65 | }; |
66 | ||
67 | self.check_argument_types( | |
68 | sp, | |
69 | expr, | |
a2a8927a XL |
70 | &err_inputs, |
71 | vec![], | |
29967ef6 XL |
72 | args_no_rcvr, |
73 | false, | |
74 | tuple_arguments, | |
75 | None, | |
76 | ); | |
77 | return self.tcx.ty_error(); | |
78 | } | |
79 | ||
80 | let method = method.unwrap(); | |
81 | // HACK(eddyb) ignore self in the definition (see above). | |
a2a8927a | 82 | let expected_input_tys = self.expected_inputs_for_expected_output( |
29967ef6 XL |
83 | sp, |
84 | expected, | |
85 | method.sig.output(), | |
86 | &method.sig.inputs()[1..], | |
87 | ); | |
88 | self.check_argument_types( | |
89 | sp, | |
90 | expr, | |
91 | &method.sig.inputs()[1..], | |
a2a8927a | 92 | expected_input_tys, |
29967ef6 XL |
93 | args_no_rcvr, |
94 | method.sig.c_variadic, | |
95 | tuple_arguments, | |
96 | Some(method.def_id), | |
97 | ); | |
98 | method.sig.output() | |
99 | } | |
100 | ||
101 | /// Generic function that factors out common logic from function calls, | |
102 | /// method calls and overloaded operators. | |
103 | pub(in super::super) fn check_argument_types( | |
104 | &self, | |
a2a8927a XL |
105 | // Span enclosing the call site |
106 | call_span: Span, | |
107 | // Expression of the call site | |
108 | call_expr: &'tcx hir::Expr<'tcx>, | |
109 | // Types (as defined in the *signature* of the target function) | |
110 | formal_input_tys: &[Ty<'tcx>], | |
111 | // More specific expected types, after unifying with caller output types | |
112 | expected_input_tys: Vec<Ty<'tcx>>, | |
113 | // The expressions for each provided argument | |
114 | provided_args: &'tcx [hir::Expr<'tcx>], | |
115 | // Whether the function is variadic, for example when imported from C | |
29967ef6 | 116 | c_variadic: bool, |
a2a8927a | 117 | // Whether the arguments have been bundled in a tuple (ex: closures) |
29967ef6 | 118 | tuple_arguments: TupleArgumentsFlag, |
a2a8927a XL |
119 | // The DefId for the function being called, for better error messages |
120 | fn_def_id: Option<DefId>, | |
29967ef6 XL |
121 | ) { |
122 | let tcx = self.tcx; | |
123 | // Grab the argument types, supplying fresh type variables | |
124 | // if the wrong number of arguments were supplied | |
a2a8927a XL |
125 | let supplied_arg_count = |
126 | if tuple_arguments == DontTupleArguments { provided_args.len() } else { 1 }; | |
29967ef6 XL |
127 | |
128 | // All the input types from the fn signature must outlive the call | |
129 | // so as to validate implied bounds. | |
a2a8927a | 130 | for (&fn_input_ty, arg_expr) in iter::zip(formal_input_tys, provided_args) { |
29967ef6 XL |
131 | self.register_wf_obligation(fn_input_ty.into(), arg_expr.span, traits::MiscObligation); |
132 | } | |
133 | ||
a2a8927a | 134 | let expected_arg_count = formal_input_tys.len(); |
29967ef6 | 135 | |
04454e1e FG |
136 | // expected_count, arg_count, error_code, sugg_tuple_wrap_args |
137 | let mut arg_count_error: Option<(usize, usize, &str, TupleMatchFound)> = None; | |
29967ef6 | 138 | |
5099ac24 | 139 | // If the arguments should be wrapped in a tuple (ex: closures), unwrap them here |
a2a8927a XL |
140 | let (formal_input_tys, expected_input_tys) = if tuple_arguments == TupleArguments { |
141 | let tuple_type = self.structurally_resolved_type(call_span, formal_input_tys[0]); | |
29967ef6 | 142 | match tuple_type.kind() { |
5099ac24 | 143 | // We expected a tuple and got a tuple |
29967ef6 | 144 | ty::Tuple(arg_types) => { |
5099ac24 FG |
145 | // Argument length differs |
146 | if arg_types.len() != provided_args.len() { | |
04454e1e FG |
147 | arg_count_error = Some(( |
148 | arg_types.len(), | |
149 | provided_args.len(), | |
150 | "E0057", | |
151 | TupleMatchFound::None, | |
152 | )); | |
5099ac24 | 153 | } |
a2a8927a | 154 | let expected_input_tys = match expected_input_tys.get(0) { |
29967ef6 | 155 | Some(&ty) => match ty.kind() { |
5e7ed085 | 156 | ty::Tuple(tys) => tys.iter().collect(), |
29967ef6 XL |
157 | _ => vec![], |
158 | }, | |
159 | None => vec![], | |
160 | }; | |
5e7ed085 | 161 | (arg_types.iter().collect(), expected_input_tys) |
29967ef6 XL |
162 | } |
163 | _ => { | |
5099ac24 | 164 | // Otherwise, there's a mismatch, so clear out what we're expecting, and set |
5e7ed085 | 165 | // our input types to err_args so we don't blow up the error messages |
29967ef6 XL |
166 | struct_span_err!( |
167 | tcx.sess, | |
a2a8927a | 168 | call_span, |
29967ef6 XL |
169 | E0059, |
170 | "cannot use call notation; the first type parameter \ | |
171 | for the function trait is neither a tuple nor unit" | |
172 | ) | |
173 | .emit(); | |
a2a8927a | 174 | (self.err_args(provided_args.len()), vec![]) |
29967ef6 XL |
175 | } |
176 | } | |
177 | } else if expected_arg_count == supplied_arg_count { | |
a2a8927a | 178 | (formal_input_tys.to_vec(), expected_input_tys) |
29967ef6 XL |
179 | } else if c_variadic { |
180 | if supplied_arg_count >= expected_arg_count { | |
a2a8927a | 181 | (formal_input_tys.to_vec(), expected_input_tys) |
29967ef6 | 182 | } else { |
5099ac24 | 183 | arg_count_error = |
04454e1e | 184 | Some((expected_arg_count, supplied_arg_count, "E0060", TupleMatchFound::None)); |
a2a8927a | 185 | (self.err_args(supplied_arg_count), vec![]) |
29967ef6 XL |
186 | } |
187 | } else { | |
5099ac24 FG |
188 | // are we passing elements of a tuple without the tuple parentheses? |
189 | let expected_input_tys = if expected_input_tys.is_empty() { | |
190 | // In most cases we can use expected_input_tys, but some callers won't have the type | |
191 | // information, in which case we fall back to the types from the input expressions. | |
192 | formal_input_tys | |
193 | } else { | |
194 | &*expected_input_tys | |
195 | }; | |
196 | ||
197 | let sugg_tuple_wrap_args = self.suggested_tuple_wrap(expected_input_tys, provided_args); | |
198 | ||
04454e1e FG |
199 | arg_count_error = |
200 | Some((expected_arg_count, supplied_arg_count, "E0061", sugg_tuple_wrap_args)); | |
a2a8927a | 201 | (self.err_args(supplied_arg_count), vec![]) |
29967ef6 XL |
202 | }; |
203 | ||
204 | debug!( | |
a2a8927a XL |
205 | "check_argument_types: formal_input_tys={:?}", |
206 | formal_input_tys.iter().map(|t| self.ty_to_string(*t)).collect::<Vec<String>>() | |
29967ef6 XL |
207 | ); |
208 | ||
a2a8927a XL |
209 | // If there is no expectation, expect formal_input_tys. |
210 | let expected_input_tys = if !expected_input_tys.is_empty() { | |
211 | expected_input_tys | |
212 | } else { | |
213 | formal_input_tys.clone() | |
214 | }; | |
29967ef6 | 215 | |
a2a8927a XL |
216 | assert_eq!(expected_input_tys.len(), formal_input_tys.len()); |
217 | ||
5099ac24 FG |
218 | let provided_arg_count: usize = provided_args.len(); |
219 | ||
a2a8927a | 220 | // Keep track of the fully coerced argument types |
5099ac24 | 221 | let mut final_arg_types: Vec<Option<(Ty<'_>, Ty<'_>)>> = vec![None; provided_arg_count]; |
29967ef6 | 222 | |
a2a8927a XL |
223 | // We introduce a helper function to demand that a given argument satisfy a given input |
224 | // This is more complicated than just checking type equality, as arguments could be coerced | |
225 | // This version writes those types back so further type checking uses the narrowed types | |
5099ac24 | 226 | let demand_compatible = |idx, final_arg_types: &mut Vec<Option<(Ty<'tcx>, Ty<'tcx>)>>| { |
a2a8927a XL |
227 | let formal_input_ty: Ty<'tcx> = formal_input_tys[idx]; |
228 | let expected_input_ty: Ty<'tcx> = expected_input_tys[idx]; | |
229 | let provided_arg = &provided_args[idx]; | |
230 | ||
231 | debug!("checking argument {}: {:?} = {:?}", idx, provided_arg, formal_input_ty); | |
232 | ||
233 | // The special-cased logic below has three functions: | |
234 | // 1. Provide as good of an expected type as possible. | |
235 | let expectation = Expectation::rvalue_hint(self, expected_input_ty); | |
236 | ||
237 | let checked_ty = self.check_expr_with_expectation(provided_arg, expectation); | |
238 | ||
239 | // 2. Coerce to the most detailed type that could be coerced | |
240 | // to, which is `expected_ty` if `rvalue_hint` returns an | |
241 | // `ExpectHasType(expected_ty)`, or the `formal_ty` otherwise. | |
242 | let coerced_ty = expectation.only_has_type(self).unwrap_or(formal_input_ty); | |
243 | ||
244 | // Keep track of these for below | |
5099ac24 | 245 | final_arg_types[idx] = Some((checked_ty, coerced_ty)); |
a2a8927a XL |
246 | |
247 | // Cause selection errors caused by resolving a single argument to point at the | |
248 | // argument and not the call. This is otherwise redundant with the `demand_coerce` | |
249 | // call immediately after, but it lets us customize the span pointed to in the | |
250 | // fulfillment error to be more accurate. | |
5099ac24 | 251 | let coerced_ty = |
a2a8927a XL |
252 | self.resolve_vars_with_obligations_and_mutate_fulfillment(coerced_ty, |errors| { |
253 | self.point_at_type_arg_instead_of_call_if_possible(errors, call_expr); | |
254 | self.point_at_arg_instead_of_call_if_possible( | |
255 | errors, | |
256 | &final_arg_types, | |
257 | call_expr, | |
258 | call_span, | |
259 | provided_args, | |
260 | ); | |
261 | }); | |
262 | ||
5099ac24 FG |
263 | final_arg_types[idx] = Some((checked_ty, coerced_ty)); |
264 | ||
a2a8927a XL |
265 | // We're processing function arguments so we definitely want to use |
266 | // two-phase borrows. | |
267 | self.demand_coerce(&provided_arg, checked_ty, coerced_ty, None, AllowTwoPhase::Yes); | |
268 | ||
269 | // 3. Relate the expected type and the formal one, | |
270 | // if the expected type was used for the coercion. | |
271 | self.demand_suptype(provided_arg.span, formal_input_ty, coerced_ty); | |
272 | }; | |
273 | ||
5e7ed085 FG |
274 | let minimum_input_count = formal_input_tys.len(); |
275 | ||
29967ef6 XL |
276 | // Check the arguments. |
277 | // We do this in a pretty awful way: first we type-check any arguments | |
278 | // that are not closures, then we type-check the closures. This is so | |
279 | // that we have more information about the types of arguments when we | |
280 | // type-check the functions. This isn't really the right way to do this. | |
136023e0 | 281 | for check_closures in [false, true] { |
29967ef6 XL |
282 | // More awful hacks: before we check argument types, try to do |
283 | // an "opportunistic" trait resolution of any trait bounds on | |
284 | // the call. This helps coercions. | |
285 | if check_closures { | |
286 | self.select_obligations_where_possible(false, |errors| { | |
a2a8927a | 287 | self.point_at_type_arg_instead_of_call_if_possible(errors, call_expr); |
29967ef6 XL |
288 | self.point_at_arg_instead_of_call_if_possible( |
289 | errors, | |
a2a8927a XL |
290 | &final_arg_types, |
291 | call_expr, | |
292 | call_span, | |
293 | &provided_args, | |
29967ef6 XL |
294 | ); |
295 | }) | |
296 | } | |
297 | ||
a2a8927a | 298 | for (idx, arg) in provided_args.iter().enumerate() { |
29967ef6 XL |
299 | // Warn only for the first loop (the "no closures" one). |
300 | // Closure arguments themselves can't be diverging, but | |
301 | // a previous argument can, e.g., `foo(panic!(), || {})`. | |
302 | if !check_closures { | |
303 | self.warn_if_unreachable(arg.hir_id, arg.span, "expression"); | |
304 | } | |
305 | ||
a2a8927a XL |
306 | // For C-variadic functions, we don't have a declared type for all of |
307 | // the arguments hence we only do our usual type checking with | |
308 | // the arguments who's types we do know. However, we *can* check | |
309 | // for unreachable expressions (see above). | |
310 | // FIXME: unreachable warning current isn't emitted | |
311 | if idx >= minimum_input_count { | |
312 | continue; | |
313 | } | |
29967ef6 | 314 | |
a2a8927a | 315 | let is_closure = matches!(arg.kind, ExprKind::Closure(..)); |
29967ef6 XL |
316 | if is_closure != check_closures { |
317 | continue; | |
318 | } | |
319 | ||
a2a8927a | 320 | demand_compatible(idx, &mut final_arg_types); |
29967ef6 XL |
321 | } |
322 | } | |
323 | ||
5099ac24 | 324 | // If there was an error in parameter count, emit that here |
04454e1e | 325 | if let Some((expected_count, arg_count, err_code, sugg_tuple_wrap_args)) = arg_count_error { |
5099ac24 FG |
326 | let (span, start_span, args, ctor_of) = match &call_expr.kind { |
327 | hir::ExprKind::Call( | |
328 | hir::Expr { | |
329 | span, | |
330 | kind: | |
331 | hir::ExprKind::Path(hir::QPath::Resolved( | |
332 | _, | |
333 | hir::Path { res: Res::Def(DefKind::Ctor(of, _), _), .. }, | |
334 | )), | |
335 | .. | |
336 | }, | |
337 | args, | |
338 | ) => (*span, *span, &args[..], Some(of)), | |
339 | hir::ExprKind::Call(hir::Expr { span, .. }, args) => { | |
340 | (*span, *span, &args[..], None) | |
341 | } | |
342 | hir::ExprKind::MethodCall(path_segment, args, _) => ( | |
343 | path_segment.ident.span, | |
344 | // `sp` doesn't point at the whole `foo.bar()`, only at `bar`. | |
345 | path_segment | |
346 | .args | |
347 | .and_then(|args| args.args.iter().last()) | |
348 | // Account for `foo.bar::<T>()`. | |
349 | .map(|arg| { | |
350 | // Skip the closing `>`. | |
351 | tcx.sess | |
352 | .source_map() | |
353 | .next_point(tcx.sess.source_map().next_point(arg.span())) | |
354 | }) | |
355 | .unwrap_or(path_segment.ident.span), | |
356 | &args[1..], // Skip the receiver. | |
357 | None, // methods are never ctors | |
358 | ), | |
359 | k => span_bug!(call_span, "checking argument types on a non-call: `{:?}`", k), | |
360 | }; | |
361 | let arg_spans = if provided_args.is_empty() { | |
362 | // foo() | |
363 | // ^^^-- supplied 0 arguments | |
364 | // | | |
365 | // expected 2 arguments | |
366 | vec![tcx.sess.source_map().next_point(start_span).with_hi(call_span.hi())] | |
367 | } else { | |
368 | // foo(1, 2, 3) | |
369 | // ^^^ - - - supplied 3 arguments | |
370 | // | | |
371 | // expected 2 arguments | |
372 | args.iter().map(|arg| arg.span).collect::<Vec<Span>>() | |
373 | }; | |
374 | let call_name = match ctor_of { | |
375 | Some(CtorOf::Struct) => "struct", | |
376 | Some(CtorOf::Variant) => "enum variant", | |
377 | None => "function", | |
378 | }; | |
379 | let mut err = tcx.sess.struct_span_err_with_code( | |
380 | span, | |
381 | &format!( | |
382 | "this {} takes {}{} but {} {} supplied", | |
383 | call_name, | |
384 | if c_variadic { "at least " } else { "" }, | |
385 | potentially_plural_count(expected_count, "argument"), | |
386 | potentially_plural_count(arg_count, "argument"), | |
387 | if arg_count == 1 { "was" } else { "were" } | |
388 | ), | |
389 | DiagnosticId::Error(err_code.to_owned()), | |
390 | ); | |
391 | let label = format!("supplied {}", potentially_plural_count(arg_count, "argument")); | |
392 | for (i, span) in arg_spans.into_iter().enumerate() { | |
393 | err.span_label( | |
394 | span, | |
395 | if arg_count == 0 || i + 1 == arg_count { &label } else { "" }, | |
396 | ); | |
397 | } | |
5e7ed085 FG |
398 | if let Some(def_id) = fn_def_id && let Some(def_span) = tcx.def_ident_span(def_id) { |
399 | let mut spans: MultiSpan = def_span.into(); | |
400 | ||
401 | let params = tcx | |
402 | .hir() | |
403 | .get_if_local(def_id) | |
404 | .and_then(|node| node.body_id()) | |
405 | .into_iter() | |
406 | .map(|id| tcx.hir().body(id).params) | |
407 | .flatten(); | |
408 | ||
409 | for param in params { | |
410 | spans.push_span_label(param.span, String::new()); | |
5099ac24 | 411 | } |
5e7ed085 FG |
412 | |
413 | let def_kind = tcx.def_kind(def_id); | |
414 | err.span_note(spans, &format!("{} defined here", def_kind.descr(def_id))); | |
5099ac24 | 415 | } |
04454e1e FG |
416 | match sugg_tuple_wrap_args { |
417 | TupleMatchFound::Single => { | |
418 | let sugg_span = tcx.sess.source_map().end_point(call_expr.span); | |
419 | // remove closing `)` from the span | |
420 | let sugg_span = sugg_span.shrink_to_lo(); | |
421 | err.span_suggestion( | |
422 | sugg_span, | |
423 | "expected the unit value `()`; create it with empty parentheses", | |
424 | String::from("()"), | |
425 | Applicability::MachineApplicable, | |
426 | ); | |
427 | } | |
428 | TupleMatchFound::Multiple(first, last) => { | |
429 | err.multipart_suggestion( | |
430 | "use parentheses to construct a tuple", | |
431 | vec![ | |
432 | (first.shrink_to_lo(), '('.to_string()), | |
433 | (last.shrink_to_hi(), ')'.to_string()), | |
434 | ], | |
435 | Applicability::MachineApplicable, | |
436 | ); | |
437 | } | |
438 | _ => { | |
439 | err.span_label( | |
440 | span, | |
441 | format!( | |
442 | "expected {}{}", | |
443 | if c_variadic { "at least " } else { "" }, | |
444 | potentially_plural_count(expected_count, "argument") | |
445 | ), | |
446 | ); | |
447 | } | |
5099ac24 FG |
448 | } |
449 | err.emit(); | |
450 | } | |
451 | ||
5e7ed085 FG |
452 | for arg in provided_args.iter().skip(minimum_input_count) { |
453 | let arg_ty = self.check_expr(&arg); | |
5869c6ff | 454 | |
5e7ed085 FG |
455 | if c_variadic { |
456 | // We also need to make sure we at least write the ty of the other | |
457 | // arguments which we skipped above, either because they were additional | |
458 | // c_variadic args, or because we had an argument count mismatch. | |
04454e1e | 459 | fn variadic_error<'tcx>(sess: &'tcx Session, span: Span, ty: Ty<'tcx>, cast_ty: &str) { |
5e7ed085 | 460 | use crate::structured_errors::MissingCastForVariadicArg; |
29967ef6 | 461 | |
5e7ed085 FG |
462 | MissingCastForVariadicArg { sess, span, ty, cast_ty }.diagnostic().emit(); |
463 | } | |
29967ef6 XL |
464 | |
465 | // There are a few types which get autopromoted when passed via varargs | |
466 | // in C but we just error out instead and require explicit casts. | |
467 | let arg_ty = self.structurally_resolved_type(arg.span, arg_ty); | |
468 | match arg_ty.kind() { | |
5869c6ff | 469 | ty::Float(ty::FloatTy::F32) => { |
29967ef6 XL |
470 | variadic_error(tcx.sess, arg.span, arg_ty, "c_double"); |
471 | } | |
5869c6ff | 472 | ty::Int(ty::IntTy::I8 | ty::IntTy::I16) | ty::Bool => { |
29967ef6 XL |
473 | variadic_error(tcx.sess, arg.span, arg_ty, "c_int"); |
474 | } | |
5869c6ff | 475 | ty::Uint(ty::UintTy::U8 | ty::UintTy::U16) => { |
29967ef6 XL |
476 | variadic_error(tcx.sess, arg.span, arg_ty, "c_uint"); |
477 | } | |
478 | ty::FnDef(..) => { | |
479 | let ptr_ty = self.tcx.mk_fn_ptr(arg_ty.fn_sig(self.tcx)); | |
fc512014 | 480 | let ptr_ty = self.resolve_vars_if_possible(ptr_ty); |
29967ef6 XL |
481 | variadic_error(tcx.sess, arg.span, arg_ty, &ptr_ty.to_string()); |
482 | } | |
483 | _ => {} | |
484 | } | |
485 | } | |
486 | } | |
487 | } | |
488 | ||
5099ac24 FG |
489 | fn suggested_tuple_wrap( |
490 | &self, | |
491 | expected_input_tys: &[Ty<'tcx>], | |
492 | provided_args: &'tcx [hir::Expr<'tcx>], | |
04454e1e FG |
493 | ) -> TupleMatchFound { |
494 | // Only handle the case where we expect only one tuple arg | |
495 | let [expected_arg_type] = expected_input_tys[..] else { return TupleMatchFound::None }; | |
5e7ed085 | 496 | let &ty::Tuple(expected_types) = self.resolve_vars_if_possible(expected_arg_type).kind() |
04454e1e FG |
497 | else { return TupleMatchFound::None }; |
498 | ||
499 | // First check that there are the same number of types. | |
500 | if expected_types.len() != provided_args.len() { | |
501 | return TupleMatchFound::None; | |
502 | } | |
5099ac24 | 503 | |
5099ac24 FG |
504 | let supplied_types: Vec<_> = provided_args.iter().map(|arg| self.check_expr(arg)).collect(); |
505 | ||
506 | let all_match = iter::zip(expected_types, supplied_types) | |
507 | .all(|(expected, supplied)| self.can_eq(self.param_env, expected, supplied).is_ok()); | |
508 | ||
04454e1e FG |
509 | if !all_match { |
510 | return TupleMatchFound::None; | |
511 | } | |
512 | match provided_args { | |
513 | [] => TupleMatchFound::None, | |
514 | [_] => TupleMatchFound::Single, | |
515 | [first, .., last] => { | |
516 | TupleMatchFound::Multiple(first.span.shrink_to_lo(), last.span.shrink_to_hi()) | |
5099ac24 | 517 | } |
5099ac24 FG |
518 | } |
519 | } | |
520 | ||
29967ef6 XL |
521 | // AST fragment checking |
522 | pub(in super::super) fn check_lit( | |
523 | &self, | |
524 | lit: &hir::Lit, | |
525 | expected: Expectation<'tcx>, | |
526 | ) -> Ty<'tcx> { | |
527 | let tcx = self.tcx; | |
528 | ||
529 | match lit.node { | |
530 | ast::LitKind::Str(..) => tcx.mk_static_str(), | |
531 | ast::LitKind::ByteStr(ref v) => { | |
532 | tcx.mk_imm_ref(tcx.lifetimes.re_static, tcx.mk_array(tcx.types.u8, v.len() as u64)) | |
533 | } | |
534 | ast::LitKind::Byte(_) => tcx.types.u8, | |
535 | ast::LitKind::Char(_) => tcx.types.char, | |
5869c6ff XL |
536 | ast::LitKind::Int(_, ast::LitIntType::Signed(t)) => tcx.mk_mach_int(ty::int_ty(t)), |
537 | ast::LitKind::Int(_, ast::LitIntType::Unsigned(t)) => tcx.mk_mach_uint(ty::uint_ty(t)), | |
29967ef6 XL |
538 | ast::LitKind::Int(_, ast::LitIntType::Unsuffixed) => { |
539 | let opt_ty = expected.to_option(self).and_then(|ty| match ty.kind() { | |
540 | ty::Int(_) | ty::Uint(_) => Some(ty), | |
541 | ty::Char => Some(tcx.types.u8), | |
542 | ty::RawPtr(..) => Some(tcx.types.usize), | |
543 | ty::FnDef(..) | ty::FnPtr(_) => Some(tcx.types.usize), | |
544 | _ => None, | |
545 | }); | |
546 | opt_ty.unwrap_or_else(|| self.next_int_var()) | |
547 | } | |
5869c6ff XL |
548 | ast::LitKind::Float(_, ast::LitFloatType::Suffixed(t)) => { |
549 | tcx.mk_mach_float(ty::float_ty(t)) | |
550 | } | |
29967ef6 XL |
551 | ast::LitKind::Float(_, ast::LitFloatType::Unsuffixed) => { |
552 | let opt_ty = expected.to_option(self).and_then(|ty| match ty.kind() { | |
553 | ty::Float(_) => Some(ty), | |
554 | _ => None, | |
555 | }); | |
556 | opt_ty.unwrap_or_else(|| self.next_float_var()) | |
557 | } | |
558 | ast::LitKind::Bool(_) => tcx.types.bool, | |
559 | ast::LitKind::Err(_) => tcx.ty_error(), | |
560 | } | |
561 | } | |
562 | ||
563 | pub fn check_struct_path( | |
564 | &self, | |
565 | qpath: &QPath<'_>, | |
566 | hir_id: hir::HirId, | |
567 | ) -> Option<(&'tcx ty::VariantDef, Ty<'tcx>)> { | |
6a06907d | 568 | let path_span = qpath.span(); |
29967ef6 XL |
569 | let (def, ty) = self.finish_resolving_struct_path(qpath, path_span, hir_id); |
570 | let variant = match def { | |
571 | Res::Err => { | |
572 | self.set_tainted_by_errors(); | |
573 | return None; | |
574 | } | |
575 | Res::Def(DefKind::Variant, _) => match ty.kind() { | |
5e7ed085 | 576 | ty::Adt(adt, substs) => Some((adt.variant_of_res(def), adt.did(), substs)), |
29967ef6 XL |
577 | _ => bug!("unexpected type: {:?}", ty), |
578 | }, | |
579 | Res::Def(DefKind::Struct | DefKind::Union | DefKind::TyAlias | DefKind::AssocTy, _) | |
5099ac24 | 580 | | Res::SelfTy { .. } => match ty.kind() { |
29967ef6 | 581 | ty::Adt(adt, substs) if !adt.is_enum() => { |
5e7ed085 | 582 | Some((adt.non_enum_variant(), adt.did(), substs)) |
29967ef6 XL |
583 | } |
584 | _ => None, | |
585 | }, | |
586 | _ => bug!("unexpected definition: {:?}", def), | |
587 | }; | |
588 | ||
589 | if let Some((variant, did, substs)) = variant { | |
590 | debug!("check_struct_path: did={:?} substs={:?}", did, substs); | |
591 | self.write_user_type_annotation_from_substs(hir_id, did, substs, None); | |
592 | ||
593 | // Check bounds on type arguments used in the path. | |
3c0e092e | 594 | self.add_required_obligations(path_span, did, substs); |
29967ef6 XL |
595 | |
596 | Some((variant, ty)) | |
597 | } else { | |
c295e0f8 XL |
598 | match ty.kind() { |
599 | ty::Error(_) => { | |
600 | // E0071 might be caused by a spelling error, which will have | |
601 | // already caused an error message and probably a suggestion | |
602 | // elsewhere. Refrain from emitting more unhelpful errors here | |
603 | // (issue #88844). | |
604 | } | |
605 | _ => { | |
606 | struct_span_err!( | |
607 | self.tcx.sess, | |
608 | path_span, | |
609 | E0071, | |
610 | "expected struct, variant or union type, found {}", | |
611 | ty.sort_string(self.tcx) | |
612 | ) | |
613 | .span_label(path_span, "not a struct") | |
614 | .emit(); | |
615 | } | |
616 | } | |
29967ef6 XL |
617 | None |
618 | } | |
619 | } | |
620 | ||
621 | pub fn check_decl_initializer( | |
622 | &self, | |
a2a8927a XL |
623 | hir_id: hir::HirId, |
624 | pat: &'tcx hir::Pat<'tcx>, | |
29967ef6 XL |
625 | init: &'tcx hir::Expr<'tcx>, |
626 | ) -> Ty<'tcx> { | |
627 | // FIXME(tschottdorf): `contains_explicit_ref_binding()` must be removed | |
628 | // for #42640 (default match binding modes). | |
629 | // | |
630 | // See #44848. | |
a2a8927a | 631 | let ref_bindings = pat.contains_explicit_ref_binding(); |
29967ef6 | 632 | |
a2a8927a | 633 | let local_ty = self.local_ty(init.span, hir_id).revealed_ty; |
29967ef6 XL |
634 | if let Some(m) = ref_bindings { |
635 | // Somewhat subtle: if we have a `ref` binding in the pattern, | |
636 | // we want to avoid introducing coercions for the RHS. This is | |
637 | // both because it helps preserve sanity and, in the case of | |
638 | // ref mut, for soundness (issue #23116). In particular, in | |
639 | // the latter case, we need to be clear that the type of the | |
640 | // referent for the reference that results is *equal to* the | |
641 | // type of the place it is referencing, and not some | |
642 | // supertype thereof. | |
643 | let init_ty = self.check_expr_with_needs(init, Needs::maybe_mut_place(m)); | |
644 | self.demand_eqtype(init.span, local_ty, init_ty); | |
645 | init_ty | |
646 | } else { | |
647 | self.check_expr_coercable_to_type(init, local_ty, None) | |
648 | } | |
649 | } | |
650 | ||
a2a8927a | 651 | pub(in super::super) fn check_decl(&self, decl: Declaration<'tcx>) { |
29967ef6 | 652 | // Determine and write the type which we'll check the pattern against. |
a2a8927a XL |
653 | let decl_ty = self.local_ty(decl.span, decl.hir_id).decl_ty; |
654 | self.write_ty(decl.hir_id, decl_ty); | |
29967ef6 XL |
655 | |
656 | // Type check the initializer. | |
a2a8927a XL |
657 | if let Some(ref init) = decl.init { |
658 | let init_ty = self.check_decl_initializer(decl.hir_id, decl.pat, &init); | |
659 | self.overwrite_local_ty_if_err(decl.hir_id, decl.pat, decl_ty, init_ty); | |
29967ef6 XL |
660 | } |
661 | ||
662 | // Does the expected pattern type originate from an expression and what is the span? | |
a2a8927a | 663 | let (origin_expr, ty_span) = match (decl.ty, decl.init) { |
29967ef6 XL |
664 | (Some(ty), _) => (false, Some(ty.span)), // Bias towards the explicit user type. |
665 | (_, Some(init)) => (true, Some(init.span)), // No explicit type; so use the scrutinee. | |
666 | _ => (false, None), // We have `let $pat;`, so the expected type is unconstrained. | |
667 | }; | |
668 | ||
669 | // Type check the pattern. Override if necessary to avoid knock-on errors. | |
a2a8927a XL |
670 | self.check_pat_top(&decl.pat, decl_ty, ty_span, origin_expr); |
671 | let pat_ty = self.node_ty(decl.pat.hir_id); | |
672 | self.overwrite_local_ty_if_err(decl.hir_id, decl.pat, decl_ty, pat_ty); | |
673 | } | |
674 | ||
675 | /// Type check a `let` statement. | |
676 | pub fn check_decl_local(&self, local: &'tcx hir::Local<'tcx>) { | |
677 | self.check_decl(local.into()); | |
29967ef6 XL |
678 | } |
679 | ||
6a06907d | 680 | pub fn check_stmt(&self, stmt: &'tcx hir::Stmt<'tcx>, is_last: bool) { |
29967ef6 XL |
681 | // Don't do all the complex logic below for `DeclItem`. |
682 | match stmt.kind { | |
683 | hir::StmtKind::Item(..) => return, | |
684 | hir::StmtKind::Local(..) | hir::StmtKind::Expr(..) | hir::StmtKind::Semi(..) => {} | |
685 | } | |
686 | ||
687 | self.warn_if_unreachable(stmt.hir_id, stmt.span, "statement"); | |
688 | ||
689 | // Hide the outer diverging and `has_errors` flags. | |
690 | let old_diverges = self.diverges.replace(Diverges::Maybe); | |
691 | let old_has_errors = self.has_errors.replace(false); | |
692 | ||
693 | match stmt.kind { | |
694 | hir::StmtKind::Local(ref l) => { | |
695 | self.check_decl_local(&l); | |
696 | } | |
697 | // Ignore for now. | |
698 | hir::StmtKind::Item(_) => {} | |
699 | hir::StmtKind::Expr(ref expr) => { | |
700 | // Check with expected type of `()`. | |
701 | self.check_expr_has_type_or_error(&expr, self.tcx.mk_unit(), |err| { | |
6a06907d XL |
702 | if expr.can_have_side_effects() { |
703 | self.suggest_semicolon_at_end(expr.span, err); | |
704 | } | |
29967ef6 XL |
705 | }); |
706 | } | |
707 | hir::StmtKind::Semi(ref expr) => { | |
6a06907d XL |
708 | // All of this is equivalent to calling `check_expr`, but it is inlined out here |
709 | // in order to capture the fact that this `match` is the last statement in its | |
710 | // function. This is done for better suggestions to remove the `;`. | |
711 | let expectation = match expr.kind { | |
712 | hir::ExprKind::Match(..) if is_last => IsLast(stmt.span), | |
713 | _ => NoExpectation, | |
714 | }; | |
715 | self.check_expr_with_expectation(expr, expectation); | |
29967ef6 XL |
716 | } |
717 | } | |
718 | ||
719 | // Combine the diverging and `has_error` flags. | |
720 | self.diverges.set(self.diverges.get() | old_diverges); | |
721 | self.has_errors.set(self.has_errors.get() | old_has_errors); | |
722 | } | |
723 | ||
724 | pub fn check_block_no_value(&self, blk: &'tcx hir::Block<'tcx>) { | |
725 | let unit = self.tcx.mk_unit(); | |
726 | let ty = self.check_block_with_expected(blk, ExpectHasType(unit)); | |
727 | ||
728 | // if the block produces a `!` value, that can always be | |
729 | // (effectively) coerced to unit. | |
730 | if !ty.is_never() { | |
731 | self.demand_suptype(blk.span, unit, ty); | |
732 | } | |
733 | } | |
734 | ||
735 | pub(in super::super) fn check_block_with_expected( | |
736 | &self, | |
737 | blk: &'tcx hir::Block<'tcx>, | |
738 | expected: Expectation<'tcx>, | |
739 | ) -> Ty<'tcx> { | |
5869c6ff | 740 | let prev = self.ps.replace(self.ps.get().recurse(blk)); |
29967ef6 XL |
741 | |
742 | // In some cases, blocks have just one exit, but other blocks | |
743 | // can be targeted by multiple breaks. This can happen both | |
744 | // with labeled blocks as well as when we desugar | |
745 | // a `try { ... }` expression. | |
746 | // | |
747 | // Example 1: | |
748 | // | |
749 | // 'a: { if true { break 'a Err(()); } Ok(()) } | |
750 | // | |
751 | // Here we would wind up with two coercions, one from | |
752 | // `Err(())` and the other from the tail expression | |
753 | // `Ok(())`. If the tail expression is omitted, that's a | |
754 | // "forced unit" -- unless the block diverges, in which | |
755 | // case we can ignore the tail expression (e.g., `'a: { | |
756 | // break 'a 22; }` would not force the type of the block | |
757 | // to be `()`). | |
758 | let tail_expr = blk.expr.as_ref(); | |
759 | let coerce_to_ty = expected.coercion_target_type(self, blk.span); | |
760 | let coerce = if blk.targeted_by_break { | |
761 | CoerceMany::new(coerce_to_ty) | |
762 | } else { | |
763 | let tail_expr: &[&hir::Expr<'_>] = match tail_expr { | |
764 | Some(e) => slice::from_ref(e), | |
765 | None => &[], | |
766 | }; | |
767 | CoerceMany::with_coercion_sites(coerce_to_ty, tail_expr) | |
768 | }; | |
769 | ||
770 | let prev_diverges = self.diverges.get(); | |
771 | let ctxt = BreakableCtxt { coerce: Some(coerce), may_break: false }; | |
772 | ||
773 | let (ctxt, ()) = self.with_breakable_ctxt(blk.hir_id, ctxt, || { | |
6a06907d XL |
774 | for (pos, s) in blk.stmts.iter().enumerate() { |
775 | self.check_stmt(s, blk.stmts.len() - 1 == pos); | |
29967ef6 XL |
776 | } |
777 | ||
778 | // check the tail expression **without** holding the | |
779 | // `enclosing_breakables` lock below. | |
780 | let tail_expr_ty = tail_expr.map(|t| self.check_expr_with_expectation(t, expected)); | |
781 | ||
782 | let mut enclosing_breakables = self.enclosing_breakables.borrow_mut(); | |
783 | let ctxt = enclosing_breakables.find_breakable(blk.hir_id); | |
784 | let coerce = ctxt.coerce.as_mut().unwrap(); | |
785 | if let Some(tail_expr_ty) = tail_expr_ty { | |
786 | let tail_expr = tail_expr.unwrap(); | |
787 | let span = self.get_expr_coercion_span(tail_expr); | |
788 | let cause = self.cause(span, ObligationCauseCode::BlockTailExpression(blk.hir_id)); | |
5e7ed085 FG |
789 | let ty_for_diagnostic = coerce.merged_ty(); |
790 | // We use coerce_inner here because we want to augment the error | |
791 | // suggesting to wrap the block in square brackets if it might've | |
792 | // been mistaken array syntax | |
793 | coerce.coerce_inner( | |
794 | self, | |
795 | &cause, | |
796 | Some(tail_expr), | |
797 | tail_expr_ty, | |
798 | Some(&mut |diag: &mut Diagnostic| { | |
799 | self.suggest_block_to_brackets(diag, blk, tail_expr_ty, ty_for_diagnostic); | |
800 | }), | |
801 | false, | |
802 | ); | |
29967ef6 XL |
803 | } else { |
804 | // Subtle: if there is no explicit tail expression, | |
805 | // that is typically equivalent to a tail expression | |
806 | // of `()` -- except if the block diverges. In that | |
807 | // case, there is no value supplied from the tail | |
808 | // expression (assuming there are no other breaks, | |
809 | // this implies that the type of the block will be | |
810 | // `!`). | |
811 | // | |
812 | // #41425 -- label the implicit `()` as being the | |
813 | // "found type" here, rather than the "expected type". | |
814 | if !self.diverges.get().is_always() { | |
815 | // #50009 -- Do not point at the entire fn block span, point at the return type | |
816 | // span, as it is the cause of the requirement, and | |
817 | // `consider_hint_about_removing_semicolon` will point at the last expression | |
818 | // if it were a relevant part of the error. This improves usability in editors | |
819 | // that highlight errors inline. | |
820 | let mut sp = blk.span; | |
821 | let mut fn_span = None; | |
822 | if let Some((decl, ident)) = self.get_parent_fn_decl(blk.hir_id) { | |
823 | let ret_sp = decl.output.span(); | |
824 | if let Some(block_sp) = self.parent_item_span(blk.hir_id) { | |
825 | // HACK: on some cases (`ui/liveness/liveness-issue-2163.rs`) the | |
826 | // output would otherwise be incorrect and even misleading. Make sure | |
827 | // the span we're aiming at correspond to a `fn` body. | |
828 | if block_sp == blk.span { | |
829 | sp = ret_sp; | |
830 | fn_span = Some(ident.span); | |
831 | } | |
832 | } | |
833 | } | |
834 | coerce.coerce_forced_unit( | |
835 | self, | |
836 | &self.misc(sp), | |
837 | &mut |err| { | |
838 | if let Some(expected_ty) = expected.only_has_type(self) { | |
839 | self.consider_hint_about_removing_semicolon(blk, expected_ty, err); | |
3c0e092e XL |
840 | if expected_ty == self.tcx.types.bool { |
841 | // If this is caused by a missing `let` in a `while let`, | |
842 | // silence this redundant error, as we already emit E0070. | |
5e7ed085 FG |
843 | |
844 | // Our block must be a `assign desugar local; assignment` | |
845 | if let Some(hir::Node::Block(hir::Block { | |
846 | stmts: | |
847 | [ | |
848 | hir::Stmt { | |
849 | kind: | |
850 | hir::StmtKind::Local(hir::Local { | |
851 | source: | |
852 | hir::LocalSource::AssignDesugar(_), | |
853 | .. | |
854 | }), | |
855 | .. | |
856 | }, | |
857 | hir::Stmt { | |
858 | kind: | |
859 | hir::StmtKind::Expr(hir::Expr { | |
860 | kind: hir::ExprKind::Assign(..), | |
861 | .. | |
862 | }), | |
863 | .. | |
864 | }, | |
865 | ], | |
866 | .. | |
867 | })) = self.tcx.hir().find(blk.hir_id) | |
868 | { | |
869 | self.comes_from_while_condition(blk.hir_id, |_| { | |
870 | err.downgrade_to_delayed_bug(); | |
871 | }) | |
3c0e092e XL |
872 | } |
873 | } | |
29967ef6 XL |
874 | } |
875 | if let Some(fn_span) = fn_span { | |
876 | err.span_label( | |
877 | fn_span, | |
878 | "implicitly returns `()` as its body has no tail or `return` \ | |
879 | expression", | |
880 | ); | |
881 | } | |
882 | }, | |
883 | false, | |
884 | ); | |
885 | } | |
886 | } | |
887 | }); | |
888 | ||
889 | if ctxt.may_break { | |
890 | // If we can break from the block, then the block's exit is always reachable | |
891 | // (... as long as the entry is reachable) - regardless of the tail of the block. | |
892 | self.diverges.set(prev_diverges); | |
893 | } | |
894 | ||
895 | let mut ty = ctxt.coerce.unwrap().complete(self); | |
896 | ||
897 | if self.has_errors.get() || ty.references_error() { | |
898 | ty = self.tcx.ty_error() | |
899 | } | |
900 | ||
901 | self.write_ty(blk.hir_id, ty); | |
902 | ||
5869c6ff | 903 | self.ps.set(prev); |
29967ef6 XL |
904 | ty |
905 | } | |
906 | ||
29967ef6 XL |
907 | /// A common error is to add an extra semicolon: |
908 | /// | |
04454e1e | 909 | /// ```compile_fail,E0308 |
29967ef6 XL |
910 | /// fn foo() -> usize { |
911 | /// 22; | |
912 | /// } | |
913 | /// ``` | |
914 | /// | |
915 | /// This routine checks if the final statement in a block is an | |
916 | /// expression with an explicit semicolon whose type is compatible | |
917 | /// with `expected_ty`. If so, it suggests removing the semicolon. | |
918 | fn consider_hint_about_removing_semicolon( | |
919 | &self, | |
920 | blk: &'tcx hir::Block<'tcx>, | |
921 | expected_ty: Ty<'tcx>, | |
5e7ed085 | 922 | err: &mut Diagnostic, |
29967ef6 XL |
923 | ) { |
924 | if let Some((span_semi, boxed)) = self.could_remove_semicolon(blk, expected_ty) { | |
925 | if let StatementAsExpression::NeedsBoxing = boxed { | |
926 | err.span_suggestion_verbose( | |
927 | span_semi, | |
928 | "consider removing this semicolon and boxing the expression", | |
929 | String::new(), | |
930 | Applicability::HasPlaceholders, | |
931 | ); | |
932 | } else { | |
933 | err.span_suggestion_short( | |
934 | span_semi, | |
04454e1e | 935 | "remove this semicolon", |
29967ef6 XL |
936 | String::new(), |
937 | Applicability::MachineApplicable, | |
938 | ); | |
939 | } | |
940 | } | |
941 | } | |
942 | ||
943 | fn parent_item_span(&self, id: hir::HirId) -> Option<Span> { | |
5099ac24 | 944 | let node = self.tcx.hir().get_by_def_id(self.tcx.hir().get_parent_item(id)); |
29967ef6 XL |
945 | match node { |
946 | Node::Item(&hir::Item { kind: hir::ItemKind::Fn(_, _, body_id), .. }) | |
947 | | Node::ImplItem(&hir::ImplItem { kind: hir::ImplItemKind::Fn(_, body_id), .. }) => { | |
948 | let body = self.tcx.hir().body(body_id); | |
949 | if let ExprKind::Block(block, _) = &body.value.kind { | |
950 | return Some(block.span); | |
951 | } | |
952 | } | |
953 | _ => {} | |
954 | } | |
955 | None | |
956 | } | |
957 | ||
958 | /// Given a function block's `HirId`, returns its `FnDecl` if it exists, or `None` otherwise. | |
959 | fn get_parent_fn_decl(&self, blk_id: hir::HirId) -> Option<(&'tcx hir::FnDecl<'tcx>, Ident)> { | |
5099ac24 | 960 | let parent = self.tcx.hir().get_by_def_id(self.tcx.hir().get_parent_item(blk_id)); |
29967ef6 XL |
961 | self.get_node_fn_decl(parent).map(|(fn_decl, ident, _)| (fn_decl, ident)) |
962 | } | |
963 | ||
964 | /// If `expr` is a `match` expression that has only one non-`!` arm, use that arm's tail | |
965 | /// expression's `Span`, otherwise return `expr.span`. This is done to give better errors | |
966 | /// when given code like the following: | |
967 | /// ```text | |
968 | /// if false { return 0i32; } else { 1u32 } | |
969 | /// // ^^^^ point at this instead of the whole `if` expression | |
970 | /// ``` | |
971 | fn get_expr_coercion_span(&self, expr: &hir::Expr<'_>) -> rustc_span::Span { | |
5869c6ff XL |
972 | let check_in_progress = |elem: &hir::Expr<'_>| { |
973 | self.in_progress_typeck_results | |
974 | .and_then(|typeck_results| typeck_results.borrow().node_type_opt(elem.hir_id)) | |
975 | .and_then(|ty| { | |
976 | if ty.is_never() { | |
977 | None | |
978 | } else { | |
979 | Some(match elem.kind { | |
980 | // Point at the tail expression when possible. | |
981 | hir::ExprKind::Block(block, _) => { | |
982 | block.expr.map_or(block.span, |e| e.span) | |
29967ef6 | 983 | } |
5869c6ff | 984 | _ => elem.span, |
29967ef6 | 985 | }) |
5869c6ff | 986 | } |
29967ef6 | 987 | }) |
5869c6ff XL |
988 | }; |
989 | ||
990 | if let hir::ExprKind::If(_, _, Some(el)) = expr.kind { | |
991 | if let Some(rslt) = check_in_progress(el) { | |
992 | return rslt; | |
29967ef6 XL |
993 | } |
994 | } | |
5869c6ff XL |
995 | |
996 | if let hir::ExprKind::Match(_, arms, _) = expr.kind { | |
997 | let mut iter = arms.iter().filter_map(|arm| check_in_progress(arm.body)); | |
998 | if let Some(span) = iter.next() { | |
999 | if iter.next().is_none() { | |
1000 | return span; | |
1001 | } | |
1002 | } | |
1003 | } | |
1004 | ||
29967ef6 XL |
1005 | expr.span |
1006 | } | |
1007 | ||
1008 | fn overwrite_local_ty_if_err( | |
1009 | &self, | |
a2a8927a XL |
1010 | hir_id: hir::HirId, |
1011 | pat: &'tcx hir::Pat<'tcx>, | |
29967ef6 XL |
1012 | decl_ty: Ty<'tcx>, |
1013 | ty: Ty<'tcx>, | |
1014 | ) { | |
1015 | if ty.references_error() { | |
1016 | // Override the types everywhere with `err()` to avoid knock on errors. | |
a2a8927a XL |
1017 | self.write_ty(hir_id, ty); |
1018 | self.write_ty(pat.hir_id, ty); | |
29967ef6 | 1019 | let local_ty = LocalTy { decl_ty, revealed_ty: ty }; |
a2a8927a XL |
1020 | self.locals.borrow_mut().insert(hir_id, local_ty); |
1021 | self.locals.borrow_mut().insert(pat.hir_id, local_ty); | |
29967ef6 XL |
1022 | } |
1023 | } | |
1024 | ||
1025 | // Finish resolving a path in a struct expression or pattern `S::A { .. }` if necessary. | |
1026 | // The newly resolved definition is written into `type_dependent_defs`. | |
1027 | fn finish_resolving_struct_path( | |
1028 | &self, | |
1029 | qpath: &QPath<'_>, | |
1030 | path_span: Span, | |
1031 | hir_id: hir::HirId, | |
1032 | ) -> (Res, Ty<'tcx>) { | |
1033 | match *qpath { | |
1034 | QPath::Resolved(ref maybe_qself, ref path) => { | |
1035 | let self_ty = maybe_qself.as_ref().map(|qself| self.to_ty(qself)); | |
6a06907d | 1036 | let ty = <dyn AstConv<'_>>::res_to_ty(self, self_ty, path, true); |
29967ef6 XL |
1037 | (path.res, ty) |
1038 | } | |
1039 | QPath::TypeRelative(ref qself, ref segment) => { | |
1040 | let ty = self.to_ty(qself); | |
1041 | ||
1042 | let res = if let hir::TyKind::Path(QPath::Resolved(_, ref path)) = qself.kind { | |
1043 | path.res | |
1044 | } else { | |
1045 | Res::Err | |
1046 | }; | |
6a06907d XL |
1047 | let result = <dyn AstConv<'_>>::associated_path_to_ty( |
1048 | self, hir_id, path_span, ty, res, segment, true, | |
1049 | ); | |
29967ef6 XL |
1050 | let ty = result.map(|(ty, _, _)| ty).unwrap_or_else(|_| self.tcx().ty_error()); |
1051 | let result = result.map(|(_, kind, def_id)| (kind, def_id)); | |
1052 | ||
1053 | // Write back the new resolution. | |
1054 | self.write_resolution(hir_id, result); | |
1055 | ||
5869c6ff | 1056 | (result.map_or(Res::Err, |(kind, def_id)| Res::Def(kind, def_id)), ty) |
29967ef6 | 1057 | } |
a2a8927a XL |
1058 | QPath::LangItem(lang_item, span, id) => { |
1059 | self.resolve_lang_item_path(lang_item, span, hir_id, id) | |
29967ef6 XL |
1060 | } |
1061 | } | |
1062 | } | |
1063 | ||
1064 | /// Given a vec of evaluated `FulfillmentError`s and an `fn` call argument expressions, we walk | |
1065 | /// the checked and coerced types for each argument to see if any of the `FulfillmentError`s | |
1066 | /// reference a type argument. The reason to walk also the checked type is that the coerced type | |
1067 | /// can be not easily comparable with predicate type (because of coercion). If the types match | |
1068 | /// for either checked or coerced type, and there's only *one* argument that does, we point at | |
1069 | /// the corresponding argument's expression span instead of the `fn` call path span. | |
1070 | fn point_at_arg_instead_of_call_if_possible( | |
1071 | &self, | |
1072 | errors: &mut Vec<traits::FulfillmentError<'tcx>>, | |
5099ac24 | 1073 | final_arg_types: &[Option<(Ty<'tcx>, Ty<'tcx>)>], |
c295e0f8 | 1074 | expr: &'tcx hir::Expr<'tcx>, |
29967ef6 XL |
1075 | call_sp: Span, |
1076 | args: &'tcx [hir::Expr<'tcx>], | |
1077 | ) { | |
1078 | // We *do not* do this for desugared call spans to keep good diagnostics when involving | |
1079 | // the `?` operator. | |
1080 | if call_sp.desugaring_kind().is_some() { | |
1081 | return; | |
1082 | } | |
1083 | ||
1084 | for error in errors { | |
1085 | // Only if the cause is somewhere inside the expression we want try to point at arg. | |
1086 | // Otherwise, it means that the cause is somewhere else and we should not change | |
1087 | // anything because we can break the correct span. | |
1088 | if !call_sp.contains(error.obligation.cause.span) { | |
1089 | continue; | |
1090 | } | |
1091 | ||
3c0e092e XL |
1092 | // Peel derived obligation, because it's the type that originally |
1093 | // started this inference chain that matters, not the one we wound | |
1094 | // up with at the end. | |
1095 | fn unpeel_to_top( | |
1096 | mut code: Lrc<ObligationCauseCode<'_>>, | |
1097 | ) -> Lrc<ObligationCauseCode<'_>> { | |
1098 | let mut result_code = code.clone(); | |
1099 | loop { | |
1100 | let parent = match &*code { | |
5e7ed085 FG |
1101 | ObligationCauseCode::ImplDerivedObligation(c) => { |
1102 | c.derived.parent_code.clone() | |
1103 | } | |
3c0e092e | 1104 | ObligationCauseCode::BuiltinDerivedObligation(c) |
3c0e092e XL |
1105 | | ObligationCauseCode::DerivedObligation(c) => c.parent_code.clone(), |
1106 | _ => break, | |
1107 | }; | |
1108 | result_code = std::mem::replace(&mut code, parent); | |
1109 | } | |
1110 | result_code | |
1111 | } | |
a2a8927a | 1112 | let self_: ty::subst::GenericArg<'_> = match &*unpeel_to_top(error.obligation.cause.clone_code()) { |
3c0e092e | 1113 | ObligationCauseCode::BuiltinDerivedObligation(code) | |
3c0e092e | 1114 | ObligationCauseCode::DerivedObligation(code) => { |
5099ac24 | 1115 | code.parent_trait_pred.self_ty().skip_binder().into() |
3c0e092e | 1116 | } |
5e7ed085 FG |
1117 | ObligationCauseCode::ImplDerivedObligation(code) => { |
1118 | code.derived.parent_trait_pred.self_ty().skip_binder().into() | |
1119 | } | |
3c0e092e XL |
1120 | _ if let ty::PredicateKind::Trait(predicate) = |
1121 | error.obligation.predicate.kind().skip_binder() => { | |
1122 | predicate.self_ty().into() | |
1123 | } | |
1124 | _ => continue, | |
1125 | }; | |
1126 | let self_ = self.resolve_vars_if_possible(self_); | |
1127 | ||
1128 | // Collect the argument position for all arguments that could have caused this | |
1129 | // `FulfillmentError`. | |
1130 | let mut referenced_in = final_arg_types | |
1131 | .iter() | |
5099ac24 FG |
1132 | .enumerate() |
1133 | .filter_map(|(i, arg)| match arg { | |
1134 | Some((checked_ty, coerce_ty)) => Some([(i, *checked_ty), (i, *coerce_ty)]), | |
1135 | _ => None, | |
1136 | }) | |
1137 | .flatten() | |
3c0e092e XL |
1138 | .flat_map(|(i, ty)| { |
1139 | let ty = self.resolve_vars_if_possible(ty); | |
1140 | // We walk the argument type because the argument's type could have | |
1141 | // been `Option<T>`, but the `FulfillmentError` references `T`. | |
5099ac24 | 1142 | if ty.walk().any(|arg| arg == self_) { Some(i) } else { None } |
3c0e092e XL |
1143 | }) |
1144 | .collect::<Vec<usize>>(); | |
1145 | ||
1146 | // Both checked and coerced types could have matched, thus we need to remove | |
1147 | // duplicates. | |
1148 | ||
1149 | // We sort primitive type usize here and can use unstable sort | |
1150 | referenced_in.sort_unstable(); | |
1151 | referenced_in.dedup(); | |
1152 | ||
1153 | if let (Some(ref_in), None) = (referenced_in.pop(), referenced_in.pop()) { | |
1154 | // Do not point at the inside of a macro. | |
1155 | // That would often result in poor error messages. | |
1156 | if args[ref_in].span.from_expansion() { | |
1157 | return; | |
1158 | } | |
1159 | // We make sure that only *one* argument matches the obligation failure | |
1160 | // and we assign the obligation's span to its expression's. | |
a2a8927a XL |
1161 | error.obligation.cause.span = args[ref_in].span; |
1162 | let parent_code = error.obligation.cause.clone_code(); | |
1163 | *error.obligation.cause.make_mut_code() = | |
3c0e092e XL |
1164 | ObligationCauseCode::FunctionArgumentObligation { |
1165 | arg_hir_id: args[ref_in].hir_id, | |
1166 | call_hir_id: expr.hir_id, | |
a2a8927a | 1167 | parent_code, |
3c0e092e | 1168 | }; |
a2a8927a | 1169 | } else if error.obligation.cause.span == call_sp { |
3c0e092e XL |
1170 | // Make function calls point at the callee, not the whole thing. |
1171 | if let hir::ExprKind::Call(callee, _) = expr.kind { | |
a2a8927a | 1172 | error.obligation.cause.span = callee.span; |
29967ef6 XL |
1173 | } |
1174 | } | |
1175 | } | |
1176 | } | |
1177 | ||
1178 | /// Given a vec of evaluated `FulfillmentError`s and an `fn` call expression, we walk the | |
1179 | /// `PathSegment`s and resolve their type parameters to see if any of the `FulfillmentError`s | |
1180 | /// were caused by them. If they were, we point at the corresponding type argument's span | |
1181 | /// instead of the `fn` call path span. | |
1182 | fn point_at_type_arg_instead_of_call_if_possible( | |
1183 | &self, | |
1184 | errors: &mut Vec<traits::FulfillmentError<'tcx>>, | |
1185 | call_expr: &'tcx hir::Expr<'tcx>, | |
1186 | ) { | |
1187 | if let hir::ExprKind::Call(path, _) = &call_expr.kind { | |
3c0e092e XL |
1188 | if let hir::ExprKind::Path(hir::QPath::Resolved(_, path)) = &path.kind { |
1189 | for error in errors { | |
1190 | if let ty::PredicateKind::Trait(predicate) = | |
1191 | error.obligation.predicate.kind().skip_binder() | |
1192 | { | |
1193 | // If any of the type arguments in this path segment caused the | |
1194 | // `FulfillmentError`, point at its span (#61860). | |
1195 | for arg in path | |
1196 | .segments | |
1197 | .iter() | |
1198 | .filter_map(|seg| seg.args.as_ref()) | |
1199 | .flat_map(|a| a.args.iter()) | |
29967ef6 | 1200 | { |
3c0e092e XL |
1201 | if let hir::GenericArg::Type(hir_ty) = &arg { |
1202 | if let hir::TyKind::Path(hir::QPath::TypeRelative(..)) = | |
1203 | &hir_ty.kind | |
1204 | { | |
1205 | // Avoid ICE with associated types. As this is best | |
1206 | // effort only, it's ok to ignore the case. It | |
1207 | // would trigger in `is_send::<T::AssocType>();` | |
1208 | // from `typeck-default-trait-impl-assoc-type.rs`. | |
1209 | } else { | |
1210 | let ty = <dyn AstConv<'_>>::ast_ty_to_ty(self, hir_ty); | |
1211 | let ty = self.resolve_vars_if_possible(ty); | |
1212 | if ty == predicate.self_ty() { | |
a2a8927a | 1213 | error.obligation.cause.span = hir_ty.span; |
29967ef6 XL |
1214 | } |
1215 | } | |
1216 | } | |
1217 | } | |
1218 | } | |
1219 | } | |
1220 | } | |
1221 | } | |
1222 | } | |
1223 | } |