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.
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/")]
73 #![cfg_attr(not(stage0), deny(warnings))]
75 #![allow(non_camel_case_types)]
77 #![feature(box_patterns)]
78 #![feature(box_syntax)]
80 #![feature(rustc_diagnostic_macros)]
81 #![feature(rustc_private)]
82 #![feature(staged_api)]
83 #![feature(question_mark)]
85 #[macro_use] extern crate log;
86 #[macro_use] extern crate syntax;
87 extern crate syntax_pos;
90 extern crate fmt_macros;
91 #[macro_use] extern crate rustc;
92 extern crate rustc_platform_intrinsics as intrinsics;
93 extern crate rustc_back;
94 extern crate rustc_const_math;
95 extern crate rustc_const_eval;
96 extern crate rustc_errors as errors;
98 pub use rustc::dep_graph;
101 pub use rustc::middle;
102 pub use rustc::session;
105 use dep_graph::DepNode;
106 use hir::map as hir_map;
107 use rustc::infer::TypeOrigin;
108 use rustc::ty::subst::Substs;
109 use rustc::ty::{self, Ty, TyCtxt, TypeFoldable};
110 use rustc::traits::{self, Reveal};
111 use session::{config, CompileResult};
112 use util::common::time;
115 use syntax::abi::Abi;
116 use syntax_pos::Span;
118 use std::cell::RefCell;
119 use util::nodemap::NodeMap;
121 // NB: This module needs to be declared first so diagnostics are
122 // registered before they are used.
126 pub mod check_unused;
130 mod constrained_type_params;
134 pub struct TypeAndSubsts<'tcx> {
135 pub substs: Substs<'tcx>,
139 pub struct CrateCtxt<'a, 'tcx: 'a> {
140 ast_ty_to_ty_cache: RefCell<NodeMap<Ty<'tcx>>>,
142 /// A vector of every trait accessible in the whole crate
143 /// (i.e. including those from subcrates). This is used only for
144 /// error reporting, and so is lazily initialised and generally
145 /// shouldn't taint the common path (hence the RefCell).
146 pub all_traits: RefCell<Option<check::method::AllTraitsVec>>,
148 /// This stack is used to identify cycles in the user's source.
149 /// Note that these cycles can cross multiple items.
150 pub stack: RefCell<Vec<collect::AstConvRequest>>,
152 pub tcx: TyCtxt<'a, 'tcx, 'tcx>,
154 /// Obligations which will have to be checked at the end of
155 /// type-checking, after all functions have been inferred.
156 /// The key is the NodeId of the item the obligations were from.
157 pub deferred_obligations: RefCell<NodeMap<Vec<traits::DeferredObligation<'tcx>>>>,
160 // Functions that write types into the node type table
161 fn write_ty_to_tcx<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, node_id: ast::NodeId, ty: Ty<'tcx>) {
162 debug!("write_ty_to_tcx({}, {:?})", node_id, ty);
163 assert!(!ty.needs_infer());
164 ccx.tcx.node_type_insert(node_id, ty);
167 fn write_substs_to_tcx<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
168 node_id: ast::NodeId,
169 item_substs: ty::ItemSubsts<'tcx>) {
170 if !item_substs.is_noop() {
171 debug!("write_substs_to_tcx({}, {:?})",
175 assert!(!item_substs.substs.types.needs_infer());
177 ccx.tcx.tables.borrow_mut().item_substs.insert(node_id, item_substs);
181 fn require_c_abi_if_variadic(tcx: TyCtxt,
185 if decl.variadic && abi != Abi::C {
186 let mut err = struct_span_err!(tcx.sess, span, E0045,
187 "variadic function must have C calling convention");
188 err.span_label(span, &("variadics require C calling conventions").to_string())
193 fn require_same_types<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
198 ccx.tcx.infer_ctxt(None, None, Reveal::NotSpecializable).enter(|infcx| {
199 if let Err(err) = infcx.eq_types(false, origin.clone(), t1, t2) {
200 infcx.report_mismatched_types(origin, t1, t2, err);
208 fn check_main_fn_ty(ccx: &CrateCtxt,
209 main_id: ast::NodeId,
212 let main_t = tcx.node_id_to_type(main_id);
215 match tcx.map.find(main_id) {
216 Some(hir_map::NodeItem(it)) => {
218 hir::ItemFn(_, _, _, _, ref generics, _) => {
219 if let Some(gen_span) = generics.span() {
220 struct_span_err!(ccx.tcx.sess, gen_span, E0131,
221 "main function is not allowed to have type parameters")
222 .span_label(gen_span,
223 &format!("main cannot have type parameters"))
233 let main_def_id = tcx.map.local_def_id(main_id);
234 let substs = tcx.mk_substs(Substs::empty());
235 let se_ty = tcx.mk_fn_def(main_def_id, substs,
236 tcx.mk_bare_fn(ty::BareFnTy {
237 unsafety: hir::Unsafety::Normal,
239 sig: ty::Binder(ty::FnSig {
241 output: ty::FnConverging(tcx.mk_nil()),
248 TypeOrigin::MainFunctionType(main_span),
254 "main has a non-function type: found `{}`",
260 fn check_start_fn_ty(ccx: &CrateCtxt,
261 start_id: ast::NodeId,
264 let start_t = tcx.node_id_to_type(start_id);
267 match tcx.map.find(start_id) {
268 Some(hir_map::NodeItem(it)) => {
270 hir::ItemFn(_,_,_,_,ref ps,_)
271 if ps.is_parameterized() => {
272 let sp = if let Some(sp) = ps.span() { sp } else { start_span };
273 struct_span_err!(tcx.sess, sp, E0132,
274 "start function is not allowed to have type parameters")
276 &format!("start function cannot have type parameters"))
286 let start_def_id = ccx.tcx.map.local_def_id(start_id);
287 let substs = tcx.mk_substs(Substs::empty());
288 let se_ty = tcx.mk_fn_def(start_def_id, substs,
289 tcx.mk_bare_fn(ty::BareFnTy {
290 unsafety: hir::Unsafety::Normal,
292 sig: ty::Binder(ty::FnSig {
295 tcx.mk_imm_ptr(tcx.mk_imm_ptr(tcx.types.u8))
297 output: ty::FnConverging(tcx.types.isize),
304 TypeOrigin::StartFunctionType(start_span),
309 span_bug!(start_span,
310 "start has a non-function type: found `{}`",
316 fn check_for_entry_fn(ccx: &CrateCtxt) {
318 let _task = tcx.dep_graph.in_task(DepNode::CheckEntryFn);
319 if let Some((id, sp)) = *tcx.sess.entry_fn.borrow() {
320 match tcx.sess.entry_type.get() {
321 Some(config::EntryMain) => check_main_fn_ty(ccx, id, sp),
322 Some(config::EntryStart) => check_start_fn_ty(ccx, id, sp),
323 Some(config::EntryNone) => {}
324 None => bug!("entry function without a type")
329 pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>)
331 let time_passes = tcx.sess.time_passes();
332 let ccx = CrateCtxt {
333 ast_ty_to_ty_cache: RefCell::new(NodeMap()),
334 all_traits: RefCell::new(None),
335 stack: RefCell::new(Vec::new()),
337 deferred_obligations: RefCell::new(NodeMap()),
340 // this ensures that later parts of type checking can assume that items
341 // have valid types and not error
342 tcx.sess.track_errors(|| {
343 time(time_passes, "type collecting", ||
344 collect::collect_item_types(&ccx));
348 time(time_passes, "variance inference", ||
349 variance::infer_variance(tcx));
351 tcx.sess.track_errors(|| {
352 time(time_passes, "coherence checking", ||
353 coherence::check_coherence(&ccx));
356 time(time_passes, "wf checking", || check::check_wf_new(&ccx))?;
358 time(time_passes, "item-types checking", || check::check_item_types(&ccx))?;
360 time(time_passes, "item-bodies checking", || check::check_item_bodies(&ccx))?;
362 time(time_passes, "drop-impl checking", || check::check_drop_impls(&ccx))?;
364 check_unused::check_crate(tcx);
365 check_for_entry_fn(&ccx);
367 let err_count = tcx.sess.err_count();
375 __build_diagnostic_array! { librustc_typeck, DIAGNOSTICS }