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")]
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(ref_slice)]
85 #![feature(rustc_diagnostic_macros)]
86 #![feature(rustc_private)]
87 #![feature(slice_splits)]
88 #![feature(staged_api)]
89 #![feature(vec_push_all)]
90 #![feature(cell_extras)]
92 #[macro_use] extern crate log;
93 #[macro_use] extern crate syntax;
96 extern crate fmt_macros;
98 extern crate rustc_platform_intrinsics as intrinsics;
99 extern crate rustc_front;
101 pub use rustc::front;
103 pub use rustc::metadata;
104 pub use rustc::middle;
105 pub use rustc::session;
108 use front::map as hir_map;
112 use middle::ty::{self, Ty, HasTypeFlags};
114 use util::common::time;
115 use rustc_front::hir;
117 use syntax::codemap::Span;
118 use syntax::print::pprust::*;
119 use syntax::{ast, abi};
121 use std::cell::RefCell;
123 // NB: This module needs to be declared first so diagnostics are
124 // registered before they are used.
131 mod constrained_type_params;
135 pub struct TypeAndSubsts<'tcx> {
136 pub substs: subst::Substs<'tcx>,
140 pub struct CrateCtxt<'a, 'tcx: 'a> {
141 // A mapping from method call sites to traits that have that method.
142 pub trait_map: ty::TraitMap,
143 /// A vector of every trait accessible in the whole crate
144 /// (i.e. including those from subcrates). This is used only for
145 /// error reporting, and so is lazily initialised and generally
146 /// shouldn't taint the common path (hence the RefCell).
147 pub all_traits: RefCell<Option<check::method::AllTraitsVec>>,
148 pub tcx: &'a ty::ctxt<'tcx>,
151 // Functions that write types into the node type table
152 fn write_ty_to_tcx<'tcx>(tcx: &ty::ctxt<'tcx>, node_id: ast::NodeId, ty: Ty<'tcx>) {
153 debug!("write_ty_to_tcx({}, {:?})", node_id, ty);
154 assert!(!ty.needs_infer());
155 tcx.node_type_insert(node_id, ty);
158 fn write_substs_to_tcx<'tcx>(tcx: &ty::ctxt<'tcx>,
159 node_id: ast::NodeId,
160 item_substs: ty::ItemSubsts<'tcx>) {
161 if !item_substs.is_noop() {
162 debug!("write_substs_to_tcx({}, {:?})",
166 assert!(!item_substs.substs.types.needs_infer());
168 tcx.tables.borrow_mut().item_substs.insert(node_id, item_substs);
172 fn lookup_full_def(tcx: &ty::ctxt, sp: Span, id: ast::NodeId) -> def::Def {
173 match tcx.def_map.borrow().get(&id) {
174 Some(x) => x.full_def(),
176 span_fatal!(tcx.sess, sp, E0242, "internal error looking up a definition")
181 fn require_c_abi_if_variadic(tcx: &ty::ctxt,
185 if decl.variadic && abi != abi::C {
186 span_err!(tcx.sess, span, E0045,
187 "variadic function must have C calling convention");
191 fn require_same_types<'a, 'tcx, M>(tcx: &ty::ctxt<'tcx>,
192 maybe_infcx: Option<&infer::InferCtxt<'a, 'tcx>>,
193 t1_is_expected: bool,
199 M: FnOnce() -> String,
201 let result = match maybe_infcx {
203 let infcx = infer::new_infer_ctxt(tcx, &tcx.tables, None, false);
204 infer::mk_eqty(&infcx, t1_is_expected, infer::Misc(span), t1, t2)
207 infer::mk_eqty(infcx, t1_is_expected, infer::Misc(span), t1, t2)
214 span_err!(tcx.sess, span, E0211, "{}: {}", msg(), terr);
215 tcx.note_and_explain_type_err(terr, span);
221 fn check_main_fn_ty(ccx: &CrateCtxt,
222 main_id: ast::NodeId,
225 let main_t = tcx.node_id_to_type(main_id);
227 ty::TyBareFn(..) => {
228 match tcx.map.find(main_id) {
229 Some(hir_map::NodeItem(it)) => {
231 hir::ItemFn(_, _, _, _, ref ps, _)
232 if ps.is_parameterized() => {
233 span_err!(ccx.tcx.sess, main_span, E0131,
234 "main function is not allowed to have type parameters");
242 let main_def_id = tcx.map.local_def_id(main_id);
243 let se_ty = tcx.mk_fn(Some(main_def_id), tcx.mk_bare_fn(ty::BareFnTy {
244 unsafety: hir::Unsafety::Normal,
246 sig: ty::Binder(ty::FnSig {
248 output: ty::FnConverging(tcx.mk_nil()),
253 require_same_types(tcx, None, false, main_span, main_t, se_ty,
255 format!("main function expects type: `{}`",
260 tcx.sess.span_bug(main_span,
261 &format!("main has a non-function type: found `{}`",
267 fn check_start_fn_ty(ccx: &CrateCtxt,
268 start_id: ast::NodeId,
271 let start_t = tcx.node_id_to_type(start_id);
273 ty::TyBareFn(..) => {
274 match tcx.map.find(start_id) {
275 Some(hir_map::NodeItem(it)) => {
277 hir::ItemFn(_,_,_,_,ref ps,_)
278 if ps.is_parameterized() => {
279 span_err!(tcx.sess, start_span, E0132,
280 "start function is not allowed to have type parameters");
289 let se_ty = tcx.mk_fn(Some(ccx.tcx.map.local_def_id(start_id)),
290 tcx.mk_bare_fn(ty::BareFnTy {
291 unsafety: hir::Unsafety::Normal,
293 sig: ty::Binder(ty::FnSig {
296 tcx.mk_imm_ptr(tcx.mk_imm_ptr(tcx.types.u8))
298 output: ty::FnConverging(tcx.types.isize),
303 require_same_types(tcx, None, false, start_span, start_t, se_ty,
305 format!("start function expects type: `{}`",
311 tcx.sess.span_bug(start_span,
312 &format!("start has a non-function type: found `{}`",
318 fn check_for_entry_fn(ccx: &CrateCtxt) {
320 match *tcx.sess.entry_fn.borrow() {
321 Some((id, sp)) => match tcx.sess.entry_type.get() {
322 Some(config::EntryMain) => check_main_fn_ty(ccx, id, sp),
323 Some(config::EntryStart) => check_start_fn_ty(ccx, id, sp),
324 Some(config::EntryNone) => {}
325 None => tcx.sess.bug("entry function without a type")
331 pub fn check_crate(tcx: &ty::ctxt, trait_map: ty::TraitMap) {
332 let time_passes = tcx.sess.time_passes();
333 let ccx = CrateCtxt {
334 trait_map: trait_map,
335 all_traits: RefCell::new(None),
339 time(time_passes, "type collecting", ||
340 collect::collect_item_types(tcx));
342 // this ensures that later parts of type checking can assume that items
343 // have valid types and not error
344 tcx.sess.abort_if_errors();
346 time(time_passes, "variance inference", ||
347 variance::infer_variance(tcx));
349 time(time_passes, "coherence checking", ||
350 coherence::check_coherence(&ccx));
352 time(time_passes, "wf checking (old)", ||
353 check::check_wf_old(&ccx));
355 time(time_passes, "item-types checking", ||
356 check::check_item_types(&ccx));
358 time(time_passes, "item-bodies checking", ||
359 check::check_item_bodies(&ccx));
361 time(time_passes, "drop-impl checking", ||
362 check::check_drop_impls(&ccx));
364 // Do this last so that if there are errors in the old code, they
365 // get reported, and we don't get extra warnings.
366 time(time_passes, "wf checking (new)", ||
367 check::check_wf_new(&ccx));
369 check_for_entry_fn(&ccx);
370 tcx.sess.abort_if_errors();
373 __build_diagnostic_array! { librustc_typeck, DIAGNOSTICS }