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