1 // Copyright 2014 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
13 typeck.rs, an introduction
15 The type checker is responsible for:
17 1. Determining the type of each expression
18 2. Resolving methods and traits
19 3. Guaranteeing that most type rules are met ("most?", you say, "why most?"
20 Well, dear reader, read on)
22 The main entry point is `check_crate()`. Type checking operates in
25 1. The collect phase first passes over all items and determines their
26 type, without examining their "innards".
28 2. Variance inference then runs to compute the variance of each parameter
30 3. Coherence checks for overlapping or orphaned impls
32 4. Finally, the check phase then checks function bodies and so forth.
33 Within the check phase, we check each function body one at a time
34 (bodies of function expressions are checked as part of the
35 containing function). Inference is used to supply types wherever
36 they are unknown. The actual checking of a function itself has
37 several phases (check, regionck, writeback), as discussed in the
38 documentation for the `check` module.
40 The type checker is defined into various submodules which are documented
43 - astconv: converts the AST representation of types
44 into the `ty` representation
46 - collect: computes the types of each top-level item and enters them into
47 the `tcx.types` table for later use
49 - coherence: enforces coherence rules, builds some tables
51 - variance: variance inference
53 - outlives: outlives inference
55 - check: walks over function bodies and type checks them, inferring types for
56 local variables, type parameters, etc as necessary.
58 - infer: finds the types to use for each type variable such that
59 all subtyping and assignment constraints are met. In essence, the check
60 module specifies the constraints, and the infer module solves them.
64 This API is completely unstable and subject to change.
68 #![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
69 html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
70 html_root_url = "https://doc.rust-lang.org/nightly/")]
72 #![allow(non_camel_case_types)]
74 #![feature(box_patterns)]
75 #![feature(box_syntax)]
76 #![feature(crate_visibility_modifier)]
78 #![feature(exhaustive_patterns)]
80 #![feature(refcell_replace_swap)]
81 #![feature(rustc_diagnostic_macros)]
82 #![feature(slice_patterns)]
83 #![feature(slice_sort_by_cached_key)]
84 #![feature(dyn_trait)]
85 #![feature(never_type)]
87 #[macro_use] extern crate log;
88 #[macro_use] extern crate syntax;
89 extern crate syntax_pos;
92 #[macro_use] extern crate rustc;
93 extern crate rustc_platform_intrinsics as intrinsics;
94 extern crate rustc_const_math;
95 extern crate rustc_data_structures;
96 extern crate rustc_errors as errors;
97 extern crate rustc_target;
105 use hir::map as hir_map;
106 use rustc::infer::InferOk;
107 use rustc::ty::subst::Substs;
108 use rustc::ty::{self, Ty, TyCtxt};
109 use rustc::ty::maps::Providers;
110 use rustc::traits::{ObligationCause, ObligationCauseCode, TraitEngine};
111 use session::{CompileIncomplete, config};
112 use util::common::time;
115 use rustc_target::spec::abi::Abi;
116 use syntax_pos::Span;
120 // NB: This module needs to be declared first so diagnostics are
121 // registered before they are used.
129 mod constrained_type_params;
130 mod structured_errors;
136 pub struct TypeAndSubsts<'tcx> {
137 substs: &'tcx Substs<'tcx>,
141 fn require_c_abi_if_variadic(tcx: TyCtxt,
145 if decl.variadic && !(abi == Abi::C || abi == Abi::Cdecl) {
146 let mut err = struct_span_err!(tcx.sess, span, E0045,
147 "variadic function must have C or cdecl calling convention");
148 err.span_label(span, "variadics require C or cdecl calling convention").emit();
152 fn require_same_types<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
153 cause: &ObligationCause<'tcx>,
157 tcx.infer_ctxt().enter(|ref infcx| {
158 let param_env = ty::ParamEnv::empty();
159 let mut fulfill_cx = TraitEngine::new(infcx.tcx);
160 match infcx.at(&cause, param_env).eq(expected, actual) {
161 Ok(InferOk { obligations, .. }) => {
162 fulfill_cx.register_predicate_obligations(infcx, obligations);
165 infcx.report_mismatched_types(cause, expected, actual, err).emit();
170 match fulfill_cx.select_all_or_error(infcx) {
173 infcx.report_fulfillment_errors(&errors, None, false);
180 fn check_main_fn_ty<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
181 main_id: ast::NodeId,
183 let main_def_id = tcx.hir.local_def_id(main_id);
184 let main_t = tcx.type_of(main_def_id);
187 match tcx.hir.find(main_id) {
188 Some(hir_map::NodeItem(it)) => {
190 hir::ItemFn(.., ref generics, _) => {
191 if !generics.params.is_empty() {
192 struct_span_err!(tcx.sess, generics.span, E0131,
193 "main function is not allowed to have type parameters")
194 .span_label(generics.span,
195 "main cannot have type parameters")
206 let actual = tcx.fn_sig(main_def_id);
207 let expected_return_type = if tcx.lang_items().termination().is_some() {
208 // we take the return type of the given main function, the real check is done
210 actual.output().skip_binder()
212 // standard () main return type
216 let se_ty = tcx.mk_fn_ptr(ty::Binder::bind(
219 expected_return_type,
221 hir::Unsafety::Normal,
228 &ObligationCause::new(main_span, main_id, ObligationCauseCode::MainFunctionType),
230 tcx.mk_fn_ptr(actual));
234 "main has a non-function type: found `{}`",
240 fn check_start_fn_ty<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
241 start_id: ast::NodeId,
243 let start_def_id = tcx.hir.local_def_id(start_id);
244 let start_t = tcx.type_of(start_def_id);
247 match tcx.hir.find(start_id) {
248 Some(hir_map::NodeItem(it)) => {
250 hir::ItemFn(..,ref ps,_)
251 if !ps.params.is_empty() => {
252 struct_span_err!(tcx.sess, ps.span, E0132,
253 "start function is not allowed to have type parameters")
255 "start function cannot have type parameters")
265 let se_ty = tcx.mk_fn_ptr(ty::Binder::bind(
269 tcx.mk_imm_ptr(tcx.mk_imm_ptr(tcx.types.u8))
273 hir::Unsafety::Normal,
280 &ObligationCause::new(start_span, start_id, ObligationCauseCode::StartFunctionType),
282 tcx.mk_fn_ptr(tcx.fn_sig(start_def_id)));
285 span_bug!(start_span,
286 "start has a non-function type: found `{}`",
292 fn check_for_entry_fn<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
293 if let Some((id, sp, entry_type)) = *tcx.sess.entry_fn.borrow() {
295 config::EntryMain => check_main_fn_ty(tcx, id, sp),
296 config::EntryStart => check_start_fn_ty(tcx, id, sp),
301 pub fn provide(providers: &mut Providers) {
302 collect::provide(providers);
303 coherence::provide(providers);
304 check::provide(providers);
305 variance::provide(providers);
306 outlives::provide(providers);
309 pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>)
310 -> Result<(), CompileIncomplete>
312 // this ensures that later parts of type checking can assume that items
313 // have valid types and not error
314 tcx.sess.track_errors(|| {
315 time(tcx.sess, "type collecting", ||
316 collect::collect_item_types(tcx));
320 tcx.sess.track_errors(|| {
321 time(tcx.sess, "outlives testing", ||
322 outlives::test::test_inferred_outlives(tcx));
325 tcx.sess.track_errors(|| {
326 time(tcx.sess, "impl wf inference", ||
327 impl_wf_check::impl_wf_check(tcx));
330 tcx.sess.track_errors(|| {
331 time(tcx.sess, "coherence checking", ||
332 coherence::check_coherence(tcx));
335 tcx.sess.track_errors(|| {
336 time(tcx.sess, "variance testing", ||
337 variance::test::test_variance(tcx));
340 time(tcx.sess, "wf checking", || check::check_wf_new(tcx))?;
342 time(tcx.sess, "item-types checking", || check::check_item_types(tcx))?;
344 time(tcx.sess, "item-bodies checking", || check::check_item_bodies(tcx))?;
346 check_unused::check_crate(tcx);
347 check_for_entry_fn(tcx);
349 tcx.sess.compile_status()
352 /// A quasi-deprecated helper used in rustdoc and save-analysis to get
353 /// the type from a HIR node.
354 pub fn hir_ty_to_ty<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, hir_ty: &hir::Ty) -> Ty<'tcx> {
355 // In case there are any projections etc, find the "environment"
356 // def-id that will be used to determine the traits/predicates in
357 // scope. This is derived from the enclosing item-like thing.
358 let env_node_id = tcx.hir.get_parent(hir_ty.id);
359 let env_def_id = tcx.hir.local_def_id(env_node_id);
360 let item_cx = self::collect::ItemCtxt::new(tcx, env_def_id);
361 astconv::AstConv::ast_ty_to_ty(&item_cx, hir_ty)
364 pub fn hir_trait_to_predicates<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, hir_trait: &hir::TraitRef)
365 -> (ty::PolyTraitRef<'tcx>, Vec<ty::PolyProjectionPredicate<'tcx>>) {
366 // In case there are any projections etc, find the "environment"
367 // def-id that will be used to determine the traits/predicates in
368 // scope. This is derived from the enclosing item-like thing.
369 let env_node_id = tcx.hir.get_parent(hir_trait.ref_id);
370 let env_def_id = tcx.hir.local_def_id(env_node_id);
371 let item_cx = self::collect::ItemCtxt::new(tcx, env_def_id);
372 let mut projections = Vec::new();
373 let principal = astconv::AstConv::instantiate_poly_trait_ref_inner(
374 &item_cx, hir_trait, tcx.types.err, &mut projections, true
376 (principal, projections)
379 __build_diagnostic_array! { librustc_typeck, DIAGNOSTICS }