]> git.lizzy.rs Git - rust.git/blob - compiler/rustc_typeck/src/lib.rs
Auto merge of #102189 - davidtwco:translation-derive-enums, r=compiler-errors
[rust.git] / compiler / rustc_typeck / src / lib.rs
1 /*!
2
3 # typeck
4
5 The type checker is responsible for:
6
7 1. Determining the type of each expression.
8 2. Resolving methods and traits.
9 3. Guaranteeing that most type rules are met. ("Most?", you say, "why most?"
10    Well, dear reader, read on.)
11
12 The main entry point is [`check_crate()`]. Type checking operates in
13 several major phases:
14
15 1. The collect phase first passes over all items and determines their
16    type, without examining their "innards".
17
18 2. Variance inference then runs to compute the variance of each parameter.
19
20 3. Coherence checks for overlapping or orphaned impls.
21
22 4. Finally, the check phase then checks function bodies and so forth.
23    Within the check phase, we check each function body one at a time
24    (bodies of function expressions are checked as part of the
25    containing function).  Inference is used to supply types wherever
26    they are unknown. The actual checking of a function itself has
27    several phases (check, regionck, writeback), as discussed in the
28    documentation for the [`check`] module.
29
30 The type checker is defined into various submodules which are documented
31 independently:
32
33 - astconv: converts the AST representation of types
34   into the `ty` representation.
35
36 - collect: computes the types of each top-level item and enters them into
37   the `tcx.types` table for later use.
38
39 - coherence: enforces coherence rules, builds some tables.
40
41 - variance: variance inference
42
43 - outlives: outlives inference
44
45 - check: walks over function bodies and type checks them, inferring types for
46   local variables, type parameters, etc as necessary.
47
48 - infer: finds the types to use for each type variable such that
49   all subtyping and assignment constraints are met.  In essence, the check
50   module specifies the constraints, and the infer module solves them.
51
52 ## Note
53
54 This API is completely unstable and subject to change.
55
56 */
57
58 #![allow(rustc::potential_query_instability)]
59 #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
60 #![feature(box_patterns)]
61 #![feature(control_flow_enum)]
62 #![feature(drain_filter)]
63 #![feature(hash_drain_filter)]
64 #![feature(if_let_guard)]
65 #![feature(is_sorted)]
66 #![feature(iter_intersperse)]
67 #![feature(let_chains)]
68 #![feature(min_specialization)]
69 #![feature(never_type)]
70 #![feature(once_cell)]
71 #![feature(slice_partition_dedup)]
72 #![feature(try_blocks)]
73 #![feature(is_some_with)]
74 #![feature(type_alias_impl_trait)]
75 #![recursion_limit = "256"]
76
77 #[macro_use]
78 extern crate tracing;
79
80 #[macro_use]
81 extern crate rustc_middle;
82
83 // These are used by Clippy.
84 pub mod check;
85 pub mod expr_use_visitor;
86
87 mod astconv;
88 mod bounds;
89 mod check_unused;
90 mod coherence;
91 mod collect;
92 mod constrained_generic_params;
93 mod errors;
94 pub mod hir_wf_check;
95 mod impl_wf_check;
96 mod mem_categorization;
97 mod outlives;
98 mod structured_errors;
99 mod variance;
100
101 use rustc_errors::{struct_span_err, ErrorGuaranteed};
102 use rustc_hir as hir;
103 use rustc_hir::def_id::DefId;
104 use rustc_hir::{Node, CRATE_HIR_ID};
105 use rustc_infer::infer::{InferOk, TyCtxtInferExt};
106 use rustc_middle::middle;
107 use rustc_middle::ty::query::Providers;
108 use rustc_middle::ty::{self, Ty, TyCtxt};
109 use rustc_middle::util;
110 use rustc_session::config::EntryFnType;
111 use rustc_span::{symbol::sym, Span, DUMMY_SP};
112 use rustc_target::spec::abi::Abi;
113 use rustc_trait_selection::traits::error_reporting::InferCtxtExt as _;
114 use rustc_trait_selection::traits::{self, ObligationCause, ObligationCauseCode};
115
116 use std::iter;
117
118 use astconv::AstConv;
119 use bounds::Bounds;
120
121 fn require_c_abi_if_c_variadic(tcx: TyCtxt<'_>, decl: &hir::FnDecl<'_>, abi: Abi, span: Span) {
122     match (decl.c_variadic, abi) {
123         // The function has the correct calling convention, or isn't a "C-variadic" function.
124         (false, _) | (true, Abi::C { .. }) | (true, Abi::Cdecl { .. }) => {}
125         // The function is a "C-variadic" function with an incorrect calling convention.
126         (true, _) => {
127             let mut err = struct_span_err!(
128                 tcx.sess,
129                 span,
130                 E0045,
131                 "C-variadic function must have C or cdecl calling convention"
132             );
133             err.span_label(span, "C-variadics require C or cdecl calling convention").emit();
134         }
135     }
136 }
137
138 fn require_same_types<'tcx>(
139     tcx: TyCtxt<'tcx>,
140     cause: &ObligationCause<'tcx>,
141     expected: Ty<'tcx>,
142     actual: Ty<'tcx>,
143 ) -> bool {
144     tcx.infer_ctxt().enter(|ref infcx| {
145         let param_env = ty::ParamEnv::empty();
146         let errors = match infcx.at(cause, param_env).eq(expected, actual) {
147             Ok(InferOk { obligations, .. }) => traits::fully_solve_obligations(infcx, obligations),
148             Err(err) => {
149                 infcx.report_mismatched_types(cause, expected, actual, err).emit();
150                 return false;
151             }
152         };
153
154         match &errors[..] {
155             [] => true,
156             errors => {
157                 infcx.report_fulfillment_errors(errors, None, false);
158                 false
159             }
160         }
161     })
162 }
163
164 fn check_main_fn_ty(tcx: TyCtxt<'_>, main_def_id: DefId) {
165     let main_fnsig = tcx.fn_sig(main_def_id);
166     let main_span = tcx.def_span(main_def_id);
167
168     fn main_fn_diagnostics_hir_id(tcx: TyCtxt<'_>, def_id: DefId, sp: Span) -> hir::HirId {
169         if let Some(local_def_id) = def_id.as_local() {
170             let hir_id = tcx.hir().local_def_id_to_hir_id(local_def_id);
171             let hir_type = tcx.type_of(local_def_id);
172             if !matches!(hir_type.kind(), ty::FnDef(..)) {
173                 span_bug!(sp, "main has a non-function type: found `{}`", hir_type);
174             }
175             hir_id
176         } else {
177             CRATE_HIR_ID
178         }
179     }
180
181     fn main_fn_generics_params_span(tcx: TyCtxt<'_>, def_id: DefId) -> Option<Span> {
182         if !def_id.is_local() {
183             return None;
184         }
185         let hir_id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local());
186         match tcx.hir().find(hir_id) {
187             Some(Node::Item(hir::Item { kind: hir::ItemKind::Fn(_, ref generics, _), .. })) => {
188                 if !generics.params.is_empty() {
189                     Some(generics.span)
190                 } else {
191                     None
192                 }
193             }
194             _ => {
195                 span_bug!(tcx.def_span(def_id), "main has a non-function type");
196             }
197         }
198     }
199
200     fn main_fn_where_clauses_span(tcx: TyCtxt<'_>, def_id: DefId) -> Option<Span> {
201         if !def_id.is_local() {
202             return None;
203         }
204         let hir_id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local());
205         match tcx.hir().find(hir_id) {
206             Some(Node::Item(hir::Item { kind: hir::ItemKind::Fn(_, ref generics, _), .. })) => {
207                 Some(generics.where_clause_span)
208             }
209             _ => {
210                 span_bug!(tcx.def_span(def_id), "main has a non-function type");
211             }
212         }
213     }
214
215     fn main_fn_asyncness_span(tcx: TyCtxt<'_>, def_id: DefId) -> Option<Span> {
216         if !def_id.is_local() {
217             return None;
218         }
219         Some(tcx.def_span(def_id))
220     }
221
222     fn main_fn_return_type_span(tcx: TyCtxt<'_>, def_id: DefId) -> Option<Span> {
223         if !def_id.is_local() {
224             return None;
225         }
226         let hir_id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local());
227         match tcx.hir().find(hir_id) {
228             Some(Node::Item(hir::Item { kind: hir::ItemKind::Fn(ref fn_sig, _, _), .. })) => {
229                 Some(fn_sig.decl.output.span())
230             }
231             _ => {
232                 span_bug!(tcx.def_span(def_id), "main has a non-function type");
233             }
234         }
235     }
236
237     let mut error = false;
238     let main_diagnostics_hir_id = main_fn_diagnostics_hir_id(tcx, main_def_id, main_span);
239     let main_fn_generics = tcx.generics_of(main_def_id);
240     let main_fn_predicates = tcx.predicates_of(main_def_id);
241     if main_fn_generics.count() != 0 || !main_fnsig.bound_vars().is_empty() {
242         let generics_param_span = main_fn_generics_params_span(tcx, main_def_id);
243         let msg = "`main` function is not allowed to have generic \
244             parameters";
245         let mut diag =
246             struct_span_err!(tcx.sess, generics_param_span.unwrap_or(main_span), E0131, "{}", msg);
247         if let Some(generics_param_span) = generics_param_span {
248             let label = "`main` cannot have generic parameters";
249             diag.span_label(generics_param_span, label);
250         }
251         diag.emit();
252         error = true;
253     } else if !main_fn_predicates.predicates.is_empty() {
254         // generics may bring in implicit predicates, so we skip this check if generics is present.
255         let generics_where_clauses_span = main_fn_where_clauses_span(tcx, main_def_id);
256         let mut diag = struct_span_err!(
257             tcx.sess,
258             generics_where_clauses_span.unwrap_or(main_span),
259             E0646,
260             "`main` function is not allowed to have a `where` clause"
261         );
262         if let Some(generics_where_clauses_span) = generics_where_clauses_span {
263             diag.span_label(generics_where_clauses_span, "`main` cannot have a `where` clause");
264         }
265         diag.emit();
266         error = true;
267     }
268
269     let main_asyncness = tcx.asyncness(main_def_id);
270     if let hir::IsAsync::Async = main_asyncness {
271         let mut diag = struct_span_err!(
272             tcx.sess,
273             main_span,
274             E0752,
275             "`main` function is not allowed to be `async`"
276         );
277         let asyncness_span = main_fn_asyncness_span(tcx, main_def_id);
278         if let Some(asyncness_span) = asyncness_span {
279             diag.span_label(asyncness_span, "`main` function is not allowed to be `async`");
280         }
281         diag.emit();
282         error = true;
283     }
284
285     for attr in tcx.get_attrs(main_def_id, sym::track_caller) {
286         tcx.sess
287             .struct_span_err(attr.span, "`main` function is not allowed to be `#[track_caller]`")
288             .span_label(main_span, "`main` function is not allowed to be `#[track_caller]`")
289             .emit();
290         error = true;
291     }
292
293     if error {
294         return;
295     }
296
297     let expected_return_type;
298     if let Some(term_did) = tcx.lang_items().termination() {
299         let return_ty = main_fnsig.output();
300         let return_ty_span = main_fn_return_type_span(tcx, main_def_id).unwrap_or(main_span);
301         if !return_ty.bound_vars().is_empty() {
302             let msg = "`main` function return type is not allowed to have generic \
303                     parameters";
304             struct_span_err!(tcx.sess, return_ty_span, E0131, "{}", msg).emit();
305             error = true;
306         }
307         let return_ty = return_ty.skip_binder();
308         tcx.infer_ctxt().enter(|infcx| {
309             // Main should have no WC, so empty param env is OK here.
310             let param_env = ty::ParamEnv::empty();
311             let cause = traits::ObligationCause::new(
312                 return_ty_span,
313                 main_diagnostics_hir_id,
314                 ObligationCauseCode::MainFunctionType,
315             );
316             let ocx = traits::ObligationCtxt::new(&infcx);
317             let norm_return_ty = ocx.normalize(cause.clone(), param_env, return_ty);
318             ocx.register_bound(cause, param_env, norm_return_ty, term_did);
319             let errors = ocx.select_all_or_error();
320             if !errors.is_empty() {
321                 infcx.report_fulfillment_errors(&errors, None, false);
322                 error = true;
323             }
324         });
325         // now we can take the return type of the given main function
326         expected_return_type = main_fnsig.output();
327     } else {
328         // standard () main return type
329         expected_return_type = ty::Binder::dummy(tcx.mk_unit());
330     }
331
332     if error {
333         return;
334     }
335
336     let se_ty = tcx.mk_fn_ptr(expected_return_type.map_bound(|expected_return_type| {
337         tcx.mk_fn_sig(iter::empty(), expected_return_type, false, hir::Unsafety::Normal, Abi::Rust)
338     }));
339
340     require_same_types(
341         tcx,
342         &ObligationCause::new(
343             main_span,
344             main_diagnostics_hir_id,
345             ObligationCauseCode::MainFunctionType,
346         ),
347         se_ty,
348         tcx.mk_fn_ptr(main_fnsig),
349     );
350 }
351 fn check_start_fn_ty(tcx: TyCtxt<'_>, start_def_id: DefId) {
352     let start_def_id = start_def_id.expect_local();
353     let start_id = tcx.hir().local_def_id_to_hir_id(start_def_id);
354     let start_span = tcx.def_span(start_def_id);
355     let start_t = tcx.type_of(start_def_id);
356     match start_t.kind() {
357         ty::FnDef(..) => {
358             if let Some(Node::Item(it)) = tcx.hir().find(start_id) {
359                 if let hir::ItemKind::Fn(ref sig, ref generics, _) = it.kind {
360                     let mut error = false;
361                     if !generics.params.is_empty() {
362                         struct_span_err!(
363                             tcx.sess,
364                             generics.span,
365                             E0132,
366                             "start function is not allowed to have type parameters"
367                         )
368                         .span_label(generics.span, "start function cannot have type parameters")
369                         .emit();
370                         error = true;
371                     }
372                     if generics.has_where_clause_predicates {
373                         struct_span_err!(
374                             tcx.sess,
375                             generics.where_clause_span,
376                             E0647,
377                             "start function is not allowed to have a `where` clause"
378                         )
379                         .span_label(
380                             generics.where_clause_span,
381                             "start function cannot have a `where` clause",
382                         )
383                         .emit();
384                         error = true;
385                     }
386                     if let hir::IsAsync::Async = sig.header.asyncness {
387                         let span = tcx.def_span(it.def_id);
388                         struct_span_err!(
389                             tcx.sess,
390                             span,
391                             E0752,
392                             "`start` is not allowed to be `async`"
393                         )
394                         .span_label(span, "`start` is not allowed to be `async`")
395                         .emit();
396                         error = true;
397                     }
398
399                     let attrs = tcx.hir().attrs(start_id);
400                     for attr in attrs {
401                         if attr.has_name(sym::track_caller) {
402                             tcx.sess
403                                 .struct_span_err(
404                                     attr.span,
405                                     "`start` is not allowed to be `#[track_caller]`",
406                                 )
407                                 .span_label(
408                                     start_span,
409                                     "`start` is not allowed to be `#[track_caller]`",
410                                 )
411                                 .emit();
412                             error = true;
413                         }
414                     }
415
416                     if error {
417                         return;
418                     }
419                 }
420             }
421
422             let se_ty = tcx.mk_fn_ptr(ty::Binder::dummy(tcx.mk_fn_sig(
423                 [tcx.types.isize, tcx.mk_imm_ptr(tcx.mk_imm_ptr(tcx.types.u8))].iter().cloned(),
424                 tcx.types.isize,
425                 false,
426                 hir::Unsafety::Normal,
427                 Abi::Rust,
428             )));
429
430             require_same_types(
431                 tcx,
432                 &ObligationCause::new(start_span, start_id, ObligationCauseCode::StartFunctionType),
433                 se_ty,
434                 tcx.mk_fn_ptr(tcx.fn_sig(start_def_id)),
435             );
436         }
437         _ => {
438             span_bug!(start_span, "start has a non-function type: found `{}`", start_t);
439         }
440     }
441 }
442
443 fn check_for_entry_fn(tcx: TyCtxt<'_>) {
444     match tcx.entry_fn(()) {
445         Some((def_id, EntryFnType::Main { .. })) => check_main_fn_ty(tcx, def_id),
446         Some((def_id, EntryFnType::Start)) => check_start_fn_ty(tcx, def_id),
447         _ => {}
448     }
449 }
450
451 pub fn provide(providers: &mut Providers) {
452     collect::provide(providers);
453     coherence::provide(providers);
454     check::provide(providers);
455     variance::provide(providers);
456     outlives::provide(providers);
457     impl_wf_check::provide(providers);
458     hir_wf_check::provide(providers);
459 }
460
461 pub fn check_crate(tcx: TyCtxt<'_>) -> Result<(), ErrorGuaranteed> {
462     let _prof_timer = tcx.sess.timer("type_check_crate");
463
464     // this ensures that later parts of type checking can assume that items
465     // have valid types and not error
466     // FIXME(matthewjasper) We shouldn't need to use `track_errors`.
467     tcx.sess.track_errors(|| {
468         tcx.sess.time("type_collecting", || {
469             tcx.hir().for_each_module(|module| tcx.ensure().collect_mod_item_types(module))
470         });
471     })?;
472
473     if tcx.features().rustc_attrs {
474         tcx.sess.track_errors(|| {
475             tcx.sess.time("outlives_testing", || outlives::test::test_inferred_outlives(tcx));
476         })?;
477     }
478
479     tcx.sess.track_errors(|| {
480         tcx.sess.time("impl_wf_inference", || {
481             tcx.hir().for_each_module(|module| tcx.ensure().check_mod_impl_wf(module))
482         });
483     })?;
484
485     tcx.sess.track_errors(|| {
486         tcx.sess.time("coherence_checking", || {
487             for &trait_def_id in tcx.all_local_trait_impls(()).keys() {
488                 tcx.ensure().coherent_trait(trait_def_id);
489             }
490
491             // these queries are executed for side-effects (error reporting):
492             tcx.ensure().crate_inherent_impls(());
493             tcx.ensure().crate_inherent_impls_overlap_check(());
494         });
495     })?;
496
497     if tcx.features().rustc_attrs {
498         tcx.sess.track_errors(|| {
499             tcx.sess.time("variance_testing", || variance::test::test_variance(tcx));
500         })?;
501     }
502
503     tcx.sess.track_errors(|| {
504         tcx.sess.time("wf_checking", || {
505             tcx.hir().par_for_each_module(|module| tcx.ensure().check_mod_type_wf(module))
506         });
507     })?;
508
509     // NOTE: This is copy/pasted in librustdoc/core.rs and should be kept in sync.
510     tcx.sess.time("item_types_checking", || {
511         tcx.hir().for_each_module(|module| tcx.ensure().check_mod_item_types(module))
512     });
513
514     tcx.sess.time("item_bodies_checking", || tcx.typeck_item_bodies(()));
515
516     check_unused::check_crate(tcx);
517     check_for_entry_fn(tcx);
518
519     if let Some(reported) = tcx.sess.has_errors() { Err(reported) } else { Ok(()) }
520 }
521
522 /// A quasi-deprecated helper used in rustdoc and clippy to get
523 /// the type from a HIR node.
524 pub fn hir_ty_to_ty<'tcx>(tcx: TyCtxt<'tcx>, hir_ty: &hir::Ty<'_>) -> Ty<'tcx> {
525     // In case there are any projections, etc., find the "environment"
526     // def-ID that will be used to determine the traits/predicates in
527     // scope.  This is derived from the enclosing item-like thing.
528     let env_def_id = tcx.hir().get_parent_item(hir_ty.hir_id);
529     let item_cx = self::collect::ItemCtxt::new(tcx, env_def_id.to_def_id());
530     <dyn AstConv<'_>>::ast_ty_to_ty(&item_cx, hir_ty)
531 }
532
533 pub fn hir_trait_to_predicates<'tcx>(
534     tcx: TyCtxt<'tcx>,
535     hir_trait: &hir::TraitRef<'_>,
536     self_ty: Ty<'tcx>,
537 ) -> Bounds<'tcx> {
538     // In case there are any projections, etc., find the "environment"
539     // def-ID that will be used to determine the traits/predicates in
540     // scope.  This is derived from the enclosing item-like thing.
541     let env_def_id = tcx.hir().get_parent_item(hir_trait.hir_ref_id);
542     let item_cx = self::collect::ItemCtxt::new(tcx, env_def_id.to_def_id());
543     let mut bounds = Bounds::default();
544     let _ = <dyn AstConv<'_>>::instantiate_poly_trait_ref(
545         &item_cx,
546         hir_trait,
547         DUMMY_SP,
548         ty::BoundConstness::NotConst,
549         self_ty,
550         &mut bounds,
551         true,
552     );
553
554     bounds
555 }