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(bindings_after_at)]
60 #![feature(bool_to_option)]
61 #![feature(box_syntax)]
62 #![feature(crate_visibility_modifier)]
63 #![feature(format_args_capture)]
64 #![feature(in_band_lifetimes)]
65 #![feature(is_sorted)]
68 #![cfg_attr(bootstrap, feature(or_patterns))]
69 #![feature(try_blocks)]
70 #![feature(never_type)]
71 #![feature(slice_partition_dedup)]
72 #![feature(control_flow_enum)]
73 #![recursion_limit = "256"]
79 extern crate rustc_middle;
81 // These are used by Clippy.
83 pub mod expr_use_visitor;
90 mod constrained_generic_params;
93 mod mem_categorization;
95 mod structured_errors;
98 use rustc_errors::{struct_span_err, ErrorReported};
100 use rustc_hir::def_id::{LocalDefId, LOCAL_CRATE};
102 use rustc_infer::infer::{InferOk, TyCtxtInferExt};
103 use rustc_infer::traits::TraitEngineExt as _;
104 use rustc_middle::middle;
105 use rustc_middle::ty::query::Providers;
106 use rustc_middle::ty::{self, Ty, TyCtxt};
107 use rustc_middle::util;
108 use rustc_session::config::EntryFnType;
109 use rustc_span::{symbol::sym, Span, DUMMY_SP};
110 use rustc_target::spec::abi::Abi;
111 use rustc_trait_selection::traits::error_reporting::InferCtxtExt as _;
112 use rustc_trait_selection::traits::{
113 ObligationCause, ObligationCauseCode, TraitEngine, TraitEngineExt as _,
118 use astconv::AstConv;
121 fn require_c_abi_if_c_variadic(tcx: TyCtxt<'_>, decl: &hir::FnDecl<'_>, abi: Abi, span: Span) {
122 match (decl.c_variadic, abi) {
123 // The function has the correct calling convention, or isn't a "C-variadic" function.
124 (false, _) | (true, Abi::C { .. }) | (true, Abi::Cdecl) => {}
125 // The function is a "C-variadic" function with an incorrect calling convention.
127 let mut err = struct_span_err!(
131 "C-variadic function must have C or cdecl calling convention"
133 err.span_label(span, "C-variadics require C or cdecl calling convention").emit();
138 fn require_same_types<'tcx>(
140 cause: &ObligationCause<'tcx>,
144 tcx.infer_ctxt().enter(|ref infcx| {
145 let param_env = ty::ParamEnv::empty();
146 let mut fulfill_cx = <dyn TraitEngine<'_>>::new(infcx.tcx);
147 match infcx.at(&cause, param_env).eq(expected, actual) {
148 Ok(InferOk { obligations, .. }) => {
149 fulfill_cx.register_predicate_obligations(infcx, obligations);
152 infcx.report_mismatched_types(cause, expected, actual, err).emit();
157 match fulfill_cx.select_all_or_error(infcx) {
160 infcx.report_fulfillment_errors(&errors, None, false);
167 fn check_main_fn_ty(tcx: TyCtxt<'_>, main_def_id: LocalDefId) {
168 let main_id = tcx.hir().local_def_id_to_hir_id(main_def_id);
169 let main_span = tcx.def_span(main_def_id);
170 let main_t = tcx.type_of(main_def_id);
171 match main_t.kind() {
173 if let Some(Node::Item(it)) = tcx.hir().find(main_id) {
174 if let hir::ItemKind::Fn(ref sig, ref generics, _) = it.kind {
175 let mut error = false;
176 if !generics.params.is_empty() {
177 let msg = "`main` function is not allowed to have generic \
180 let label = "`main` cannot have generic parameters".to_string();
181 struct_span_err!(tcx.sess, generics.span, E0131, "{}", msg)
182 .span_label(generics.span, label)
186 if let Some(sp) = generics.where_clause.span() {
191 "`main` function is not allowed to have a `where` clause"
193 .span_label(sp, "`main` cannot have a `where` clause")
197 if let hir::IsAsync::Async = sig.header.asyncness {
198 let span = tcx.sess.source_map().guess_head_span(it.span);
203 "`main` function is not allowed to be `async`"
205 .span_label(span, "`main` function is not allowed to be `async`")
210 let attrs = tcx.hir().attrs(main_id);
212 if tcx.sess.check_name(attr, sym::track_caller) {
216 "`main` function is not allowed to be `#[track_caller]`",
220 "`main` function is not allowed to be `#[track_caller]`",
233 let actual = tcx.fn_sig(main_def_id);
234 let expected_return_type = if tcx.lang_items().termination().is_some() {
235 // we take the return type of the given main function, the real check is done
239 // standard () main return type
240 ty::Binder::dummy(tcx.mk_unit())
243 let se_ty = tcx.mk_fn_ptr(expected_return_type.map_bound(|expected_return_type| {
246 expected_return_type,
248 hir::Unsafety::Normal,
255 &ObligationCause::new(main_span, main_id, ObligationCauseCode::MainFunctionType),
257 tcx.mk_fn_ptr(actual),
261 span_bug!(main_span, "main has a non-function type: found `{}`", main_t);
266 fn check_start_fn_ty(tcx: TyCtxt<'_>, start_def_id: LocalDefId) {
267 let start_id = tcx.hir().local_def_id_to_hir_id(start_def_id);
268 let start_span = tcx.def_span(start_def_id);
269 let start_t = tcx.type_of(start_def_id);
270 match start_t.kind() {
272 if let Some(Node::Item(it)) = tcx.hir().find(start_id) {
273 if let hir::ItemKind::Fn(ref sig, ref generics, _) = it.kind {
274 let mut error = false;
275 if !generics.params.is_empty() {
280 "start function is not allowed to have type parameters"
282 .span_label(generics.span, "start function cannot have type parameters")
286 if let Some(sp) = generics.where_clause.span() {
291 "start function is not allowed to have a `where` clause"
293 .span_label(sp, "start function cannot have a `where` clause")
297 if let hir::IsAsync::Async = sig.header.asyncness {
298 let span = tcx.sess.source_map().guess_head_span(it.span);
303 "`start` is not allowed to be `async`"
305 .span_label(span, "`start` is not allowed to be `async`")
310 let attrs = tcx.hir().attrs(start_id);
312 if tcx.sess.check_name(attr, sym::track_caller) {
316 "`start` is not allowed to be `#[track_caller]`",
320 "`start` is not allowed to be `#[track_caller]`",
333 let se_ty = tcx.mk_fn_ptr(ty::Binder::dummy(tcx.mk_fn_sig(
334 [tcx.types.isize, tcx.mk_imm_ptr(tcx.mk_imm_ptr(tcx.types.u8))].iter().cloned(),
337 hir::Unsafety::Normal,
343 &ObligationCause::new(start_span, start_id, ObligationCauseCode::StartFunctionType),
345 tcx.mk_fn_ptr(tcx.fn_sig(start_def_id)),
349 span_bug!(start_span, "start has a non-function type: found `{}`", start_t);
354 fn check_for_entry_fn(tcx: TyCtxt<'_>) {
355 match tcx.entry_fn(LOCAL_CRATE) {
356 Some((def_id, EntryFnType::Main)) => check_main_fn_ty(tcx, def_id),
357 Some((def_id, EntryFnType::Start)) => check_start_fn_ty(tcx, def_id),
362 pub fn provide(providers: &mut Providers) {
363 collect::provide(providers);
364 coherence::provide(providers);
365 check::provide(providers);
366 variance::provide(providers);
367 outlives::provide(providers);
368 impl_wf_check::provide(providers);
371 pub fn check_crate(tcx: TyCtxt<'_>) -> Result<(), ErrorReported> {
372 let _prof_timer = tcx.sess.timer("type_check_crate");
374 // this ensures that later parts of type checking can assume that items
375 // have valid types and not error
376 // FIXME(matthewjasper) We shouldn't need to use `track_errors`.
377 tcx.sess.track_errors(|| {
378 tcx.sess.time("type_collecting", || {
379 for &module in tcx.hir().krate().modules.keys() {
380 tcx.ensure().collect_mod_item_types(module);
385 if tcx.features().rustc_attrs {
386 tcx.sess.track_errors(|| {
387 tcx.sess.time("outlives_testing", || outlives::test::test_inferred_outlives(tcx));
391 tcx.sess.track_errors(|| {
392 tcx.sess.time("impl_wf_inference", || impl_wf_check::impl_wf_check(tcx));
395 tcx.sess.track_errors(|| {
396 tcx.sess.time("coherence_checking", || coherence::check_coherence(tcx));
399 if tcx.features().rustc_attrs {
400 tcx.sess.track_errors(|| {
401 tcx.sess.time("variance_testing", || variance::test::test_variance(tcx));
405 tcx.sess.track_errors(|| {
406 tcx.sess.time("wf_checking", || check::check_wf_new(tcx));
409 // NOTE: This is copy/pasted in librustdoc/core.rs and should be kept in sync.
410 tcx.sess.time("item_types_checking", || {
411 for &module in tcx.hir().krate().modules.keys() {
412 tcx.ensure().check_mod_item_types(module);
416 tcx.sess.time("item_bodies_checking", || tcx.typeck_item_bodies(LOCAL_CRATE));
418 check_unused::check_crate(tcx);
419 check_for_entry_fn(tcx);
421 if tcx.sess.err_count() == 0 { Ok(()) } else { Err(ErrorReported) }
424 /// A quasi-deprecated helper used in rustdoc and clippy to get
425 /// the type from a HIR node.
426 pub fn hir_ty_to_ty<'tcx>(tcx: TyCtxt<'tcx>, hir_ty: &hir::Ty<'_>) -> Ty<'tcx> {
427 // In case there are any projections, etc., find the "environment"
428 // def-ID that will be used to determine the traits/predicates in
429 // scope. This is derived from the enclosing item-like thing.
430 let env_node_id = tcx.hir().get_parent_item(hir_ty.hir_id);
431 let env_def_id = tcx.hir().local_def_id(env_node_id);
432 let item_cx = self::collect::ItemCtxt::new(tcx, env_def_id.to_def_id());
433 item_cx.to_ty(hir_ty)
436 pub fn hir_trait_to_predicates<'tcx>(
438 hir_trait: &hir::TraitRef<'_>,
441 // In case there are any projections, etc., find the "environment"
442 // def-ID that will be used to determine the traits/predicates in
443 // scope. This is derived from the enclosing item-like thing.
444 let env_hir_id = tcx.hir().get_parent_item(hir_trait.hir_ref_id);
445 let env_def_id = tcx.hir().local_def_id(env_hir_id);
446 let item_cx = self::collect::ItemCtxt::new(tcx, env_def_id.to_def_id());
447 let mut bounds = Bounds::default();
448 let _ = <dyn AstConv<'_>>::instantiate_poly_trait_ref_inner(
452 hir::Constness::NotConst,