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