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 `cx.tcache` 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.
65 // Do not remove on snapshot creation. Needed for bootstrap. (Issue #22364)
66 #![cfg_attr(stage0, feature(custom_attribute))]
67 #![crate_name = "rustc_typeck"]
68 #![unstable(feature = "rustc_private", issue = "27812")]
69 #![cfg_attr(stage0, staged_api)]
70 #![crate_type = "dylib"]
71 #![crate_type = "rlib"]
72 #![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
73 html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
74 html_root_url = "https://doc.rust-lang.org/nightly/")]
76 #![allow(non_camel_case_types)]
78 #![feature(box_patterns)]
79 #![feature(box_syntax)]
82 #![feature(iter_arith)]
84 #![feature(rustc_diagnostic_macros)]
85 #![feature(rustc_private)]
86 #![feature(staged_api)]
87 #![feature(vec_push_all)]
88 #![feature(cell_extras)]
90 #[macro_use] extern crate log;
91 #[macro_use] extern crate syntax;
94 extern crate fmt_macros;
96 extern crate rustc_platform_intrinsics as intrinsics;
97 extern crate rustc_front;
98 extern crate rustc_back;
100 pub use rustc::front;
102 pub use rustc::middle;
103 pub use rustc::session;
106 use front::map as hir_map;
108 use middle::infer::{self, TypeOrigin};
110 use middle::ty::{self, Ty, HasTypeFlags};
112 use util::common::time;
113 use rustc_front::hir;
115 use syntax::codemap::Span;
116 use syntax::print::pprust::*;
117 use syntax::{ast, abi};
119 use std::cell::RefCell;
121 // NB: This module needs to be declared first so diagnostics are
122 // registered before they are used.
129 mod constrained_type_params;
133 pub struct TypeAndSubsts<'tcx> {
134 pub substs: subst::Substs<'tcx>,
138 pub struct CrateCtxt<'a, 'tcx: 'a> {
139 // A mapping from method call sites to traits that have that method.
140 pub trait_map: ty::TraitMap,
141 /// A vector of every trait accessible in the whole crate
142 /// (i.e. including those from subcrates). This is used only for
143 /// error reporting, and so is lazily initialised and generally
144 /// shouldn't taint the common path (hence the RefCell).
145 pub all_traits: RefCell<Option<check::method::AllTraitsVec>>,
146 pub tcx: &'a ty::ctxt<'tcx>,
149 // Functions that write types into the node type table
150 fn write_ty_to_tcx<'tcx>(tcx: &ty::ctxt<'tcx>, node_id: ast::NodeId, ty: Ty<'tcx>) {
151 debug!("write_ty_to_tcx({}, {:?})", node_id, ty);
152 assert!(!ty.needs_infer());
153 tcx.node_type_insert(node_id, ty);
156 fn write_substs_to_tcx<'tcx>(tcx: &ty::ctxt<'tcx>,
157 node_id: ast::NodeId,
158 item_substs: ty::ItemSubsts<'tcx>) {
159 if !item_substs.is_noop() {
160 debug!("write_substs_to_tcx({}, {:?})",
164 assert!(!item_substs.substs.types.needs_infer());
166 tcx.tables.borrow_mut().item_substs.insert(node_id, item_substs);
170 fn lookup_full_def(tcx: &ty::ctxt, sp: Span, id: ast::NodeId) -> def::Def {
171 match tcx.def_map.borrow().get(&id) {
172 Some(x) => x.full_def(),
174 span_fatal!(tcx.sess, sp, E0242, "internal error looking up a definition")
179 fn require_c_abi_if_variadic(tcx: &ty::ctxt,
183 if decl.variadic && abi != abi::C {
184 span_err!(tcx.sess, span, E0045,
185 "variadic function must have C calling convention");
189 fn require_same_types<'a, 'tcx, M>(tcx: &ty::ctxt<'tcx>,
190 maybe_infcx: Option<&infer::InferCtxt<'a, 'tcx>>,
191 t1_is_expected: bool,
197 M: FnOnce() -> String,
199 let result = match maybe_infcx {
201 let infcx = infer::new_infer_ctxt(tcx, &tcx.tables, None, false);
202 infer::mk_eqty(&infcx, t1_is_expected, TypeOrigin::Misc(span), t1, t2)
205 infer::mk_eqty(infcx, t1_is_expected, TypeOrigin::Misc(span), t1, t2)
212 span_err!(tcx.sess, span, E0211, "{}: {}", msg(), terr);
213 tcx.note_and_explain_type_err(terr, span);
219 fn check_main_fn_ty(ccx: &CrateCtxt,
220 main_id: ast::NodeId,
223 let main_t = tcx.node_id_to_type(main_id);
225 ty::TyBareFn(..) => {
226 match tcx.map.find(main_id) {
227 Some(hir_map::NodeItem(it)) => {
229 hir::ItemFn(_, _, _, _, ref ps, _)
230 if ps.is_parameterized() => {
231 span_err!(ccx.tcx.sess, main_span, E0131,
232 "main function is not allowed to have type parameters");
240 let main_def_id = tcx.map.local_def_id(main_id);
241 let se_ty = tcx.mk_fn(Some(main_def_id), tcx.mk_bare_fn(ty::BareFnTy {
242 unsafety: hir::Unsafety::Normal,
244 sig: ty::Binder(ty::FnSig {
246 output: ty::FnConverging(tcx.mk_nil()),
251 require_same_types(tcx, None, false, main_span, main_t, se_ty,
253 format!("main function expects type: `{}`",
258 tcx.sess.span_bug(main_span,
259 &format!("main has a non-function type: found `{}`",
265 fn check_start_fn_ty(ccx: &CrateCtxt,
266 start_id: ast::NodeId,
269 let start_t = tcx.node_id_to_type(start_id);
271 ty::TyBareFn(..) => {
272 match tcx.map.find(start_id) {
273 Some(hir_map::NodeItem(it)) => {
275 hir::ItemFn(_,_,_,_,ref ps,_)
276 if ps.is_parameterized() => {
277 span_err!(tcx.sess, start_span, E0132,
278 "start function is not allowed to have type parameters");
287 let se_ty = tcx.mk_fn(Some(ccx.tcx.map.local_def_id(start_id)),
288 tcx.mk_bare_fn(ty::BareFnTy {
289 unsafety: hir::Unsafety::Normal,
291 sig: ty::Binder(ty::FnSig {
294 tcx.mk_imm_ptr(tcx.mk_imm_ptr(tcx.types.u8))
296 output: ty::FnConverging(tcx.types.isize),
301 require_same_types(tcx, None, false, start_span, start_t, se_ty,
303 format!("start function expects type: `{}`",
309 tcx.sess.span_bug(start_span,
310 &format!("start has a non-function type: found `{}`",
316 fn check_for_entry_fn(ccx: &CrateCtxt) {
318 match *tcx.sess.entry_fn.borrow() {
319 Some((id, sp)) => match tcx.sess.entry_type.get() {
320 Some(config::EntryMain) => check_main_fn_ty(ccx, id, sp),
321 Some(config::EntryStart) => check_start_fn_ty(ccx, id, sp),
322 Some(config::EntryNone) => {}
323 None => tcx.sess.bug("entry function without a type")
329 pub fn check_crate(tcx: &ty::ctxt, trait_map: ty::TraitMap) {
330 let time_passes = tcx.sess.time_passes();
331 let ccx = CrateCtxt {
332 trait_map: trait_map,
333 all_traits: RefCell::new(None),
337 time(time_passes, "type collecting", ||
338 collect::collect_item_types(tcx));
340 // this ensures that later parts of type checking can assume that items
341 // have valid types and not error
342 tcx.sess.abort_if_errors();
344 time(time_passes, "variance inference", ||
345 variance::infer_variance(tcx));
347 time(time_passes, "coherence checking", ||
348 coherence::check_coherence(&ccx));
350 time(time_passes, "wf checking (old)", ||
351 check::check_wf_old(&ccx));
353 time(time_passes, "item-types checking", ||
354 check::check_item_types(&ccx));
356 time(time_passes, "item-bodies checking", ||
357 check::check_item_bodies(&ccx));
359 time(time_passes, "drop-impl checking", ||
360 check::check_drop_impls(&ccx));
362 // Do this last so that if there are errors in the old code, they
363 // get reported, and we don't get extra warnings.
364 time(time_passes, "wf checking (new)", ||
365 check::check_wf_new(&ccx));
367 check_for_entry_fn(&ccx);
368 tcx.sess.abort_if_errors();
371 __build_diagnostic_array! { librustc_typeck, DIAGNOSTICS }