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 // This is used by Clippy.
78 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::{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().as_local_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`")
203 let actual = tcx.fn_sig(main_def_id);
204 let expected_return_type = if tcx.lang_items().termination().is_some() {
205 // we take the return type of the given main function, the real check is done
207 actual.output().skip_binder()
209 // standard () main return type
213 let se_ty = tcx.mk_fn_ptr(ty::Binder::bind(tcx.mk_fn_sig(
215 expected_return_type,
217 hir::Unsafety::Normal,
223 &ObligationCause::new(main_span, main_id, ObligationCauseCode::MainFunctionType),
225 tcx.mk_fn_ptr(actual),
229 span_bug!(main_span, "main has a non-function type: found `{}`", main_t);
234 fn check_start_fn_ty(tcx: TyCtxt<'_>, start_def_id: LocalDefId) {
235 let start_id = tcx.hir().as_local_hir_id(start_def_id);
236 let start_span = tcx.def_span(start_def_id);
237 let start_t = tcx.type_of(start_def_id);
240 if let Some(Node::Item(it)) = tcx.hir().find(start_id) {
241 if let hir::ItemKind::Fn(ref sig, ref generics, _) = it.kind {
242 let mut error = false;
243 if !generics.params.is_empty() {
248 "start function is not allowed to have type parameters"
250 .span_label(generics.span, "start function cannot have type parameters")
254 if let Some(sp) = generics.where_clause.span() {
259 "start function is not allowed to have a `where` clause"
261 .span_label(sp, "start function cannot have a `where` clause")
265 if let hir::IsAsync::Async = sig.header.asyncness {
266 let span = tcx.sess.source_map().guess_head_span(it.span);
271 "start is not allowed to be `async`"
273 .span_label(span, "start is not allowed to be `async`")
283 let se_ty = tcx.mk_fn_ptr(ty::Binder::bind(tcx.mk_fn_sig(
284 [tcx.types.isize, tcx.mk_imm_ptr(tcx.mk_imm_ptr(tcx.types.u8))].iter().cloned(),
287 hir::Unsafety::Normal,
293 &ObligationCause::new(start_span, start_id, ObligationCauseCode::StartFunctionType),
295 tcx.mk_fn_ptr(tcx.fn_sig(start_def_id)),
299 span_bug!(start_span, "start has a non-function type: found `{}`", start_t);
304 fn check_for_entry_fn(tcx: TyCtxt<'_>) {
305 match tcx.entry_fn(LOCAL_CRATE) {
306 Some((def_id, EntryFnType::Main)) => check_main_fn_ty(tcx, def_id),
307 Some((def_id, EntryFnType::Start)) => check_start_fn_ty(tcx, def_id),
312 pub fn provide(providers: &mut Providers) {
313 collect::provide(providers);
314 coherence::provide(providers);
315 check::provide(providers);
316 variance::provide(providers);
317 outlives::provide(providers);
318 impl_wf_check::provide(providers);
321 pub fn check_crate(tcx: TyCtxt<'_>) -> Result<(), ErrorReported> {
322 let _prof_timer = tcx.sess.timer("type_check_crate");
324 // this ensures that later parts of type checking can assume that items
325 // have valid types and not error
326 // FIXME(matthewjasper) We shouldn't need to do this.
327 tcx.sess.track_errors(|| {
328 tcx.sess.time("type_collecting", || {
329 for &module in tcx.hir().krate().modules.keys() {
330 tcx.ensure().collect_mod_item_types(tcx.hir().local_def_id(module));
335 if tcx.features().rustc_attrs {
336 tcx.sess.track_errors(|| {
337 tcx.sess.time("outlives_testing", || outlives::test::test_inferred_outlives(tcx));
341 tcx.sess.track_errors(|| {
342 tcx.sess.time("impl_wf_inference", || impl_wf_check::impl_wf_check(tcx));
345 tcx.sess.track_errors(|| {
346 tcx.sess.time("coherence_checking", || coherence::check_coherence(tcx));
349 if tcx.features().rustc_attrs {
350 tcx.sess.track_errors(|| {
351 tcx.sess.time("variance_testing", || variance::test::test_variance(tcx));
355 tcx.sess.track_errors(|| {
356 tcx.sess.time("wf_checking", || check::check_wf_new(tcx));
359 tcx.sess.time("item_types_checking", || {
360 for &module in tcx.hir().krate().modules.keys() {
361 tcx.ensure().check_mod_item_types(tcx.hir().local_def_id(module));
365 tcx.sess.time("item_bodies_checking", || tcx.typeck_item_bodies(LOCAL_CRATE));
367 check_unused::check_crate(tcx);
368 check_for_entry_fn(tcx);
370 if tcx.sess.err_count() == 0 { Ok(()) } else { Err(ErrorReported) }
373 /// A quasi-deprecated helper used in rustdoc and clippy to get
374 /// the type from a HIR node.
375 pub fn hir_ty_to_ty<'tcx>(tcx: TyCtxt<'tcx>, hir_ty: &hir::Ty<'_>) -> Ty<'tcx> {
376 // In case there are any projections, etc., find the "environment"
377 // def-ID that will be used to determine the traits/predicates in
378 // scope. This is derived from the enclosing item-like thing.
379 let env_node_id = tcx.hir().get_parent_item(hir_ty.hir_id);
380 let env_def_id = tcx.hir().local_def_id(env_node_id);
381 let item_cx = self::collect::ItemCtxt::new(tcx, env_def_id.to_def_id());
383 astconv::AstConv::ast_ty_to_ty(&item_cx, hir_ty)
386 pub fn hir_trait_to_predicates<'tcx>(
388 hir_trait: &hir::TraitRef<'_>,
391 // In case there are any projections, etc., find the "environment"
392 // def-ID that will be used to determine the traits/predicates in
393 // scope. This is derived from the enclosing item-like thing.
394 let env_hir_id = tcx.hir().get_parent_item(hir_trait.hir_ref_id);
395 let env_def_id = tcx.hir().local_def_id(env_hir_id);
396 let item_cx = self::collect::ItemCtxt::new(tcx, env_def_id.to_def_id());
397 let mut bounds = Bounds::default();
398 let _ = AstConv::instantiate_poly_trait_ref_inner(
402 hir::Constness::NotConst,