]> git.lizzy.rs Git - rust.git/blob - compiler/rustc_hir_analysis/src/lib.rs
b7d9fc8a2fe272b71b7af99f9254708950300687
[rust.git] / compiler / rustc_hir_analysis / 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_and)]
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::TypeErrCtxtExt 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     let infcx = &tcx.infer_ctxt().build();
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.err_ctxt().report_mismatched_types(cause, expected, actual, err).emit();
150             return false;
151         }
152     };
153
154     match &errors[..] {
155         [] => true,
156         errors => {
157             infcx.err_ctxt().report_fulfillment_errors(errors, None, false);
158             false
159         }
160     }
161 }
162
163 fn check_main_fn_ty(tcx: TyCtxt<'_>, main_def_id: DefId) {
164     let main_fnsig = tcx.fn_sig(main_def_id);
165     let main_span = tcx.def_span(main_def_id);
166
167     fn main_fn_diagnostics_hir_id(tcx: TyCtxt<'_>, def_id: DefId, sp: Span) -> hir::HirId {
168         if let Some(local_def_id) = def_id.as_local() {
169             let hir_id = tcx.hir().local_def_id_to_hir_id(local_def_id);
170             let hir_type = tcx.type_of(local_def_id);
171             if !matches!(hir_type.kind(), ty::FnDef(..)) {
172                 span_bug!(sp, "main has a non-function type: found `{}`", hir_type);
173             }
174             hir_id
175         } else {
176             CRATE_HIR_ID
177         }
178     }
179
180     fn main_fn_generics_params_span(tcx: TyCtxt<'_>, def_id: DefId) -> Option<Span> {
181         if !def_id.is_local() {
182             return None;
183         }
184         let hir_id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local());
185         match tcx.hir().find(hir_id) {
186             Some(Node::Item(hir::Item { kind: hir::ItemKind::Fn(_, ref generics, _), .. })) => {
187                 if !generics.params.is_empty() {
188                     Some(generics.span)
189                 } else {
190                     None
191                 }
192             }
193             _ => {
194                 span_bug!(tcx.def_span(def_id), "main has a non-function type");
195             }
196         }
197     }
198
199     fn main_fn_where_clauses_span(tcx: TyCtxt<'_>, def_id: DefId) -> Option<Span> {
200         if !def_id.is_local() {
201             return None;
202         }
203         let hir_id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local());
204         match tcx.hir().find(hir_id) {
205             Some(Node::Item(hir::Item { kind: hir::ItemKind::Fn(_, ref generics, _), .. })) => {
206                 Some(generics.where_clause_span)
207             }
208             _ => {
209                 span_bug!(tcx.def_span(def_id), "main has a non-function type");
210             }
211         }
212     }
213
214     fn main_fn_asyncness_span(tcx: TyCtxt<'_>, def_id: DefId) -> Option<Span> {
215         if !def_id.is_local() {
216             return None;
217         }
218         Some(tcx.def_span(def_id))
219     }
220
221     fn main_fn_return_type_span(tcx: TyCtxt<'_>, def_id: DefId) -> Option<Span> {
222         if !def_id.is_local() {
223             return None;
224         }
225         let hir_id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local());
226         match tcx.hir().find(hir_id) {
227             Some(Node::Item(hir::Item { kind: hir::ItemKind::Fn(ref fn_sig, _, _), .. })) => {
228                 Some(fn_sig.decl.output.span())
229             }
230             _ => {
231                 span_bug!(tcx.def_span(def_id), "main has a non-function type");
232             }
233         }
234     }
235
236     let mut error = false;
237     let main_diagnostics_hir_id = main_fn_diagnostics_hir_id(tcx, main_def_id, main_span);
238     let main_fn_generics = tcx.generics_of(main_def_id);
239     let main_fn_predicates = tcx.predicates_of(main_def_id);
240     if main_fn_generics.count() != 0 || !main_fnsig.bound_vars().is_empty() {
241         let generics_param_span = main_fn_generics_params_span(tcx, main_def_id);
242         let msg = "`main` function is not allowed to have generic \
243             parameters";
244         let mut diag =
245             struct_span_err!(tcx.sess, generics_param_span.unwrap_or(main_span), E0131, "{}", msg);
246         if let Some(generics_param_span) = generics_param_span {
247             let label = "`main` cannot have generic parameters";
248             diag.span_label(generics_param_span, label);
249         }
250         diag.emit();
251         error = true;
252     } else if !main_fn_predicates.predicates.is_empty() {
253         // generics may bring in implicit predicates, so we skip this check if generics is present.
254         let generics_where_clauses_span = main_fn_where_clauses_span(tcx, main_def_id);
255         let mut diag = struct_span_err!(
256             tcx.sess,
257             generics_where_clauses_span.unwrap_or(main_span),
258             E0646,
259             "`main` function is not allowed to have a `where` clause"
260         );
261         if let Some(generics_where_clauses_span) = generics_where_clauses_span {
262             diag.span_label(generics_where_clauses_span, "`main` cannot have a `where` clause");
263         }
264         diag.emit();
265         error = true;
266     }
267
268     let main_asyncness = tcx.asyncness(main_def_id);
269     if let hir::IsAsync::Async = main_asyncness {
270         let mut diag = struct_span_err!(
271             tcx.sess,
272             main_span,
273             E0752,
274             "`main` function is not allowed to be `async`"
275         );
276         let asyncness_span = main_fn_asyncness_span(tcx, main_def_id);
277         if let Some(asyncness_span) = asyncness_span {
278             diag.span_label(asyncness_span, "`main` function is not allowed to be `async`");
279         }
280         diag.emit();
281         error = true;
282     }
283
284     for attr in tcx.get_attrs(main_def_id, sym::track_caller) {
285         tcx.sess
286             .struct_span_err(attr.span, "`main` function is not allowed to be `#[track_caller]`")
287             .span_label(main_span, "`main` function is not allowed to be `#[track_caller]`")
288             .emit();
289         error = true;
290     }
291
292     if error {
293         return;
294     }
295
296     let expected_return_type;
297     if let Some(term_did) = tcx.lang_items().termination() {
298         let return_ty = main_fnsig.output();
299         let return_ty_span = main_fn_return_type_span(tcx, main_def_id).unwrap_or(main_span);
300         if !return_ty.bound_vars().is_empty() {
301             let msg = "`main` function return type is not allowed to have generic \
302                     parameters";
303             struct_span_err!(tcx.sess, return_ty_span, E0131, "{}", msg).emit();
304             error = true;
305         }
306         let return_ty = return_ty.skip_binder();
307         let infcx = tcx.infer_ctxt().build();
308         // Main should have no WC, so empty param env is OK here.
309         let param_env = ty::ParamEnv::empty();
310         let cause = traits::ObligationCause::new(
311             return_ty_span,
312             main_diagnostics_hir_id,
313             ObligationCauseCode::MainFunctionType,
314         );
315         let ocx = traits::ObligationCtxt::new(&infcx);
316         let norm_return_ty = ocx.normalize(cause.clone(), param_env, return_ty);
317         ocx.register_bound(cause, param_env, norm_return_ty, term_did);
318         let errors = ocx.select_all_or_error();
319         if !errors.is_empty() {
320             infcx.err_ctxt().report_fulfillment_errors(&errors, None, false);
321             error = true;
322         }
323         // now we can take the return type of the given main function
324         expected_return_type = main_fnsig.output();
325     } else {
326         // standard () main return type
327         expected_return_type = ty::Binder::dummy(tcx.mk_unit());
328     }
329
330     if error {
331         return;
332     }
333
334     let se_ty = tcx.mk_fn_ptr(expected_return_type.map_bound(|expected_return_type| {
335         tcx.mk_fn_sig(iter::empty(), expected_return_type, false, hir::Unsafety::Normal, Abi::Rust)
336     }));
337
338     require_same_types(
339         tcx,
340         &ObligationCause::new(
341             main_span,
342             main_diagnostics_hir_id,
343             ObligationCauseCode::MainFunctionType,
344         ),
345         se_ty,
346         tcx.mk_fn_ptr(main_fnsig),
347     );
348 }
349 fn check_start_fn_ty(tcx: TyCtxt<'_>, start_def_id: DefId) {
350     let start_def_id = start_def_id.expect_local();
351     let start_id = tcx.hir().local_def_id_to_hir_id(start_def_id);
352     let start_span = tcx.def_span(start_def_id);
353     let start_t = tcx.type_of(start_def_id);
354     match start_t.kind() {
355         ty::FnDef(..) => {
356             if let Some(Node::Item(it)) = tcx.hir().find(start_id) {
357                 if let hir::ItemKind::Fn(ref sig, ref generics, _) = it.kind {
358                     let mut error = false;
359                     if !generics.params.is_empty() {
360                         struct_span_err!(
361                             tcx.sess,
362                             generics.span,
363                             E0132,
364                             "start function is not allowed to have type parameters"
365                         )
366                         .span_label(generics.span, "start function cannot have type parameters")
367                         .emit();
368                         error = true;
369                     }
370                     if generics.has_where_clause_predicates {
371                         struct_span_err!(
372                             tcx.sess,
373                             generics.where_clause_span,
374                             E0647,
375                             "start function is not allowed to have a `where` clause"
376                         )
377                         .span_label(
378                             generics.where_clause_span,
379                             "start function cannot have a `where` clause",
380                         )
381                         .emit();
382                         error = true;
383                     }
384                     if let hir::IsAsync::Async = sig.header.asyncness {
385                         let span = tcx.def_span(it.def_id);
386                         struct_span_err!(
387                             tcx.sess,
388                             span,
389                             E0752,
390                             "`start` is not allowed to be `async`"
391                         )
392                         .span_label(span, "`start` is not allowed to be `async`")
393                         .emit();
394                         error = true;
395                     }
396
397                     let attrs = tcx.hir().attrs(start_id);
398                     for attr in attrs {
399                         if attr.has_name(sym::track_caller) {
400                             tcx.sess
401                                 .struct_span_err(
402                                     attr.span,
403                                     "`start` is not allowed to be `#[track_caller]`",
404                                 )
405                                 .span_label(
406                                     start_span,
407                                     "`start` is not allowed to be `#[track_caller]`",
408                                 )
409                                 .emit();
410                             error = true;
411                         }
412                     }
413
414                     if error {
415                         return;
416                     }
417                 }
418             }
419
420             let se_ty = tcx.mk_fn_ptr(ty::Binder::dummy(tcx.mk_fn_sig(
421                 [tcx.types.isize, tcx.mk_imm_ptr(tcx.mk_imm_ptr(tcx.types.u8))].iter().cloned(),
422                 tcx.types.isize,
423                 false,
424                 hir::Unsafety::Normal,
425                 Abi::Rust,
426             )));
427
428             require_same_types(
429                 tcx,
430                 &ObligationCause::new(start_span, start_id, ObligationCauseCode::StartFunctionType),
431                 se_ty,
432                 tcx.mk_fn_ptr(tcx.fn_sig(start_def_id)),
433             );
434         }
435         _ => {
436             span_bug!(start_span, "start has a non-function type: found `{}`", start_t);
437         }
438     }
439 }
440
441 fn check_for_entry_fn(tcx: TyCtxt<'_>) {
442     match tcx.entry_fn(()) {
443         Some((def_id, EntryFnType::Main { .. })) => check_main_fn_ty(tcx, def_id),
444         Some((def_id, EntryFnType::Start)) => check_start_fn_ty(tcx, def_id),
445         _ => {}
446     }
447 }
448
449 pub fn provide(providers: &mut Providers) {
450     collect::provide(providers);
451     coherence::provide(providers);
452     check::provide(providers);
453     variance::provide(providers);
454     outlives::provide(providers);
455     impl_wf_check::provide(providers);
456     hir_wf_check::provide(providers);
457 }
458
459 pub fn check_crate(tcx: TyCtxt<'_>) -> Result<(), ErrorGuaranteed> {
460     let _prof_timer = tcx.sess.timer("type_check_crate");
461
462     // this ensures that later parts of type checking can assume that items
463     // have valid types and not error
464     // FIXME(matthewjasper) We shouldn't need to use `track_errors`.
465     tcx.sess.track_errors(|| {
466         tcx.sess.time("type_collecting", || {
467             tcx.hir().for_each_module(|module| tcx.ensure().collect_mod_item_types(module))
468         });
469     })?;
470
471     if tcx.features().rustc_attrs {
472         tcx.sess.track_errors(|| {
473             tcx.sess.time("outlives_testing", || outlives::test::test_inferred_outlives(tcx));
474         })?;
475     }
476
477     tcx.sess.track_errors(|| {
478         tcx.sess.time("impl_wf_inference", || {
479             tcx.hir().for_each_module(|module| tcx.ensure().check_mod_impl_wf(module))
480         });
481     })?;
482
483     tcx.sess.track_errors(|| {
484         tcx.sess.time("coherence_checking", || {
485             for &trait_def_id in tcx.all_local_trait_impls(()).keys() {
486                 tcx.ensure().coherent_trait(trait_def_id);
487             }
488
489             // these queries are executed for side-effects (error reporting):
490             tcx.ensure().crate_inherent_impls(());
491             tcx.ensure().crate_inherent_impls_overlap_check(());
492         });
493     })?;
494
495     if tcx.features().rustc_attrs {
496         tcx.sess.track_errors(|| {
497             tcx.sess.time("variance_testing", || variance::test::test_variance(tcx));
498         })?;
499     }
500
501     tcx.sess.track_errors(|| {
502         tcx.sess.time("wf_checking", || {
503             tcx.hir().par_for_each_module(|module| tcx.ensure().check_mod_type_wf(module))
504         });
505     })?;
506
507     // NOTE: This is copy/pasted in librustdoc/core.rs and should be kept in sync.
508     tcx.sess.time("item_types_checking", || {
509         tcx.hir().for_each_module(|module| tcx.ensure().check_mod_item_types(module))
510     });
511
512     tcx.sess.time("item_bodies_checking", || tcx.typeck_item_bodies(()));
513
514     check_unused::check_crate(tcx);
515     check_for_entry_fn(tcx);
516
517     if let Some(reported) = tcx.sess.has_errors() { Err(reported) } else { Ok(()) }
518 }
519
520 /// A quasi-deprecated helper used in rustdoc and clippy to get
521 /// the type from a HIR node.
522 pub fn hir_ty_to_ty<'tcx>(tcx: TyCtxt<'tcx>, hir_ty: &hir::Ty<'_>) -> Ty<'tcx> {
523     // In case there are any projections, etc., find the "environment"
524     // def-ID that will be used to determine the traits/predicates in
525     // scope.  This is derived from the enclosing item-like thing.
526     let env_def_id = tcx.hir().get_parent_item(hir_ty.hir_id);
527     let item_cx = self::collect::ItemCtxt::new(tcx, env_def_id.to_def_id());
528     <dyn AstConv<'_>>::ast_ty_to_ty(&item_cx, hir_ty)
529 }
530
531 pub fn hir_trait_to_predicates<'tcx>(
532     tcx: TyCtxt<'tcx>,
533     hir_trait: &hir::TraitRef<'_>,
534     self_ty: Ty<'tcx>,
535 ) -> Bounds<'tcx> {
536     // In case there are any projections, etc., find the "environment"
537     // def-ID that will be used to determine the traits/predicates in
538     // scope.  This is derived from the enclosing item-like thing.
539     let env_def_id = tcx.hir().get_parent_item(hir_trait.hir_ref_id);
540     let item_cx = self::collect::ItemCtxt::new(tcx, env_def_id.to_def_id());
541     let mut bounds = Bounds::default();
542     let _ = <dyn AstConv<'_>>::instantiate_poly_trait_ref(
543         &item_cx,
544         hir_trait,
545         DUMMY_SP,
546         ty::BoundConstness::NotConst,
547         self_ty,
548         &mut bounds,
549         true,
550     );
551
552     bounds
553 }