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