]> git.lizzy.rs Git - rust.git/blob - compiler/rustc_typeck/src/lib.rs
Rollup merge of #87646 - JohnTitor:fix-parser-ice, r=oli-obk
[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 #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
59 #![cfg_attr(bootstrap, feature(bindings_after_at))]
60 #![feature(bool_to_option)]
61 #![feature(box_syntax)]
62 #![feature(crate_visibility_modifier)]
63 #![feature(format_args_capture)]
64 #![feature(in_band_lifetimes)]
65 #![feature(is_sorted)]
66 #![feature(iter_zip)]
67 #![feature(nll)]
68 #![feature(try_blocks)]
69 #![feature(never_type)]
70 #![feature(slice_partition_dedup)]
71 #![feature(control_flow_enum)]
72 #![recursion_limit = "256"]
73
74 #[macro_use]
75 extern crate tracing;
76
77 #[macro_use]
78 extern crate rustc_middle;
79
80 // These are used by Clippy.
81 pub mod check;
82 pub mod expr_use_visitor;
83
84 mod astconv;
85 mod bounds;
86 mod check_unused;
87 mod coherence;
88 mod collect;
89 mod constrained_generic_params;
90 mod errors;
91 pub mod hir_wf_check;
92 mod impl_wf_check;
93 mod mem_categorization;
94 mod outlives;
95 mod structured_errors;
96 mod variance;
97
98 use rustc_errors::{struct_span_err, ErrorReported};
99 use rustc_hir as hir;
100 use rustc_hir::def_id::DefId;
101 use rustc_hir::{Node, CRATE_HIR_ID};
102 use rustc_infer::infer::{InferOk, TyCtxtInferExt};
103 use rustc_infer::traits::TraitEngineExt as _;
104 use rustc_middle::middle;
105 use rustc_middle::ty::query::Providers;
106 use rustc_middle::ty::{self, Ty, TyCtxt};
107 use rustc_middle::util;
108 use rustc_session::config::EntryFnType;
109 use rustc_span::{symbol::sym, Span, DUMMY_SP};
110 use rustc_target::spec::abi::Abi;
111 use rustc_trait_selection::traits::error_reporting::InferCtxtExt as _;
112 use rustc_trait_selection::traits::{
113     self, ObligationCause, ObligationCauseCode, TraitEngine, TraitEngineExt as _,
114 };
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 mut fulfill_cx = <dyn TraitEngine<'_>>::new(infcx.tcx);
147         match infcx.at(&cause, param_env).eq(expected, actual) {
148             Ok(InferOk { obligations, .. }) => {
149                 fulfill_cx.register_predicate_obligations(infcx, obligations);
150             }
151             Err(err) => {
152                 infcx.report_mismatched_types(cause, expected, actual, err).emit();
153                 return false;
154             }
155         }
156
157         match fulfill_cx.select_all_or_error(infcx) {
158             Ok(()) => true,
159             Err(errors) => {
160                 infcx.report_fulfillment_errors(&errors, None, false);
161                 false
162             }
163         }
164     })
165 }
166
167 fn check_main_fn_ty(tcx: TyCtxt<'_>, main_def_id: DefId) {
168     let main_fnsig = tcx.fn_sig(main_def_id);
169     let main_span = tcx.def_span(main_def_id);
170
171     fn main_fn_diagnostics_hir_id(tcx: TyCtxt<'_>, def_id: DefId, sp: Span) -> hir::HirId {
172         if let Some(local_def_id) = def_id.as_local() {
173             let hir_id = tcx.hir().local_def_id_to_hir_id(local_def_id);
174             let hir_type = tcx.type_of(local_def_id);
175             if !matches!(hir_type.kind(), ty::FnDef(..)) {
176                 span_bug!(sp, "main has a non-function type: found `{}`", hir_type);
177             }
178             hir_id
179         } else {
180             CRATE_HIR_ID
181         }
182     }
183
184     fn main_fn_generics_params_span(tcx: TyCtxt<'_>, def_id: DefId) -> Option<Span> {
185         if !def_id.is_local() {
186             return None;
187         }
188         let hir_id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local());
189         match tcx.hir().find(hir_id) {
190             Some(Node::Item(hir::Item { kind: hir::ItemKind::Fn(_, ref generics, _), .. })) => {
191                 let generics_param_span =
192                     if !generics.params.is_empty() { Some(generics.span) } else { None };
193                 generics_param_span
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                 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         let hir_id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local());
221         match tcx.hir().find(hir_id) {
222             Some(Node::Item(hir::Item { span: item_span, .. })) => {
223                 Some(tcx.sess.source_map().guess_head_span(*item_span))
224             }
225             _ => {
226                 span_bug!(tcx.def_span(def_id), "main has a non-function type");
227             }
228         }
229     }
230
231     fn main_fn_return_type_span(tcx: TyCtxt<'_>, def_id: DefId) -> Option<Span> {
232         if !def_id.is_local() {
233             return None;
234         }
235         let hir_id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local());
236         match tcx.hir().find(hir_id) {
237             Some(Node::Item(hir::Item { kind: hir::ItemKind::Fn(ref fn_sig, _, _), .. })) => {
238                 Some(fn_sig.decl.output.span())
239             }
240             _ => {
241                 span_bug!(tcx.def_span(def_id), "main has a non-function type");
242             }
243         }
244     }
245
246     let mut error = false;
247     let main_diagnostics_hir_id = main_fn_diagnostics_hir_id(tcx, main_def_id, main_span);
248     let main_fn_generics = tcx.generics_of(main_def_id);
249     let main_fn_predicates = tcx.predicates_of(main_def_id);
250     if main_fn_generics.count() != 0 || !main_fnsig.bound_vars().is_empty() {
251         let generics_param_span = main_fn_generics_params_span(tcx, main_def_id);
252         let msg = "`main` function is not allowed to have generic \
253             parameters";
254         let mut diag =
255             struct_span_err!(tcx.sess, generics_param_span.unwrap_or(main_span), E0131, "{}", msg);
256         if let Some(generics_param_span) = generics_param_span {
257             let label = "`main` cannot have generic parameters".to_string();
258             diag.span_label(generics_param_span, label);
259         }
260         diag.emit();
261         error = true;
262     } else if !main_fn_predicates.predicates.is_empty() {
263         // generics may bring in implicit predicates, so we skip this check if generics is present.
264         let generics_where_clauses_span = main_fn_where_clauses_span(tcx, main_def_id);
265         let mut diag = struct_span_err!(
266             tcx.sess,
267             generics_where_clauses_span.unwrap_or(main_span),
268             E0646,
269             "`main` function is not allowed to have a `where` clause"
270         );
271         if let Some(generics_where_clauses_span) = generics_where_clauses_span {
272             diag.span_label(generics_where_clauses_span, "`main` cannot have a `where` clause");
273         }
274         diag.emit();
275         error = true;
276     }
277
278     let main_asyncness = tcx.asyncness(main_def_id);
279     if let hir::IsAsync::Async = main_asyncness {
280         let mut diag = struct_span_err!(
281             tcx.sess,
282             main_span,
283             E0752,
284             "`main` function is not allowed to be `async`"
285         );
286         let asyncness_span = main_fn_asyncness_span(tcx, main_def_id);
287         if let Some(asyncness_span) = asyncness_span {
288             diag.span_label(asyncness_span, "`main` function is not allowed to be `async`");
289         }
290         diag.emit();
291         error = true;
292     }
293
294     for attr in tcx.get_attrs(main_def_id) {
295         if tcx.sess.check_name(attr, sym::track_caller) {
296             tcx.sess
297                 .struct_span_err(
298                     attr.span,
299                     "`main` function is not allowed to be `#[track_caller]`",
300                 )
301                 .span_label(main_span, "`main` function is not allowed to be `#[track_caller]`")
302                 .emit();
303             error = true;
304         }
305     }
306
307     if error {
308         return;
309     }
310
311     let expected_return_type;
312     if let Some(term_id) = tcx.lang_items().termination() {
313         let return_ty = main_fnsig.output();
314         let return_ty_span = main_fn_return_type_span(tcx, main_def_id).unwrap_or(main_span);
315         if !return_ty.bound_vars().is_empty() {
316             let msg = "`main` function return type is not allowed to have generic \
317                     parameters"
318                 .to_owned();
319             struct_span_err!(tcx.sess, return_ty_span, E0131, "{}", msg).emit();
320             error = true;
321         }
322         let return_ty = return_ty.skip_binder();
323         tcx.infer_ctxt().enter(|infcx| {
324             let cause = traits::ObligationCause::new(
325                 return_ty_span,
326                 main_diagnostics_hir_id,
327                 ObligationCauseCode::MainFunctionType,
328             );
329             let mut fulfillment_cx = traits::FulfillmentContext::new();
330             fulfillment_cx.register_bound(&infcx, ty::ParamEnv::empty(), return_ty, term_id, cause);
331             if let Err(err) = fulfillment_cx.select_all_or_error(&infcx) {
332                 infcx.report_fulfillment_errors(&err, None, false);
333                 error = true;
334             }
335         });
336         // now we can take the return type of the given main function
337         expected_return_type = main_fnsig.output();
338     } else {
339         // standard () main return type
340         expected_return_type = ty::Binder::dummy(tcx.mk_unit());
341     }
342
343     if error {
344         return;
345     }
346
347     let se_ty = tcx.mk_fn_ptr(expected_return_type.map_bound(|expected_return_type| {
348         tcx.mk_fn_sig(iter::empty(), expected_return_type, false, hir::Unsafety::Normal, Abi::Rust)
349     }));
350
351     require_same_types(
352         tcx,
353         &ObligationCause::new(
354             main_span,
355             main_diagnostics_hir_id,
356             ObligationCauseCode::MainFunctionType,
357         ),
358         se_ty,
359         tcx.mk_fn_ptr(main_fnsig),
360     );
361 }
362 fn check_start_fn_ty(tcx: TyCtxt<'_>, start_def_id: DefId) {
363     let start_def_id = start_def_id.expect_local();
364     let start_id = tcx.hir().local_def_id_to_hir_id(start_def_id);
365     let start_span = tcx.def_span(start_def_id);
366     let start_t = tcx.type_of(start_def_id);
367     match start_t.kind() {
368         ty::FnDef(..) => {
369             if let Some(Node::Item(it)) = tcx.hir().find(start_id) {
370                 if let hir::ItemKind::Fn(ref sig, ref generics, _) = it.kind {
371                     let mut error = false;
372                     if !generics.params.is_empty() {
373                         struct_span_err!(
374                             tcx.sess,
375                             generics.span,
376                             E0132,
377                             "start function is not allowed to have type parameters"
378                         )
379                         .span_label(generics.span, "start function cannot have type parameters")
380                         .emit();
381                         error = true;
382                     }
383                     if let Some(sp) = generics.where_clause.span() {
384                         struct_span_err!(
385                             tcx.sess,
386                             sp,
387                             E0647,
388                             "start function is not allowed to have a `where` clause"
389                         )
390                         .span_label(sp, "start function cannot have a `where` clause")
391                         .emit();
392                         error = true;
393                     }
394                     if let hir::IsAsync::Async = sig.header.asyncness {
395                         let span = tcx.sess.source_map().guess_head_span(it.span);
396                         struct_span_err!(
397                             tcx.sess,
398                             span,
399                             E0752,
400                             "`start` is not allowed to be `async`"
401                         )
402                         .span_label(span, "`start` is not allowed to be `async`")
403                         .emit();
404                         error = true;
405                     }
406
407                     let attrs = tcx.hir().attrs(start_id);
408                     for attr in attrs {
409                         if tcx.sess.check_name(attr, sym::track_caller) {
410                             tcx.sess
411                                 .struct_span_err(
412                                     attr.span,
413                                     "`start` is not allowed to be `#[track_caller]`",
414                                 )
415                                 .span_label(
416                                     start_span,
417                                     "`start` is not allowed to be `#[track_caller]`",
418                                 )
419                                 .emit();
420                             error = true;
421                         }
422                     }
423
424                     if error {
425                         return;
426                     }
427                 }
428             }
429
430             let se_ty = tcx.mk_fn_ptr(ty::Binder::dummy(tcx.mk_fn_sig(
431                 [tcx.types.isize, tcx.mk_imm_ptr(tcx.mk_imm_ptr(tcx.types.u8))].iter().cloned(),
432                 tcx.types.isize,
433                 false,
434                 hir::Unsafety::Normal,
435                 Abi::Rust,
436             )));
437
438             require_same_types(
439                 tcx,
440                 &ObligationCause::new(start_span, start_id, ObligationCauseCode::StartFunctionType),
441                 se_ty,
442                 tcx.mk_fn_ptr(tcx.fn_sig(start_def_id)),
443             );
444         }
445         _ => {
446             span_bug!(start_span, "start has a non-function type: found `{}`", start_t);
447         }
448     }
449 }
450
451 fn check_for_entry_fn(tcx: TyCtxt<'_>) {
452     match tcx.entry_fn(()) {
453         Some((def_id, EntryFnType::Main)) => check_main_fn_ty(tcx, def_id),
454         Some((def_id, EntryFnType::Start)) => check_start_fn_ty(tcx, def_id),
455         _ => {}
456     }
457 }
458
459 pub fn provide(providers: &mut Providers) {
460     collect::provide(providers);
461     coherence::provide(providers);
462     check::provide(providers);
463     variance::provide(providers);
464     outlives::provide(providers);
465     impl_wf_check::provide(providers);
466     hir_wf_check::provide(providers);
467 }
468
469 pub fn check_crate(tcx: TyCtxt<'_>) -> Result<(), ErrorReported> {
470     let _prof_timer = tcx.sess.timer("type_check_crate");
471
472     // this ensures that later parts of type checking can assume that items
473     // have valid types and not error
474     // FIXME(matthewjasper) We shouldn't need to use `track_errors`.
475     tcx.sess.track_errors(|| {
476         tcx.sess.time("type_collecting", || {
477             for &module in tcx.hir().krate().modules.keys() {
478                 tcx.ensure().collect_mod_item_types(module);
479             }
480         });
481     })?;
482
483     if tcx.features().rustc_attrs {
484         tcx.sess.track_errors(|| {
485             tcx.sess.time("outlives_testing", || outlives::test::test_inferred_outlives(tcx));
486         })?;
487     }
488
489     tcx.sess.track_errors(|| {
490         tcx.sess.time("impl_wf_inference", || impl_wf_check::impl_wf_check(tcx));
491     })?;
492
493     tcx.sess.track_errors(|| {
494         tcx.sess.time("coherence_checking", || coherence::check_coherence(tcx));
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", || check::check_wf_new(tcx));
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         for &module in tcx.hir().krate().modules.keys() {
510             tcx.ensure().check_mod_item_types(module);
511         }
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 tcx.sess.err_count() == 0 { Ok(()) } else { Err(ErrorReported) }
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_node_id = tcx.hir().get_parent_item(hir_ty.hir_id);
529     let env_def_id = tcx.hir().local_def_id(env_node_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_hir_id = tcx.hir().get_parent_item(hir_trait.hir_ref_id);
543     let env_def_id = tcx.hir().local_def_id(env_hir_id);
544     let item_cx = self::collect::ItemCtxt::new(tcx, env_def_id.to_def_id());
545     let mut bounds = Bounds::default();
546     let _ = <dyn AstConv<'_>>::instantiate_poly_trait_ref(
547         &item_cx,
548         hir_trait,
549         DUMMY_SP,
550         hir::Constness::NotConst,
551         self_ty,
552         &mut bounds,
553         true,
554     );
555
556     bounds
557 }