5 The type checker is responsible for:
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)
12 The main entry point is `check_crate()`. Type checking operates in
15 1. The collect phase first passes over all items and determines their
16 type, without examining their "innards".
18 2. Variance inference then runs to compute the variance of each parameter.
20 3. Coherence checks for overlapping or orphaned impls.
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.
30 The type checker is defined into various submodules which are documented
33 - astconv: converts the AST representation of types
34 into the `ty` representation.
36 - collect: computes the types of each top-level item and enters them into
37 the `tcx.types` table for later use.
39 - coherence: enforces coherence rules, builds some tables.
41 - variance: variance inference
43 - outlives: outlives inference
45 - check: walks over function bodies and type checks them, inferring types for
46 local variables, type parameters, etc as necessary.
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.
54 This API is completely unstable and subject to change.
58 #![doc(html_root_url = "https://doc.rust-lang.org/nightly/")]
59 #![allow(non_camel_case_types)]
60 #![feature(bool_to_option)]
61 #![feature(box_syntax)]
62 #![feature(crate_visibility_modifier)]
63 #![feature(in_band_lifetimes)]
65 #![feature(or_patterns)]
66 #![feature(try_blocks)]
67 #![feature(never_type)]
68 #![feature(slice_partition_dedup)]
69 #![recursion_limit = "256"]
75 extern crate rustc_middle;
77 // These are used by Clippy.
79 pub mod expr_use_visitor;
85 mod constrained_generic_params;
87 mod mem_categorization;
89 mod structured_errors;
92 use rustc_errors::{struct_span_err, ErrorReported};
94 use rustc_hir::def_id::{LocalDefId, LOCAL_CRATE};
96 use rustc_infer::infer::{InferOk, TyCtxtInferExt};
97 use rustc_infer::traits::TraitEngineExt as _;
98 use rustc_middle::middle;
99 use rustc_middle::ty::query::Providers;
100 use rustc_middle::ty::{self, Ty, TyCtxt};
101 use rustc_middle::util;
102 use rustc_session::config::EntryFnType;
103 use rustc_span::{symbol::sym, Span, DUMMY_SP};
104 use rustc_target::spec::abi::Abi;
105 use rustc_trait_selection::traits::error_reporting::InferCtxtExt as _;
106 use rustc_trait_selection::traits::{
107 ObligationCause, ObligationCauseCode, TraitEngine, TraitEngineExt as _,
112 use astconv::{AstConv, Bounds};
114 fn require_c_abi_if_c_variadic(tcx: TyCtxt<'_>, decl: &hir::FnDecl<'_>, abi: Abi, span: Span) {
115 if decl.c_variadic && !(abi == Abi::C || abi == Abi::Cdecl) {
116 let mut err = struct_span_err!(
120 "C-variadic function must have C or cdecl calling convention"
122 err.span_label(span, "C-variadics require C or cdecl calling convention").emit();
126 fn require_same_types<'tcx>(
128 cause: &ObligationCause<'tcx>,
132 tcx.infer_ctxt().enter(|ref infcx| {
133 let param_env = ty::ParamEnv::empty();
134 let mut fulfill_cx = TraitEngine::new(infcx.tcx);
135 match infcx.at(&cause, param_env).eq(expected, actual) {
136 Ok(InferOk { obligations, .. }) => {
137 fulfill_cx.register_predicate_obligations(infcx, obligations);
140 infcx.report_mismatched_types(cause, expected, actual, err).emit();
145 match fulfill_cx.select_all_or_error(infcx) {
148 infcx.report_fulfillment_errors(&errors, None, false);
155 fn check_main_fn_ty(tcx: TyCtxt<'_>, main_def_id: LocalDefId) {
156 let main_id = tcx.hir().local_def_id_to_hir_id(main_def_id);
157 let main_span = tcx.def_span(main_def_id);
158 let main_t = tcx.type_of(main_def_id);
161 if let Some(Node::Item(it)) = tcx.hir().find(main_id) {
162 if let hir::ItemKind::Fn(ref sig, ref generics, _) = it.kind {
163 let mut error = false;
164 if !generics.params.is_empty() {
165 let msg = "`main` function is not allowed to have generic \
168 let label = "`main` cannot have generic parameters".to_string();
169 struct_span_err!(tcx.sess, generics.span, E0131, "{}", msg)
170 .span_label(generics.span, label)
174 if let Some(sp) = generics.where_clause.span() {
179 "`main` function is not allowed to have a `where` clause"
181 .span_label(sp, "`main` cannot have a `where` clause")
185 if let hir::IsAsync::Async = sig.header.asyncness {
186 let span = tcx.sess.source_map().guess_head_span(it.span);
191 "`main` function is not allowed to be `async`"
193 .span_label(span, "`main` function is not allowed to be `async`")
198 for attr in it.attrs {
199 if tcx.sess.check_name(attr, sym::track_caller) {
203 "`main` function is not allowed to be `#[track_caller]`",
207 "`main` function is not allowed to be `#[track_caller]`",
220 let actual = tcx.fn_sig(main_def_id);
221 let expected_return_type = if tcx.lang_items().termination().is_some() {
222 // we take the return type of the given main function, the real check is done
224 actual.output().skip_binder()
226 // standard () main return type
230 let se_ty = tcx.mk_fn_ptr(ty::Binder::bind(tcx.mk_fn_sig(
232 expected_return_type,
234 hir::Unsafety::Normal,
240 &ObligationCause::new(main_span, main_id, ObligationCauseCode::MainFunctionType),
242 tcx.mk_fn_ptr(actual),
246 span_bug!(main_span, "main has a non-function type: found `{}`", main_t);
251 fn check_start_fn_ty(tcx: TyCtxt<'_>, start_def_id: LocalDefId) {
252 let start_id = tcx.hir().local_def_id_to_hir_id(start_def_id);
253 let start_span = tcx.def_span(start_def_id);
254 let start_t = tcx.type_of(start_def_id);
257 if let Some(Node::Item(it)) = tcx.hir().find(start_id) {
258 if let hir::ItemKind::Fn(ref sig, ref generics, _) = it.kind {
259 let mut error = false;
260 if !generics.params.is_empty() {
265 "start function is not allowed to have type parameters"
267 .span_label(generics.span, "start function cannot have type parameters")
271 if let Some(sp) = generics.where_clause.span() {
276 "start function is not allowed to have a `where` clause"
278 .span_label(sp, "start function cannot have a `where` clause")
282 if let hir::IsAsync::Async = sig.header.asyncness {
283 let span = tcx.sess.source_map().guess_head_span(it.span);
288 "`start` is not allowed to be `async`"
290 .span_label(span, "`start` is not allowed to be `async`")
295 for attr in it.attrs {
296 if tcx.sess.check_name(attr, sym::track_caller) {
300 "`start` is not allowed to be `#[track_caller]`",
304 "`start` is not allowed to be `#[track_caller]`",
317 let se_ty = tcx.mk_fn_ptr(ty::Binder::bind(tcx.mk_fn_sig(
318 [tcx.types.isize, tcx.mk_imm_ptr(tcx.mk_imm_ptr(tcx.types.u8))].iter().cloned(),
321 hir::Unsafety::Normal,
327 &ObligationCause::new(start_span, start_id, ObligationCauseCode::StartFunctionType),
329 tcx.mk_fn_ptr(tcx.fn_sig(start_def_id)),
333 span_bug!(start_span, "start has a non-function type: found `{}`", start_t);
338 fn check_for_entry_fn(tcx: TyCtxt<'_>) {
339 match tcx.entry_fn(LOCAL_CRATE) {
340 Some((def_id, EntryFnType::Main)) => check_main_fn_ty(tcx, def_id),
341 Some((def_id, EntryFnType::Start)) => check_start_fn_ty(tcx, def_id),
346 pub fn provide(providers: &mut Providers) {
347 collect::provide(providers);
348 coherence::provide(providers);
349 check::provide(providers);
350 variance::provide(providers);
351 outlives::provide(providers);
352 impl_wf_check::provide(providers);
355 pub fn check_crate(tcx: TyCtxt<'_>) -> Result<(), ErrorReported> {
356 let _prof_timer = tcx.sess.timer("type_check_crate");
358 // this ensures that later parts of type checking can assume that items
359 // have valid types and not error
360 // FIXME(matthewjasper) We shouldn't need to do this.
361 tcx.sess.track_errors(|| {
362 tcx.sess.time("type_collecting", || {
363 for &module in tcx.hir().krate().modules.keys() {
364 tcx.ensure().collect_mod_item_types(tcx.hir().local_def_id(module));
369 if tcx.features().rustc_attrs {
370 tcx.sess.track_errors(|| {
371 tcx.sess.time("outlives_testing", || outlives::test::test_inferred_outlives(tcx));
375 tcx.sess.track_errors(|| {
376 tcx.sess.time("impl_wf_inference", || impl_wf_check::impl_wf_check(tcx));
379 tcx.sess.track_errors(|| {
380 tcx.sess.time("coherence_checking", || coherence::check_coherence(tcx));
383 if tcx.features().rustc_attrs {
384 tcx.sess.track_errors(|| {
385 tcx.sess.time("variance_testing", || variance::test::test_variance(tcx));
389 tcx.sess.track_errors(|| {
390 tcx.sess.time("wf_checking", || check::check_wf_new(tcx));
393 // NOTE: This is copy/pasted in librustdoc/core.rs and should be kept in sync.
394 tcx.sess.time("item_types_checking", || {
395 for &module in tcx.hir().krate().modules.keys() {
396 tcx.ensure().check_mod_item_types(tcx.hir().local_def_id(module));
400 tcx.sess.time("item_bodies_checking", || tcx.typeck_item_bodies(LOCAL_CRATE));
402 check_unused::check_crate(tcx);
403 check_for_entry_fn(tcx);
405 if tcx.sess.err_count() == 0 { Ok(()) } else { Err(ErrorReported) }
408 /// A quasi-deprecated helper used in rustdoc and clippy to get
409 /// the type from a HIR node.
410 pub fn hir_ty_to_ty<'tcx>(tcx: TyCtxt<'tcx>, hir_ty: &hir::Ty<'_>) -> Ty<'tcx> {
411 // In case there are any projections, etc., find the "environment"
412 // def-ID that will be used to determine the traits/predicates in
413 // scope. This is derived from the enclosing item-like thing.
414 let env_node_id = tcx.hir().get_parent_item(hir_ty.hir_id);
415 let env_def_id = tcx.hir().local_def_id(env_node_id);
416 let item_cx = self::collect::ItemCtxt::new(tcx, env_def_id.to_def_id());
418 astconv::AstConv::ast_ty_to_ty(&item_cx, hir_ty)
421 pub fn hir_trait_to_predicates<'tcx>(
423 hir_trait: &hir::TraitRef<'_>,
426 // In case there are any projections, etc., find the "environment"
427 // def-ID that will be used to determine the traits/predicates in
428 // scope. This is derived from the enclosing item-like thing.
429 let env_hir_id = tcx.hir().get_parent_item(hir_trait.hir_ref_id);
430 let env_def_id = tcx.hir().local_def_id(env_hir_id);
431 let item_cx = self::collect::ItemCtxt::new(tcx, env_def_id.to_def_id());
432 let mut bounds = Bounds::default();
433 let _ = AstConv::instantiate_poly_trait_ref_inner(
437 hir::Constness::NotConst,