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/nightly-rustc/")]
59 #![feature(array_value_iter)]
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 #![feature(control_flow_enum)]
70 #![recursion_limit = "256"]
76 extern crate rustc_middle;
78 // These are used by Clippy.
80 pub mod expr_use_visitor;
87 mod constrained_generic_params;
90 mod mem_categorization;
92 mod structured_errors;
95 use rustc_errors::{struct_span_err, ErrorReported};
97 use rustc_hir::def_id::{LocalDefId, LOCAL_CRATE};
99 use rustc_infer::infer::{InferOk, TyCtxtInferExt};
100 use rustc_infer::traits::TraitEngineExt as _;
101 use rustc_middle::middle;
102 use rustc_middle::ty::query::Providers;
103 use rustc_middle::ty::{self, Ty, TyCtxt};
104 use rustc_middle::util;
105 use rustc_session::config::EntryFnType;
106 use rustc_span::{symbol::sym, Span, DUMMY_SP};
107 use rustc_target::spec::abi::Abi;
108 use rustc_trait_selection::traits::error_reporting::InferCtxtExt as _;
109 use rustc_trait_selection::traits::{
110 ObligationCause, ObligationCauseCode, TraitEngine, TraitEngineExt as _,
115 use astconv::AstConv;
118 fn require_c_abi_if_c_variadic(tcx: TyCtxt<'_>, decl: &hir::FnDecl<'_>, abi: Abi, span: Span) {
119 if decl.c_variadic && !(abi == Abi::C || abi == Abi::Cdecl) {
120 let mut err = struct_span_err!(
124 "C-variadic function must have C or cdecl calling convention"
126 err.span_label(span, "C-variadics require C or cdecl calling convention").emit();
130 fn require_same_types<'tcx>(
132 cause: &ObligationCause<'tcx>,
136 tcx.infer_ctxt().enter(|ref infcx| {
137 let param_env = ty::ParamEnv::empty();
138 let mut fulfill_cx = TraitEngine::new(infcx.tcx);
139 match infcx.at(&cause, param_env).eq(expected, actual) {
140 Ok(InferOk { obligations, .. }) => {
141 fulfill_cx.register_predicate_obligations(infcx, obligations);
144 infcx.report_mismatched_types(cause, expected, actual, err).emit();
149 match fulfill_cx.select_all_or_error(infcx) {
152 infcx.report_fulfillment_errors(&errors, None, false);
159 fn check_main_fn_ty(tcx: TyCtxt<'_>, main_def_id: LocalDefId) {
160 let main_id = tcx.hir().local_def_id_to_hir_id(main_def_id);
161 let main_span = tcx.def_span(main_def_id);
162 let main_t = tcx.type_of(main_def_id);
163 match main_t.kind() {
165 if let Some(Node::Item(it)) = tcx.hir().find(main_id) {
166 if let hir::ItemKind::Fn(ref sig, ref generics, _) = it.kind {
167 let mut error = false;
168 if !generics.params.is_empty() {
169 let msg = "`main` function is not allowed to have generic \
172 let label = "`main` cannot have generic parameters".to_string();
173 struct_span_err!(tcx.sess, generics.span, E0131, "{}", msg)
174 .span_label(generics.span, label)
178 if let Some(sp) = generics.where_clause.span() {
183 "`main` function is not allowed to have a `where` clause"
185 .span_label(sp, "`main` cannot have a `where` clause")
189 if let hir::IsAsync::Async = sig.header.asyncness {
190 let span = tcx.sess.source_map().guess_head_span(it.span);
195 "`main` function is not allowed to be `async`"
197 .span_label(span, "`main` function is not allowed to be `async`")
202 for attr in it.attrs {
203 if tcx.sess.check_name(attr, sym::track_caller) {
207 "`main` function is not allowed to be `#[track_caller]`",
211 "`main` function is not allowed to be `#[track_caller]`",
224 let actual = tcx.fn_sig(main_def_id);
225 let expected_return_type = if tcx.lang_items().termination().is_some() {
226 // we take the return type of the given main function, the real check is done
228 actual.output().skip_binder()
230 // standard () main return type
234 let se_ty = tcx.mk_fn_ptr(ty::Binder::bind(tcx.mk_fn_sig(
236 expected_return_type,
238 hir::Unsafety::Normal,
244 &ObligationCause::new(main_span, main_id, ObligationCauseCode::MainFunctionType),
246 tcx.mk_fn_ptr(actual),
250 span_bug!(main_span, "main has a non-function type: found `{}`", main_t);
255 fn check_start_fn_ty(tcx: TyCtxt<'_>, start_def_id: LocalDefId) {
256 let start_id = tcx.hir().local_def_id_to_hir_id(start_def_id);
257 let start_span = tcx.def_span(start_def_id);
258 let start_t = tcx.type_of(start_def_id);
259 match start_t.kind() {
261 if let Some(Node::Item(it)) = tcx.hir().find(start_id) {
262 if let hir::ItemKind::Fn(ref sig, ref generics, _) = it.kind {
263 let mut error = false;
264 if !generics.params.is_empty() {
269 "start function is not allowed to have type parameters"
271 .span_label(generics.span, "start function cannot have type parameters")
275 if let Some(sp) = generics.where_clause.span() {
280 "start function is not allowed to have a `where` clause"
282 .span_label(sp, "start function cannot have a `where` clause")
286 if let hir::IsAsync::Async = sig.header.asyncness {
287 let span = tcx.sess.source_map().guess_head_span(it.span);
292 "`start` is not allowed to be `async`"
294 .span_label(span, "`start` is not allowed to be `async`")
299 for attr in it.attrs {
300 if tcx.sess.check_name(attr, sym::track_caller) {
304 "`start` is not allowed to be `#[track_caller]`",
308 "`start` is not allowed to be `#[track_caller]`",
321 let se_ty = tcx.mk_fn_ptr(ty::Binder::dummy(tcx.mk_fn_sig(
322 [tcx.types.isize, tcx.mk_imm_ptr(tcx.mk_imm_ptr(tcx.types.u8))].iter().cloned(),
325 hir::Unsafety::Normal,
331 &ObligationCause::new(start_span, start_id, ObligationCauseCode::StartFunctionType),
333 tcx.mk_fn_ptr(tcx.fn_sig(start_def_id)),
337 span_bug!(start_span, "start has a non-function type: found `{}`", start_t);
342 fn check_for_entry_fn(tcx: TyCtxt<'_>) {
343 match tcx.entry_fn(LOCAL_CRATE) {
344 Some((def_id, EntryFnType::Main)) => check_main_fn_ty(tcx, def_id),
345 Some((def_id, EntryFnType::Start)) => check_start_fn_ty(tcx, def_id),
350 pub fn provide(providers: &mut Providers) {
351 collect::provide(providers);
352 coherence::provide(providers);
353 check::provide(providers);
354 variance::provide(providers);
355 outlives::provide(providers);
356 impl_wf_check::provide(providers);
359 pub fn check_crate(tcx: TyCtxt<'_>) -> Result<(), ErrorReported> {
360 let _prof_timer = tcx.sess.timer("type_check_crate");
362 // this ensures that later parts of type checking can assume that items
363 // have valid types and not error
364 // FIXME(matthewjasper) We shouldn't need to use `track_errors`.
365 tcx.sess.track_errors(|| {
366 tcx.sess.time("type_collecting", || {
367 for &module in tcx.hir().krate().modules.keys() {
368 tcx.ensure().collect_mod_item_types(tcx.hir().local_def_id(module));
373 if tcx.features().rustc_attrs {
374 tcx.sess.track_errors(|| {
375 tcx.sess.time("outlives_testing", || outlives::test::test_inferred_outlives(tcx));
379 tcx.sess.track_errors(|| {
380 tcx.sess.time("impl_wf_inference", || impl_wf_check::impl_wf_check(tcx));
383 tcx.sess.track_errors(|| {
384 tcx.sess.time("coherence_checking", || coherence::check_coherence(tcx));
387 if tcx.features().rustc_attrs {
388 tcx.sess.track_errors(|| {
389 tcx.sess.time("variance_testing", || variance::test::test_variance(tcx));
393 tcx.sess.track_errors(|| {
394 tcx.sess.time("wf_checking", || check::check_wf_new(tcx));
397 // NOTE: This is copy/pasted in librustdoc/core.rs and should be kept in sync.
398 tcx.sess.time("item_types_checking", || {
399 for &module in tcx.hir().krate().modules.keys() {
400 tcx.ensure().check_mod_item_types(tcx.hir().local_def_id(module));
404 tcx.sess.time("item_bodies_checking", || tcx.typeck_item_bodies(LOCAL_CRATE));
406 check_unused::check_crate(tcx);
407 check_for_entry_fn(tcx);
409 if tcx.sess.err_count() == 0 { Ok(()) } else { Err(ErrorReported) }
412 /// A quasi-deprecated helper used in rustdoc and clippy to get
413 /// the type from a HIR node.
414 pub fn hir_ty_to_ty<'tcx>(tcx: TyCtxt<'tcx>, hir_ty: &hir::Ty<'_>) -> Ty<'tcx> {
415 // In case there are any projections, etc., find the "environment"
416 // def-ID that will be used to determine the traits/predicates in
417 // scope. This is derived from the enclosing item-like thing.
418 let env_node_id = tcx.hir().get_parent_item(hir_ty.hir_id);
419 let env_def_id = tcx.hir().local_def_id(env_node_id);
420 let item_cx = self::collect::ItemCtxt::new(tcx, env_def_id.to_def_id());
422 astconv::AstConv::ast_ty_to_ty(&item_cx, hir_ty)
425 pub fn hir_trait_to_predicates<'tcx>(
427 hir_trait: &hir::TraitRef<'_>,
430 // In case there are any projections, etc., find the "environment"
431 // def-ID that will be used to determine the traits/predicates in
432 // scope. This is derived from the enclosing item-like thing.
433 let env_hir_id = tcx.hir().get_parent_item(hir_trait.hir_ref_id);
434 let env_def_id = tcx.hir().local_def_id(env_hir_id);
435 let item_cx = self::collect::ItemCtxt::new(tcx, env_def_id.to_def_id());
436 let mut bounds = Bounds::default();
437 let _ = AstConv::instantiate_poly_trait_ref_inner(
441 hir::Constness::NotConst,