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