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 - check: walks over function bodies and type checks them, inferring types for
54 local variables, type parameters, etc as necessary.
56 - infer: finds the types to use for each type variable such that
57 all subtyping and assignment constraints are met. In essence, the check
58 module specifies the constraints, and the infer module solves them.
62 This API is completely unstable and subject to change.
66 #![crate_name = "rustc_typeck"]
67 #![unstable(feature = "rustc_private", issue = "27812")]
68 #![crate_type = "dylib"]
69 #![crate_type = "rlib"]
70 #![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
71 html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
72 html_root_url = "https://doc.rust-lang.org/nightly/")]
75 #![allow(non_camel_case_types)]
77 #![feature(box_patterns)]
78 #![feature(box_syntax)]
79 #![feature(conservative_impl_trait)]
80 #![feature(loop_break_value)]
81 #![feature(never_type)]
83 #![feature(rustc_diagnostic_macros)]
84 #![feature(rustc_private)]
85 #![feature(staged_api)]
87 #[macro_use] extern crate log;
88 #[macro_use] extern crate syntax;
89 extern crate syntax_pos;
92 extern crate fmt_macros;
93 #[macro_use] extern crate rustc;
94 extern crate rustc_platform_intrinsics as intrinsics;
95 extern crate rustc_back;
96 extern crate rustc_const_math;
97 extern crate rustc_data_structures;
98 extern crate rustc_errors as errors;
100 pub use rustc::dep_graph;
103 pub use rustc::middle;
104 pub use rustc::session;
107 use hir::map as hir_map;
108 use rustc::infer::InferOk;
109 use rustc::ty::subst::Substs;
110 use rustc::ty::{self, Ty, TyCtxt};
111 use rustc::ty::maps::Providers;
112 use rustc::traits::{FulfillmentContext, ObligationCause, ObligationCauseCode, Reveal};
114 use util::common::time;
117 use syntax::abi::Abi;
118 use syntax_pos::Span;
121 // NB: This module needs to be declared first so diagnostics are
122 // registered before they are used.
126 pub mod check_unused;
129 mod constrained_type_params;
134 pub struct TypeAndSubsts<'tcx> {
135 pub substs: &'tcx Substs<'tcx>,
139 fn require_c_abi_if_variadic(tcx: TyCtxt,
143 if decl.variadic && abi != Abi::C {
144 let mut err = struct_span_err!(tcx.sess, span, E0045,
145 "variadic function must have C calling convention");
146 err.span_label(span, &("variadics require C calling conventions").to_string())
151 fn require_same_types<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
152 cause: &ObligationCause<'tcx>,
156 tcx.infer_ctxt((), Reveal::UserFacing).enter(|ref infcx| {
157 let mut fulfill_cx = FulfillmentContext::new();
158 match infcx.eq_types(false, &cause, expected, actual) {
159 Ok(InferOk { obligations, .. }) => {
160 fulfill_cx.register_predicate_obligations(infcx, obligations);
163 infcx.report_mismatched_types(cause, expected, actual, err).emit();
168 match fulfill_cx.select_all_or_error(infcx) {
171 infcx.report_fulfillment_errors(&errors);
178 fn check_main_fn_ty<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
179 main_id: ast::NodeId,
181 let main_def_id = tcx.hir.local_def_id(main_id);
182 let main_t = tcx.type_of(main_def_id);
185 match tcx.hir.find(main_id) {
186 Some(hir_map::NodeItem(it)) => {
188 hir::ItemFn(.., ref generics, _) => {
189 if generics.is_parameterized() {
190 struct_span_err!(tcx.sess, generics.span, E0131,
191 "main function is not allowed to have type parameters")
192 .span_label(generics.span,
193 &format!("main cannot have type parameters"))
203 let substs = tcx.intern_substs(&[]);
204 let se_ty = tcx.mk_fn_def(main_def_id, substs,
205 ty::Binder(tcx.mk_fn_sig(
209 hir::Unsafety::Normal,
216 &ObligationCause::new(main_span, main_id, ObligationCauseCode::MainFunctionType),
222 "main has a non-function type: found `{}`",
228 fn check_start_fn_ty<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
229 start_id: ast::NodeId,
231 let start_def_id = tcx.hir.local_def_id(start_id);
232 let start_t = tcx.type_of(start_def_id);
235 match tcx.hir.find(start_id) {
236 Some(hir_map::NodeItem(it)) => {
238 hir::ItemFn(..,ref ps,_)
239 if ps.is_parameterized() => {
240 struct_span_err!(tcx.sess, ps.span, E0132,
241 "start function is not allowed to have type parameters")
243 &format!("start function cannot have type parameters"))
253 let substs = tcx.intern_substs(&[]);
254 let se_ty = tcx.mk_fn_def(start_def_id, substs,
255 ty::Binder(tcx.mk_fn_sig(
258 tcx.mk_imm_ptr(tcx.mk_imm_ptr(tcx.types.u8))
262 hir::Unsafety::Normal,
269 &ObligationCause::new(start_span, start_id, ObligationCauseCode::StartFunctionType),
274 span_bug!(start_span,
275 "start has a non-function type: found `{}`",
281 fn check_for_entry_fn<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
282 if let Some((id, sp)) = *tcx.sess.entry_fn.borrow() {
283 match tcx.sess.entry_type.get() {
284 Some(config::EntryMain) => check_main_fn_ty(tcx, id, sp),
285 Some(config::EntryStart) => check_start_fn_ty(tcx, id, sp),
286 Some(config::EntryNone) => {}
287 None => bug!("entry function without a type")
292 pub fn provide(providers: &mut Providers) {
293 collect::provide(providers);
294 coherence::provide(providers);
295 check::provide(providers);
298 pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>)
299 -> Result<(), usize> {
300 let time_passes = tcx.sess.time_passes();
302 // this ensures that later parts of type checking can assume that items
303 // have valid types and not error
304 tcx.sess.track_errors(|| {
305 time(time_passes, "type collecting", ||
306 collect::collect_item_types(tcx));
310 time(time_passes, "variance inference", ||
311 variance::infer_variance(tcx));
313 tcx.sess.track_errors(|| {
314 time(time_passes, "impl wf inference", ||
315 impl_wf_check::impl_wf_check(tcx));
318 tcx.sess.track_errors(|| {
319 time(time_passes, "coherence checking", ||
320 coherence::check_coherence(tcx));
323 time(time_passes, "wf checking", || check::check_wf_new(tcx))?;
325 time(time_passes, "item-types checking", || check::check_item_types(tcx))?;
327 time(time_passes, "item-bodies checking", || check::check_item_bodies(tcx))?;
329 check_unused::check_crate(tcx);
330 check_for_entry_fn(tcx);
332 let err_count = tcx.sess.err_count();
340 __build_diagnostic_array! { librustc_typeck, DIAGNOSTICS }