]>
Commit | Line | Data |
---|---|---|
29967ef6 XL |
1 | use crate::astconv::AstConv; |
2 | use crate::check::coercion::CoerceMany; | |
3 | use crate::check::method::MethodCallee; | |
4 | use crate::check::Expectation::*; | |
5 | use crate::check::TupleArgumentsFlag::*; | |
6 | use crate::check::{ | |
7 | potentially_plural_count, struct_span_err, BreakableCtxt, Diverges, Expectation, FnCtxt, | |
8 | LocalTy, Needs, TupleArgumentsFlag, | |
9 | }; | |
10 | ||
11 | use rustc_ast as ast; | |
12 | use rustc_errors::{Applicability, DiagnosticBuilder, DiagnosticId}; | |
13 | use rustc_hir as hir; | |
14 | use rustc_hir::def::{DefKind, Res}; | |
15 | use rustc_hir::def_id::DefId; | |
16 | use rustc_hir::{ExprKind, Node, QPath}; | |
17 | use rustc_middle::ty::adjustment::AllowTwoPhase; | |
18 | use rustc_middle::ty::fold::TypeFoldable; | |
19 | use rustc_middle::ty::{self, Ty}; | |
20 | use rustc_session::Session; | |
21 | use rustc_span::symbol::{sym, Ident}; | |
22 | use rustc_span::{self, MultiSpan, Span}; | |
23 | use rustc_trait_selection::traits::{self, ObligationCauseCode, StatementAsExpression}; | |
24 | ||
25 | use std::mem::replace; | |
26 | use std::slice; | |
27 | ||
28 | impl<'a, 'tcx> FnCtxt<'a, 'tcx> { | |
29 | pub(in super::super) fn check_casts(&self) { | |
30 | let mut deferred_cast_checks = self.deferred_cast_checks.borrow_mut(); | |
31 | for cast in deferred_cast_checks.drain(..) { | |
32 | cast.check(self); | |
33 | } | |
34 | } | |
35 | ||
36 | pub(in super::super) fn check_method_argument_types( | |
37 | &self, | |
38 | sp: Span, | |
39 | expr: &'tcx hir::Expr<'tcx>, | |
40 | method: Result<MethodCallee<'tcx>, ()>, | |
41 | args_no_rcvr: &'tcx [hir::Expr<'tcx>], | |
42 | tuple_arguments: TupleArgumentsFlag, | |
43 | expected: Expectation<'tcx>, | |
44 | ) -> Ty<'tcx> { | |
45 | let has_error = match method { | |
46 | Ok(method) => method.substs.references_error() || method.sig.references_error(), | |
47 | Err(_) => true, | |
48 | }; | |
49 | if has_error { | |
50 | let err_inputs = self.err_args(args_no_rcvr.len()); | |
51 | ||
52 | let err_inputs = match tuple_arguments { | |
53 | DontTupleArguments => err_inputs, | |
54 | TupleArguments => vec![self.tcx.intern_tup(&err_inputs[..])], | |
55 | }; | |
56 | ||
57 | self.check_argument_types( | |
58 | sp, | |
59 | expr, | |
60 | &err_inputs[..], | |
61 | &[], | |
62 | args_no_rcvr, | |
63 | false, | |
64 | tuple_arguments, | |
65 | None, | |
66 | ); | |
67 | return self.tcx.ty_error(); | |
68 | } | |
69 | ||
70 | let method = method.unwrap(); | |
71 | // HACK(eddyb) ignore self in the definition (see above). | |
72 | let expected_arg_tys = self.expected_inputs_for_expected_output( | |
73 | sp, | |
74 | expected, | |
75 | method.sig.output(), | |
76 | &method.sig.inputs()[1..], | |
77 | ); | |
78 | self.check_argument_types( | |
79 | sp, | |
80 | expr, | |
81 | &method.sig.inputs()[1..], | |
82 | &expected_arg_tys[..], | |
83 | args_no_rcvr, | |
84 | method.sig.c_variadic, | |
85 | tuple_arguments, | |
86 | Some(method.def_id), | |
87 | ); | |
88 | method.sig.output() | |
89 | } | |
90 | ||
91 | /// Generic function that factors out common logic from function calls, | |
92 | /// method calls and overloaded operators. | |
93 | pub(in super::super) fn check_argument_types( | |
94 | &self, | |
95 | sp: Span, | |
96 | expr: &'tcx hir::Expr<'tcx>, | |
97 | fn_inputs: &[Ty<'tcx>], | |
98 | expected_arg_tys: &[Ty<'tcx>], | |
99 | args: &'tcx [hir::Expr<'tcx>], | |
100 | c_variadic: bool, | |
101 | tuple_arguments: TupleArgumentsFlag, | |
102 | def_id: Option<DefId>, | |
103 | ) { | |
104 | let tcx = self.tcx; | |
105 | // Grab the argument types, supplying fresh type variables | |
106 | // if the wrong number of arguments were supplied | |
107 | let supplied_arg_count = if tuple_arguments == DontTupleArguments { args.len() } else { 1 }; | |
108 | ||
109 | // All the input types from the fn signature must outlive the call | |
110 | // so as to validate implied bounds. | |
111 | for (&fn_input_ty, arg_expr) in fn_inputs.iter().zip(args.iter()) { | |
112 | self.register_wf_obligation(fn_input_ty.into(), arg_expr.span, traits::MiscObligation); | |
113 | } | |
114 | ||
115 | let expected_arg_count = fn_inputs.len(); | |
116 | ||
117 | let param_count_error = |expected_count: usize, | |
118 | arg_count: usize, | |
119 | error_code: &str, | |
120 | c_variadic: bool, | |
121 | sugg_unit: bool| { | |
122 | let (span, start_span, args) = match &expr.kind { | |
123 | hir::ExprKind::Call(hir::Expr { span, .. }, args) => (*span, *span, &args[..]), | |
124 | hir::ExprKind::MethodCall(path_segment, span, args, _) => ( | |
125 | *span, | |
126 | // `sp` doesn't point at the whole `foo.bar()`, only at `bar`. | |
127 | path_segment | |
128 | .args | |
129 | .and_then(|args| args.args.iter().last()) | |
130 | // Account for `foo.bar::<T>()`. | |
131 | .map(|arg| { | |
132 | // Skip the closing `>`. | |
133 | tcx.sess | |
134 | .source_map() | |
135 | .next_point(tcx.sess.source_map().next_point(arg.span())) | |
136 | }) | |
137 | .unwrap_or(*span), | |
138 | &args[1..], // Skip the receiver. | |
139 | ), | |
140 | k => span_bug!(sp, "checking argument types on a non-call: `{:?}`", k), | |
141 | }; | |
142 | let arg_spans = if args.is_empty() { | |
143 | // foo() | |
144 | // ^^^-- supplied 0 arguments | |
145 | // | | |
146 | // expected 2 arguments | |
147 | vec![tcx.sess.source_map().next_point(start_span).with_hi(sp.hi())] | |
148 | } else { | |
149 | // foo(1, 2, 3) | |
150 | // ^^^ - - - supplied 3 arguments | |
151 | // | | |
152 | // expected 2 arguments | |
153 | args.iter().map(|arg| arg.span).collect::<Vec<Span>>() | |
154 | }; | |
155 | ||
156 | let mut err = tcx.sess.struct_span_err_with_code( | |
157 | span, | |
158 | &format!( | |
159 | "this function takes {}{} but {} {} supplied", | |
160 | if c_variadic { "at least " } else { "" }, | |
161 | potentially_plural_count(expected_count, "argument"), | |
162 | potentially_plural_count(arg_count, "argument"), | |
163 | if arg_count == 1 { "was" } else { "were" } | |
164 | ), | |
165 | DiagnosticId::Error(error_code.to_owned()), | |
166 | ); | |
167 | let label = format!("supplied {}", potentially_plural_count(arg_count, "argument")); | |
168 | for (i, span) in arg_spans.into_iter().enumerate() { | |
169 | err.span_label( | |
170 | span, | |
171 | if arg_count == 0 || i + 1 == arg_count { &label } else { "" }, | |
172 | ); | |
173 | } | |
174 | ||
175 | if let Some(def_id) = def_id { | |
176 | if let Some(node) = tcx.hir().get_if_local(def_id) { | |
177 | let mut spans: MultiSpan = node | |
178 | .ident() | |
179 | .map(|ident| ident.span) | |
180 | .unwrap_or_else(|| tcx.hir().span(node.hir_id().unwrap())) | |
181 | .into(); | |
182 | ||
183 | if let Some(id) = node.body_id() { | |
184 | let body = tcx.hir().body(id); | |
185 | for param in body.params { | |
186 | spans.push_span_label(param.span, String::new()); | |
187 | } | |
188 | } | |
189 | ||
190 | let def_kind = tcx.def_kind(def_id); | |
191 | err.span_note(spans, &format!("{} defined here", def_kind.descr(def_id))); | |
192 | } | |
193 | } | |
194 | ||
195 | if sugg_unit { | |
196 | let sugg_span = tcx.sess.source_map().end_point(expr.span); | |
197 | // remove closing `)` from the span | |
198 | let sugg_span = sugg_span.shrink_to_lo(); | |
199 | err.span_suggestion( | |
200 | sugg_span, | |
201 | "expected the unit value `()`; create it with empty parentheses", | |
202 | String::from("()"), | |
203 | Applicability::MachineApplicable, | |
204 | ); | |
205 | } else { | |
206 | err.span_label( | |
207 | span, | |
208 | format!( | |
209 | "expected {}{}", | |
210 | if c_variadic { "at least " } else { "" }, | |
211 | potentially_plural_count(expected_count, "argument") | |
212 | ), | |
213 | ); | |
214 | } | |
215 | err.emit(); | |
216 | }; | |
217 | ||
218 | let mut expected_arg_tys = expected_arg_tys.to_vec(); | |
219 | ||
220 | let formal_tys = if tuple_arguments == TupleArguments { | |
221 | let tuple_type = self.structurally_resolved_type(sp, fn_inputs[0]); | |
222 | match tuple_type.kind() { | |
223 | ty::Tuple(arg_types) if arg_types.len() != args.len() => { | |
224 | param_count_error(arg_types.len(), args.len(), "E0057", false, false); | |
225 | expected_arg_tys = vec![]; | |
226 | self.err_args(args.len()) | |
227 | } | |
228 | ty::Tuple(arg_types) => { | |
229 | expected_arg_tys = match expected_arg_tys.get(0) { | |
230 | Some(&ty) => match ty.kind() { | |
231 | ty::Tuple(ref tys) => tys.iter().map(|k| k.expect_ty()).collect(), | |
232 | _ => vec![], | |
233 | }, | |
234 | None => vec![], | |
235 | }; | |
236 | arg_types.iter().map(|k| k.expect_ty()).collect() | |
237 | } | |
238 | _ => { | |
239 | struct_span_err!( | |
240 | tcx.sess, | |
241 | sp, | |
242 | E0059, | |
243 | "cannot use call notation; the first type parameter \ | |
244 | for the function trait is neither a tuple nor unit" | |
245 | ) | |
246 | .emit(); | |
247 | expected_arg_tys = vec![]; | |
248 | self.err_args(args.len()) | |
249 | } | |
250 | } | |
251 | } else if expected_arg_count == supplied_arg_count { | |
252 | fn_inputs.to_vec() | |
253 | } else if c_variadic { | |
254 | if supplied_arg_count >= expected_arg_count { | |
255 | fn_inputs.to_vec() | |
256 | } else { | |
257 | param_count_error(expected_arg_count, supplied_arg_count, "E0060", true, false); | |
258 | expected_arg_tys = vec![]; | |
259 | self.err_args(supplied_arg_count) | |
260 | } | |
261 | } else { | |
262 | // is the missing argument of type `()`? | |
263 | let sugg_unit = if expected_arg_tys.len() == 1 && supplied_arg_count == 0 { | |
fc512014 | 264 | self.resolve_vars_if_possible(expected_arg_tys[0]).is_unit() |
29967ef6 | 265 | } else if fn_inputs.len() == 1 && supplied_arg_count == 0 { |
fc512014 | 266 | self.resolve_vars_if_possible(fn_inputs[0]).is_unit() |
29967ef6 XL |
267 | } else { |
268 | false | |
269 | }; | |
270 | param_count_error(expected_arg_count, supplied_arg_count, "E0061", false, sugg_unit); | |
271 | ||
272 | expected_arg_tys = vec![]; | |
273 | self.err_args(supplied_arg_count) | |
274 | }; | |
275 | ||
276 | debug!( | |
277 | "check_argument_types: formal_tys={:?}", | |
278 | formal_tys.iter().map(|t| self.ty_to_string(*t)).collect::<Vec<String>>() | |
279 | ); | |
280 | ||
281 | // If there is no expectation, expect formal_tys. | |
282 | let expected_arg_tys = | |
283 | if !expected_arg_tys.is_empty() { expected_arg_tys } else { formal_tys.clone() }; | |
284 | ||
285 | let mut final_arg_types: Vec<(usize, Ty<'_>, Ty<'_>)> = vec![]; | |
286 | ||
287 | // Check the arguments. | |
288 | // We do this in a pretty awful way: first we type-check any arguments | |
289 | // that are not closures, then we type-check the closures. This is so | |
290 | // that we have more information about the types of arguments when we | |
291 | // type-check the functions. This isn't really the right way to do this. | |
292 | for &check_closures in &[false, true] { | |
293 | debug!("check_closures={}", check_closures); | |
294 | ||
295 | // More awful hacks: before we check argument types, try to do | |
296 | // an "opportunistic" trait resolution of any trait bounds on | |
297 | // the call. This helps coercions. | |
298 | if check_closures { | |
299 | self.select_obligations_where_possible(false, |errors| { | |
300 | self.point_at_type_arg_instead_of_call_if_possible(errors, expr); | |
301 | self.point_at_arg_instead_of_call_if_possible( | |
302 | errors, | |
303 | &final_arg_types[..], | |
304 | sp, | |
305 | &args, | |
306 | ); | |
307 | }) | |
308 | } | |
309 | ||
310 | // For C-variadic functions, we don't have a declared type for all of | |
311 | // the arguments hence we only do our usual type checking with | |
312 | // the arguments who's types we do know. | |
313 | let t = if c_variadic { | |
314 | expected_arg_count | |
315 | } else if tuple_arguments == TupleArguments { | |
316 | args.len() | |
317 | } else { | |
318 | supplied_arg_count | |
319 | }; | |
320 | for (i, arg) in args.iter().take(t).enumerate() { | |
321 | // Warn only for the first loop (the "no closures" one). | |
322 | // Closure arguments themselves can't be diverging, but | |
323 | // a previous argument can, e.g., `foo(panic!(), || {})`. | |
324 | if !check_closures { | |
325 | self.warn_if_unreachable(arg.hir_id, arg.span, "expression"); | |
326 | } | |
327 | ||
328 | let is_closure = match arg.kind { | |
329 | ExprKind::Closure(..) => true, | |
330 | _ => false, | |
331 | }; | |
332 | ||
333 | if is_closure != check_closures { | |
334 | continue; | |
335 | } | |
336 | ||
337 | debug!("checking the argument"); | |
338 | let formal_ty = formal_tys[i]; | |
339 | ||
340 | // The special-cased logic below has three functions: | |
341 | // 1. Provide as good of an expected type as possible. | |
342 | let expected = Expectation::rvalue_hint(self, expected_arg_tys[i]); | |
343 | ||
344 | let checked_ty = self.check_expr_with_expectation(&arg, expected); | |
345 | ||
346 | // 2. Coerce to the most detailed type that could be coerced | |
347 | // to, which is `expected_ty` if `rvalue_hint` returns an | |
348 | // `ExpectHasType(expected_ty)`, or the `formal_ty` otherwise. | |
349 | let coerce_ty = expected.only_has_type(self).unwrap_or(formal_ty); | |
350 | // We're processing function arguments so we definitely want to use | |
351 | // two-phase borrows. | |
352 | self.demand_coerce(&arg, checked_ty, coerce_ty, None, AllowTwoPhase::Yes); | |
353 | final_arg_types.push((i, checked_ty, coerce_ty)); | |
354 | ||
355 | // 3. Relate the expected type and the formal one, | |
356 | // if the expected type was used for the coercion. | |
357 | self.demand_suptype(arg.span, formal_ty, coerce_ty); | |
358 | } | |
359 | } | |
360 | ||
361 | // We also need to make sure we at least write the ty of the other | |
362 | // arguments which we skipped above. | |
363 | if c_variadic { | |
364 | fn variadic_error<'tcx>(s: &Session, span: Span, t: Ty<'tcx>, cast_ty: &str) { | |
365 | use crate::structured_errors::{StructuredDiagnostic, VariadicError}; | |
366 | VariadicError::new(s, span, t, cast_ty).diagnostic().emit(); | |
367 | } | |
368 | ||
369 | for arg in args.iter().skip(expected_arg_count) { | |
370 | let arg_ty = self.check_expr(&arg); | |
371 | ||
372 | // There are a few types which get autopromoted when passed via varargs | |
373 | // in C but we just error out instead and require explicit casts. | |
374 | let arg_ty = self.structurally_resolved_type(arg.span, arg_ty); | |
375 | match arg_ty.kind() { | |
376 | ty::Float(ast::FloatTy::F32) => { | |
377 | variadic_error(tcx.sess, arg.span, arg_ty, "c_double"); | |
378 | } | |
379 | ty::Int(ast::IntTy::I8 | ast::IntTy::I16) | ty::Bool => { | |
380 | variadic_error(tcx.sess, arg.span, arg_ty, "c_int"); | |
381 | } | |
382 | ty::Uint(ast::UintTy::U8 | ast::UintTy::U16) => { | |
383 | variadic_error(tcx.sess, arg.span, arg_ty, "c_uint"); | |
384 | } | |
385 | ty::FnDef(..) => { | |
386 | let ptr_ty = self.tcx.mk_fn_ptr(arg_ty.fn_sig(self.tcx)); | |
fc512014 | 387 | let ptr_ty = self.resolve_vars_if_possible(ptr_ty); |
29967ef6 XL |
388 | variadic_error(tcx.sess, arg.span, arg_ty, &ptr_ty.to_string()); |
389 | } | |
390 | _ => {} | |
391 | } | |
392 | } | |
393 | } | |
394 | } | |
395 | ||
396 | // AST fragment checking | |
397 | pub(in super::super) fn check_lit( | |
398 | &self, | |
399 | lit: &hir::Lit, | |
400 | expected: Expectation<'tcx>, | |
401 | ) -> Ty<'tcx> { | |
402 | let tcx = self.tcx; | |
403 | ||
404 | match lit.node { | |
405 | ast::LitKind::Str(..) => tcx.mk_static_str(), | |
406 | ast::LitKind::ByteStr(ref v) => { | |
407 | tcx.mk_imm_ref(tcx.lifetimes.re_static, tcx.mk_array(tcx.types.u8, v.len() as u64)) | |
408 | } | |
409 | ast::LitKind::Byte(_) => tcx.types.u8, | |
410 | ast::LitKind::Char(_) => tcx.types.char, | |
411 | ast::LitKind::Int(_, ast::LitIntType::Signed(t)) => tcx.mk_mach_int(t), | |
412 | ast::LitKind::Int(_, ast::LitIntType::Unsigned(t)) => tcx.mk_mach_uint(t), | |
413 | ast::LitKind::Int(_, ast::LitIntType::Unsuffixed) => { | |
414 | let opt_ty = expected.to_option(self).and_then(|ty| match ty.kind() { | |
415 | ty::Int(_) | ty::Uint(_) => Some(ty), | |
416 | ty::Char => Some(tcx.types.u8), | |
417 | ty::RawPtr(..) => Some(tcx.types.usize), | |
418 | ty::FnDef(..) | ty::FnPtr(_) => Some(tcx.types.usize), | |
419 | _ => None, | |
420 | }); | |
421 | opt_ty.unwrap_or_else(|| self.next_int_var()) | |
422 | } | |
423 | ast::LitKind::Float(_, ast::LitFloatType::Suffixed(t)) => tcx.mk_mach_float(t), | |
424 | ast::LitKind::Float(_, ast::LitFloatType::Unsuffixed) => { | |
425 | let opt_ty = expected.to_option(self).and_then(|ty| match ty.kind() { | |
426 | ty::Float(_) => Some(ty), | |
427 | _ => None, | |
428 | }); | |
429 | opt_ty.unwrap_or_else(|| self.next_float_var()) | |
430 | } | |
431 | ast::LitKind::Bool(_) => tcx.types.bool, | |
432 | ast::LitKind::Err(_) => tcx.ty_error(), | |
433 | } | |
434 | } | |
435 | ||
436 | pub fn check_struct_path( | |
437 | &self, | |
438 | qpath: &QPath<'_>, | |
439 | hir_id: hir::HirId, | |
440 | ) -> Option<(&'tcx ty::VariantDef, Ty<'tcx>)> { | |
441 | let path_span = qpath.qself_span(); | |
442 | let (def, ty) = self.finish_resolving_struct_path(qpath, path_span, hir_id); | |
443 | let variant = match def { | |
444 | Res::Err => { | |
445 | self.set_tainted_by_errors(); | |
446 | return None; | |
447 | } | |
448 | Res::Def(DefKind::Variant, _) => match ty.kind() { | |
449 | ty::Adt(adt, substs) => Some((adt.variant_of_res(def), adt.did, substs)), | |
450 | _ => bug!("unexpected type: {:?}", ty), | |
451 | }, | |
452 | Res::Def(DefKind::Struct | DefKind::Union | DefKind::TyAlias | DefKind::AssocTy, _) | |
453 | | Res::SelfTy(..) => match ty.kind() { | |
454 | ty::Adt(adt, substs) if !adt.is_enum() => { | |
455 | Some((adt.non_enum_variant(), adt.did, substs)) | |
456 | } | |
457 | _ => None, | |
458 | }, | |
459 | _ => bug!("unexpected definition: {:?}", def), | |
460 | }; | |
461 | ||
462 | if let Some((variant, did, substs)) = variant { | |
463 | debug!("check_struct_path: did={:?} substs={:?}", did, substs); | |
464 | self.write_user_type_annotation_from_substs(hir_id, did, substs, None); | |
465 | ||
466 | // Check bounds on type arguments used in the path. | |
467 | let (bounds, _) = self.instantiate_bounds(path_span, did, substs); | |
468 | let cause = | |
469 | traits::ObligationCause::new(path_span, self.body_id, traits::ItemObligation(did)); | |
470 | self.add_obligations_for_parameters(cause, bounds); | |
471 | ||
472 | Some((variant, ty)) | |
473 | } else { | |
474 | struct_span_err!( | |
475 | self.tcx.sess, | |
476 | path_span, | |
477 | E0071, | |
478 | "expected struct, variant or union type, found {}", | |
479 | ty.sort_string(self.tcx) | |
480 | ) | |
481 | .span_label(path_span, "not a struct") | |
482 | .emit(); | |
483 | None | |
484 | } | |
485 | } | |
486 | ||
487 | pub fn check_decl_initializer( | |
488 | &self, | |
489 | local: &'tcx hir::Local<'tcx>, | |
490 | init: &'tcx hir::Expr<'tcx>, | |
491 | ) -> Ty<'tcx> { | |
492 | // FIXME(tschottdorf): `contains_explicit_ref_binding()` must be removed | |
493 | // for #42640 (default match binding modes). | |
494 | // | |
495 | // See #44848. | |
496 | let ref_bindings = local.pat.contains_explicit_ref_binding(); | |
497 | ||
498 | let local_ty = self.local_ty(init.span, local.hir_id).revealed_ty; | |
499 | if let Some(m) = ref_bindings { | |
500 | // Somewhat subtle: if we have a `ref` binding in the pattern, | |
501 | // we want to avoid introducing coercions for the RHS. This is | |
502 | // both because it helps preserve sanity and, in the case of | |
503 | // ref mut, for soundness (issue #23116). In particular, in | |
504 | // the latter case, we need to be clear that the type of the | |
505 | // referent for the reference that results is *equal to* the | |
506 | // type of the place it is referencing, and not some | |
507 | // supertype thereof. | |
508 | let init_ty = self.check_expr_with_needs(init, Needs::maybe_mut_place(m)); | |
509 | self.demand_eqtype(init.span, local_ty, init_ty); | |
510 | init_ty | |
511 | } else { | |
512 | self.check_expr_coercable_to_type(init, local_ty, None) | |
513 | } | |
514 | } | |
515 | ||
516 | /// Type check a `let` statement. | |
517 | pub fn check_decl_local(&self, local: &'tcx hir::Local<'tcx>) { | |
518 | // Determine and write the type which we'll check the pattern against. | |
519 | let ty = self.local_ty(local.span, local.hir_id).decl_ty; | |
520 | self.write_ty(local.hir_id, ty); | |
521 | ||
522 | // Type check the initializer. | |
523 | if let Some(ref init) = local.init { | |
524 | let init_ty = self.check_decl_initializer(local, &init); | |
525 | self.overwrite_local_ty_if_err(local, ty, init_ty); | |
526 | } | |
527 | ||
528 | // Does the expected pattern type originate from an expression and what is the span? | |
529 | let (origin_expr, ty_span) = match (local.ty, local.init) { | |
530 | (Some(ty), _) => (false, Some(ty.span)), // Bias towards the explicit user type. | |
531 | (_, Some(init)) => (true, Some(init.span)), // No explicit type; so use the scrutinee. | |
532 | _ => (false, None), // We have `let $pat;`, so the expected type is unconstrained. | |
533 | }; | |
534 | ||
535 | // Type check the pattern. Override if necessary to avoid knock-on errors. | |
536 | self.check_pat_top(&local.pat, ty, ty_span, origin_expr); | |
537 | let pat_ty = self.node_ty(local.pat.hir_id); | |
538 | self.overwrite_local_ty_if_err(local, ty, pat_ty); | |
539 | } | |
540 | ||
541 | pub fn check_stmt(&self, stmt: &'tcx hir::Stmt<'tcx>) { | |
542 | // Don't do all the complex logic below for `DeclItem`. | |
543 | match stmt.kind { | |
544 | hir::StmtKind::Item(..) => return, | |
545 | hir::StmtKind::Local(..) | hir::StmtKind::Expr(..) | hir::StmtKind::Semi(..) => {} | |
546 | } | |
547 | ||
548 | self.warn_if_unreachable(stmt.hir_id, stmt.span, "statement"); | |
549 | ||
550 | // Hide the outer diverging and `has_errors` flags. | |
551 | let old_diverges = self.diverges.replace(Diverges::Maybe); | |
552 | let old_has_errors = self.has_errors.replace(false); | |
553 | ||
554 | match stmt.kind { | |
555 | hir::StmtKind::Local(ref l) => { | |
556 | self.check_decl_local(&l); | |
557 | } | |
558 | // Ignore for now. | |
559 | hir::StmtKind::Item(_) => {} | |
560 | hir::StmtKind::Expr(ref expr) => { | |
561 | // Check with expected type of `()`. | |
562 | self.check_expr_has_type_or_error(&expr, self.tcx.mk_unit(), |err| { | |
563 | self.suggest_semicolon_at_end(expr.span, err); | |
564 | }); | |
565 | } | |
566 | hir::StmtKind::Semi(ref expr) => { | |
567 | self.check_expr(&expr); | |
568 | } | |
569 | } | |
570 | ||
571 | // Combine the diverging and `has_error` flags. | |
572 | self.diverges.set(self.diverges.get() | old_diverges); | |
573 | self.has_errors.set(self.has_errors.get() | old_has_errors); | |
574 | } | |
575 | ||
576 | pub fn check_block_no_value(&self, blk: &'tcx hir::Block<'tcx>) { | |
577 | let unit = self.tcx.mk_unit(); | |
578 | let ty = self.check_block_with_expected(blk, ExpectHasType(unit)); | |
579 | ||
580 | // if the block produces a `!` value, that can always be | |
581 | // (effectively) coerced to unit. | |
582 | if !ty.is_never() { | |
583 | self.demand_suptype(blk.span, unit, ty); | |
584 | } | |
585 | } | |
586 | ||
587 | pub(in super::super) fn check_block_with_expected( | |
588 | &self, | |
589 | blk: &'tcx hir::Block<'tcx>, | |
590 | expected: Expectation<'tcx>, | |
591 | ) -> Ty<'tcx> { | |
592 | let prev = { | |
593 | let mut fcx_ps = self.ps.borrow_mut(); | |
594 | let unsafety_state = fcx_ps.recurse(blk); | |
595 | replace(&mut *fcx_ps, unsafety_state) | |
596 | }; | |
597 | ||
598 | // In some cases, blocks have just one exit, but other blocks | |
599 | // can be targeted by multiple breaks. This can happen both | |
600 | // with labeled blocks as well as when we desugar | |
601 | // a `try { ... }` expression. | |
602 | // | |
603 | // Example 1: | |
604 | // | |
605 | // 'a: { if true { break 'a Err(()); } Ok(()) } | |
606 | // | |
607 | // Here we would wind up with two coercions, one from | |
608 | // `Err(())` and the other from the tail expression | |
609 | // `Ok(())`. If the tail expression is omitted, that's a | |
610 | // "forced unit" -- unless the block diverges, in which | |
611 | // case we can ignore the tail expression (e.g., `'a: { | |
612 | // break 'a 22; }` would not force the type of the block | |
613 | // to be `()`). | |
614 | let tail_expr = blk.expr.as_ref(); | |
615 | let coerce_to_ty = expected.coercion_target_type(self, blk.span); | |
616 | let coerce = if blk.targeted_by_break { | |
617 | CoerceMany::new(coerce_to_ty) | |
618 | } else { | |
619 | let tail_expr: &[&hir::Expr<'_>] = match tail_expr { | |
620 | Some(e) => slice::from_ref(e), | |
621 | None => &[], | |
622 | }; | |
623 | CoerceMany::with_coercion_sites(coerce_to_ty, tail_expr) | |
624 | }; | |
625 | ||
626 | let prev_diverges = self.diverges.get(); | |
627 | let ctxt = BreakableCtxt { coerce: Some(coerce), may_break: false }; | |
628 | ||
629 | let (ctxt, ()) = self.with_breakable_ctxt(blk.hir_id, ctxt, || { | |
630 | for s in blk.stmts { | |
631 | self.check_stmt(s); | |
632 | } | |
633 | ||
634 | // check the tail expression **without** holding the | |
635 | // `enclosing_breakables` lock below. | |
636 | let tail_expr_ty = tail_expr.map(|t| self.check_expr_with_expectation(t, expected)); | |
637 | ||
638 | let mut enclosing_breakables = self.enclosing_breakables.borrow_mut(); | |
639 | let ctxt = enclosing_breakables.find_breakable(blk.hir_id); | |
640 | let coerce = ctxt.coerce.as_mut().unwrap(); | |
641 | if let Some(tail_expr_ty) = tail_expr_ty { | |
642 | let tail_expr = tail_expr.unwrap(); | |
643 | let span = self.get_expr_coercion_span(tail_expr); | |
644 | let cause = self.cause(span, ObligationCauseCode::BlockTailExpression(blk.hir_id)); | |
645 | coerce.coerce(self, &cause, tail_expr, tail_expr_ty); | |
646 | } else { | |
647 | // Subtle: if there is no explicit tail expression, | |
648 | // that is typically equivalent to a tail expression | |
649 | // of `()` -- except if the block diverges. In that | |
650 | // case, there is no value supplied from the tail | |
651 | // expression (assuming there are no other breaks, | |
652 | // this implies that the type of the block will be | |
653 | // `!`). | |
654 | // | |
655 | // #41425 -- label the implicit `()` as being the | |
656 | // "found type" here, rather than the "expected type". | |
657 | if !self.diverges.get().is_always() { | |
658 | // #50009 -- Do not point at the entire fn block span, point at the return type | |
659 | // span, as it is the cause of the requirement, and | |
660 | // `consider_hint_about_removing_semicolon` will point at the last expression | |
661 | // if it were a relevant part of the error. This improves usability in editors | |
662 | // that highlight errors inline. | |
663 | let mut sp = blk.span; | |
664 | let mut fn_span = None; | |
665 | if let Some((decl, ident)) = self.get_parent_fn_decl(blk.hir_id) { | |
666 | let ret_sp = decl.output.span(); | |
667 | if let Some(block_sp) = self.parent_item_span(blk.hir_id) { | |
668 | // HACK: on some cases (`ui/liveness/liveness-issue-2163.rs`) the | |
669 | // output would otherwise be incorrect and even misleading. Make sure | |
670 | // the span we're aiming at correspond to a `fn` body. | |
671 | if block_sp == blk.span { | |
672 | sp = ret_sp; | |
673 | fn_span = Some(ident.span); | |
674 | } | |
675 | } | |
676 | } | |
677 | coerce.coerce_forced_unit( | |
678 | self, | |
679 | &self.misc(sp), | |
680 | &mut |err| { | |
681 | if let Some(expected_ty) = expected.only_has_type(self) { | |
682 | self.consider_hint_about_removing_semicolon(blk, expected_ty, err); | |
683 | } | |
684 | if let Some(fn_span) = fn_span { | |
685 | err.span_label( | |
686 | fn_span, | |
687 | "implicitly returns `()` as its body has no tail or `return` \ | |
688 | expression", | |
689 | ); | |
690 | } | |
691 | }, | |
692 | false, | |
693 | ); | |
694 | } | |
695 | } | |
696 | }); | |
697 | ||
698 | if ctxt.may_break { | |
699 | // If we can break from the block, then the block's exit is always reachable | |
700 | // (... as long as the entry is reachable) - regardless of the tail of the block. | |
701 | self.diverges.set(prev_diverges); | |
702 | } | |
703 | ||
704 | let mut ty = ctxt.coerce.unwrap().complete(self); | |
705 | ||
706 | if self.has_errors.get() || ty.references_error() { | |
707 | ty = self.tcx.ty_error() | |
708 | } | |
709 | ||
710 | self.write_ty(blk.hir_id, ty); | |
711 | ||
712 | *self.ps.borrow_mut() = prev; | |
713 | ty | |
714 | } | |
715 | ||
716 | pub(in super::super) fn check_rustc_args_require_const( | |
717 | &self, | |
718 | def_id: DefId, | |
719 | hir_id: hir::HirId, | |
720 | span: Span, | |
721 | ) { | |
722 | // We're only interested in functions tagged with | |
723 | // #[rustc_args_required_const], so ignore anything that's not. | |
724 | if !self.tcx.has_attr(def_id, sym::rustc_args_required_const) { | |
725 | return; | |
726 | } | |
727 | ||
728 | // If our calling expression is indeed the function itself, we're good! | |
729 | // If not, generate an error that this can only be called directly. | |
730 | if let Node::Expr(expr) = self.tcx.hir().get(self.tcx.hir().get_parent_node(hir_id)) { | |
731 | if let ExprKind::Call(ref callee, ..) = expr.kind { | |
732 | if callee.hir_id == hir_id { | |
733 | return; | |
734 | } | |
735 | } | |
736 | } | |
737 | ||
738 | self.tcx.sess.span_err( | |
739 | span, | |
740 | "this function can only be invoked directly, not through a function pointer", | |
741 | ); | |
742 | } | |
743 | ||
744 | /// A common error is to add an extra semicolon: | |
745 | /// | |
746 | /// ``` | |
747 | /// fn foo() -> usize { | |
748 | /// 22; | |
749 | /// } | |
750 | /// ``` | |
751 | /// | |
752 | /// This routine checks if the final statement in a block is an | |
753 | /// expression with an explicit semicolon whose type is compatible | |
754 | /// with `expected_ty`. If so, it suggests removing the semicolon. | |
755 | fn consider_hint_about_removing_semicolon( | |
756 | &self, | |
757 | blk: &'tcx hir::Block<'tcx>, | |
758 | expected_ty: Ty<'tcx>, | |
759 | err: &mut DiagnosticBuilder<'_>, | |
760 | ) { | |
761 | if let Some((span_semi, boxed)) = self.could_remove_semicolon(blk, expected_ty) { | |
762 | if let StatementAsExpression::NeedsBoxing = boxed { | |
763 | err.span_suggestion_verbose( | |
764 | span_semi, | |
765 | "consider removing this semicolon and boxing the expression", | |
766 | String::new(), | |
767 | Applicability::HasPlaceholders, | |
768 | ); | |
769 | } else { | |
770 | err.span_suggestion_short( | |
771 | span_semi, | |
772 | "consider removing this semicolon", | |
773 | String::new(), | |
774 | Applicability::MachineApplicable, | |
775 | ); | |
776 | } | |
777 | } | |
778 | } | |
779 | ||
780 | fn parent_item_span(&self, id: hir::HirId) -> Option<Span> { | |
781 | let node = self.tcx.hir().get(self.tcx.hir().get_parent_item(id)); | |
782 | match node { | |
783 | Node::Item(&hir::Item { kind: hir::ItemKind::Fn(_, _, body_id), .. }) | |
784 | | Node::ImplItem(&hir::ImplItem { kind: hir::ImplItemKind::Fn(_, body_id), .. }) => { | |
785 | let body = self.tcx.hir().body(body_id); | |
786 | if let ExprKind::Block(block, _) = &body.value.kind { | |
787 | return Some(block.span); | |
788 | } | |
789 | } | |
790 | _ => {} | |
791 | } | |
792 | None | |
793 | } | |
794 | ||
795 | /// Given a function block's `HirId`, returns its `FnDecl` if it exists, or `None` otherwise. | |
796 | fn get_parent_fn_decl(&self, blk_id: hir::HirId) -> Option<(&'tcx hir::FnDecl<'tcx>, Ident)> { | |
797 | let parent = self.tcx.hir().get(self.tcx.hir().get_parent_item(blk_id)); | |
798 | self.get_node_fn_decl(parent).map(|(fn_decl, ident, _)| (fn_decl, ident)) | |
799 | } | |
800 | ||
801 | /// If `expr` is a `match` expression that has only one non-`!` arm, use that arm's tail | |
802 | /// expression's `Span`, otherwise return `expr.span`. This is done to give better errors | |
803 | /// when given code like the following: | |
804 | /// ```text | |
805 | /// if false { return 0i32; } else { 1u32 } | |
806 | /// // ^^^^ point at this instead of the whole `if` expression | |
807 | /// ``` | |
808 | fn get_expr_coercion_span(&self, expr: &hir::Expr<'_>) -> rustc_span::Span { | |
809 | if let hir::ExprKind::Match(_, arms, _) = &expr.kind { | |
810 | let arm_spans: Vec<Span> = arms | |
811 | .iter() | |
812 | .filter_map(|arm| { | |
813 | self.in_progress_typeck_results | |
814 | .and_then(|typeck_results| { | |
815 | typeck_results.borrow().node_type_opt(arm.body.hir_id) | |
816 | }) | |
817 | .and_then(|arm_ty| { | |
818 | if arm_ty.is_never() { | |
819 | None | |
820 | } else { | |
821 | Some(match &arm.body.kind { | |
822 | // Point at the tail expression when possible. | |
823 | hir::ExprKind::Block(block, _) => { | |
824 | block.expr.as_ref().map(|e| e.span).unwrap_or(block.span) | |
825 | } | |
826 | _ => arm.body.span, | |
827 | }) | |
828 | } | |
829 | }) | |
830 | }) | |
831 | .collect(); | |
832 | if arm_spans.len() == 1 { | |
833 | return arm_spans[0]; | |
834 | } | |
835 | } | |
836 | expr.span | |
837 | } | |
838 | ||
839 | fn overwrite_local_ty_if_err( | |
840 | &self, | |
841 | local: &'tcx hir::Local<'tcx>, | |
842 | decl_ty: Ty<'tcx>, | |
843 | ty: Ty<'tcx>, | |
844 | ) { | |
845 | if ty.references_error() { | |
846 | // Override the types everywhere with `err()` to avoid knock on errors. | |
847 | self.write_ty(local.hir_id, ty); | |
848 | self.write_ty(local.pat.hir_id, ty); | |
849 | let local_ty = LocalTy { decl_ty, revealed_ty: ty }; | |
850 | self.locals.borrow_mut().insert(local.hir_id, local_ty); | |
851 | self.locals.borrow_mut().insert(local.pat.hir_id, local_ty); | |
852 | } | |
853 | } | |
854 | ||
855 | // Finish resolving a path in a struct expression or pattern `S::A { .. }` if necessary. | |
856 | // The newly resolved definition is written into `type_dependent_defs`. | |
857 | fn finish_resolving_struct_path( | |
858 | &self, | |
859 | qpath: &QPath<'_>, | |
860 | path_span: Span, | |
861 | hir_id: hir::HirId, | |
862 | ) -> (Res, Ty<'tcx>) { | |
863 | match *qpath { | |
864 | QPath::Resolved(ref maybe_qself, ref path) => { | |
865 | let self_ty = maybe_qself.as_ref().map(|qself| self.to_ty(qself)); | |
866 | let ty = AstConv::res_to_ty(self, self_ty, path, true); | |
867 | (path.res, ty) | |
868 | } | |
869 | QPath::TypeRelative(ref qself, ref segment) => { | |
870 | let ty = self.to_ty(qself); | |
871 | ||
872 | let res = if let hir::TyKind::Path(QPath::Resolved(_, ref path)) = qself.kind { | |
873 | path.res | |
874 | } else { | |
875 | Res::Err | |
876 | }; | |
877 | let result = | |
878 | AstConv::associated_path_to_ty(self, hir_id, path_span, ty, res, segment, true); | |
879 | let ty = result.map(|(ty, _, _)| ty).unwrap_or_else(|_| self.tcx().ty_error()); | |
880 | let result = result.map(|(_, kind, def_id)| (kind, def_id)); | |
881 | ||
882 | // Write back the new resolution. | |
883 | self.write_resolution(hir_id, result); | |
884 | ||
885 | (result.map(|(kind, def_id)| Res::Def(kind, def_id)).unwrap_or(Res::Err), ty) | |
886 | } | |
887 | QPath::LangItem(lang_item, span) => { | |
888 | self.resolve_lang_item_path(lang_item, span, hir_id) | |
889 | } | |
890 | } | |
891 | } | |
892 | ||
893 | /// Given a vec of evaluated `FulfillmentError`s and an `fn` call argument expressions, we walk | |
894 | /// the checked and coerced types for each argument to see if any of the `FulfillmentError`s | |
895 | /// reference a type argument. The reason to walk also the checked type is that the coerced type | |
896 | /// can be not easily comparable with predicate type (because of coercion). If the types match | |
897 | /// for either checked or coerced type, and there's only *one* argument that does, we point at | |
898 | /// the corresponding argument's expression span instead of the `fn` call path span. | |
899 | fn point_at_arg_instead_of_call_if_possible( | |
900 | &self, | |
901 | errors: &mut Vec<traits::FulfillmentError<'tcx>>, | |
902 | final_arg_types: &[(usize, Ty<'tcx>, Ty<'tcx>)], | |
903 | call_sp: Span, | |
904 | args: &'tcx [hir::Expr<'tcx>], | |
905 | ) { | |
906 | // We *do not* do this for desugared call spans to keep good diagnostics when involving | |
907 | // the `?` operator. | |
908 | if call_sp.desugaring_kind().is_some() { | |
909 | return; | |
910 | } | |
911 | ||
912 | for error in errors { | |
913 | // Only if the cause is somewhere inside the expression we want try to point at arg. | |
914 | // Otherwise, it means that the cause is somewhere else and we should not change | |
915 | // anything because we can break the correct span. | |
916 | if !call_sp.contains(error.obligation.cause.span) { | |
917 | continue; | |
918 | } | |
919 | ||
920 | if let ty::PredicateAtom::Trait(predicate, _) = | |
921 | error.obligation.predicate.skip_binders() | |
922 | { | |
923 | // Collect the argument position for all arguments that could have caused this | |
924 | // `FulfillmentError`. | |
925 | let mut referenced_in = final_arg_types | |
926 | .iter() | |
927 | .map(|&(i, checked_ty, _)| (i, checked_ty)) | |
928 | .chain(final_arg_types.iter().map(|&(i, _, coerced_ty)| (i, coerced_ty))) | |
929 | .flat_map(|(i, ty)| { | |
fc512014 | 930 | let ty = self.resolve_vars_if_possible(ty); |
29967ef6 XL |
931 | // We walk the argument type because the argument's type could have |
932 | // been `Option<T>`, but the `FulfillmentError` references `T`. | |
933 | if ty.walk().any(|arg| arg == predicate.self_ty().into()) { | |
934 | Some(i) | |
935 | } else { | |
936 | None | |
937 | } | |
938 | }) | |
939 | .collect::<Vec<usize>>(); | |
940 | ||
941 | // Both checked and coerced types could have matched, thus we need to remove | |
942 | // duplicates. | |
943 | ||
944 | // We sort primitive type usize here and can use unstable sort | |
945 | referenced_in.sort_unstable(); | |
946 | referenced_in.dedup(); | |
947 | ||
948 | if let (Some(ref_in), None) = (referenced_in.pop(), referenced_in.pop()) { | |
949 | // We make sure that only *one* argument matches the obligation failure | |
950 | // and we assign the obligation's span to its expression's. | |
951 | error.obligation.cause.make_mut().span = args[ref_in].span; | |
952 | error.points_at_arg_span = true; | |
953 | } | |
954 | } | |
955 | } | |
956 | } | |
957 | ||
958 | /// Given a vec of evaluated `FulfillmentError`s and an `fn` call expression, we walk the | |
959 | /// `PathSegment`s and resolve their type parameters to see if any of the `FulfillmentError`s | |
960 | /// were caused by them. If they were, we point at the corresponding type argument's span | |
961 | /// instead of the `fn` call path span. | |
962 | fn point_at_type_arg_instead_of_call_if_possible( | |
963 | &self, | |
964 | errors: &mut Vec<traits::FulfillmentError<'tcx>>, | |
965 | call_expr: &'tcx hir::Expr<'tcx>, | |
966 | ) { | |
967 | if let hir::ExprKind::Call(path, _) = &call_expr.kind { | |
968 | if let hir::ExprKind::Path(qpath) = &path.kind { | |
969 | if let hir::QPath::Resolved(_, path) = &qpath { | |
970 | for error in errors { | |
971 | if let ty::PredicateAtom::Trait(predicate, _) = | |
972 | error.obligation.predicate.skip_binders() | |
973 | { | |
974 | // If any of the type arguments in this path segment caused the | |
975 | // `FullfillmentError`, point at its span (#61860). | |
976 | for arg in path | |
977 | .segments | |
978 | .iter() | |
979 | .filter_map(|seg| seg.args.as_ref()) | |
980 | .flat_map(|a| a.args.iter()) | |
981 | { | |
982 | if let hir::GenericArg::Type(hir_ty) = &arg { | |
983 | if let hir::TyKind::Path(hir::QPath::TypeRelative(..)) = | |
984 | &hir_ty.kind | |
985 | { | |
986 | // Avoid ICE with associated types. As this is best | |
987 | // effort only, it's ok to ignore the case. It | |
988 | // would trigger in `is_send::<T::AssocType>();` | |
989 | // from `typeck-default-trait-impl-assoc-type.rs`. | |
990 | } else { | |
991 | let ty = AstConv::ast_ty_to_ty(self, hir_ty); | |
fc512014 | 992 | let ty = self.resolve_vars_if_possible(ty); |
29967ef6 XL |
993 | if ty == predicate.self_ty() { |
994 | error.obligation.cause.make_mut().span = hir_ty.span; | |
995 | } | |
996 | } | |
997 | } | |
998 | } | |
999 | } | |
1000 | } | |
1001 | } | |
1002 | } | |
1003 | } | |
1004 | } | |
1005 | } |