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 #![crate_type = "dylib"]
68 #![crate_type = "rlib"]
69 #![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
70 html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
71 html_root_url = "https://doc.rust-lang.org/nightly/")]
74 #![allow(non_camel_case_types)]
76 #![feature(advanced_slice_patterns)]
77 #![feature(box_patterns)]
78 #![feature(box_syntax)]
79 #![feature(conservative_impl_trait)]
80 #![feature(never_type)]
82 #![feature(rustc_diagnostic_macros)]
83 #![feature(slice_patterns)]
85 #![cfg_attr(stage0, unstable(feature = "rustc_private", issue = "27812"))]
86 #![cfg_attr(stage0, feature(rustc_private))]
87 #![cfg_attr(stage0, feature(staged_api))]
88 #![cfg_attr(stage0, feature(loop_break_value))]
90 #[macro_use] extern crate log;
91 #[macro_use] extern crate syntax;
92 extern crate syntax_pos;
95 extern crate fmt_macros;
96 #[macro_use] extern crate rustc;
97 extern crate rustc_platform_intrinsics as intrinsics;
98 extern crate rustc_back;
99 extern crate rustc_const_math;
100 extern crate rustc_data_structures;
101 extern crate rustc_errors as errors;
103 pub use rustc::dep_graph;
106 pub use rustc::middle;
107 pub use rustc::session;
110 use hir::map as hir_map;
111 use rustc::infer::InferOk;
112 use rustc::ty::subst::Substs;
113 use rustc::ty::{self, Ty, TyCtxt};
114 use rustc::ty::maps::Providers;
115 use rustc::traits::{FulfillmentContext, ObligationCause, ObligationCauseCode, Reveal};
117 use util::common::time;
120 use syntax::abi::Abi;
121 use syntax_pos::Span;
124 // NB: This module needs to be declared first so diagnostics are
125 // registered before they are used.
132 mod constrained_type_params;
137 pub struct TypeAndSubsts<'tcx> {
138 pub substs: &'tcx Substs<'tcx>,
142 fn require_c_abi_if_variadic(tcx: TyCtxt,
146 if decl.variadic && !(abi == Abi::C || abi == Abi::Cdecl) {
147 let mut err = struct_span_err!(tcx.sess, span, E0045,
148 "variadic function must have C or cdecl calling convention");
149 err.span_label(span, "variadics require C or cdecl calling convention").emit();
153 fn require_same_types<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
154 cause: &ObligationCause<'tcx>,
158 tcx.infer_ctxt((), Reveal::UserFacing).enter(|ref infcx| {
159 let mut fulfill_cx = FulfillmentContext::new();
160 match infcx.eq_types(false, &cause, 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);
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.is_parameterized() {
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")
205 let substs = tcx.intern_substs(&[]);
206 let se_ty = tcx.mk_fn_def(main_def_id, substs,
207 ty::Binder(tcx.mk_fn_sig(
211 hir::Unsafety::Normal,
218 &ObligationCause::new(main_span, main_id, ObligationCauseCode::MainFunctionType),
224 "main has a non-function type: found `{}`",
230 fn check_start_fn_ty<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
231 start_id: ast::NodeId,
233 let start_def_id = tcx.hir.local_def_id(start_id);
234 let start_t = tcx.type_of(start_def_id);
237 match tcx.hir.find(start_id) {
238 Some(hir_map::NodeItem(it)) => {
240 hir::ItemFn(..,ref ps,_)
241 if ps.is_parameterized() => {
242 struct_span_err!(tcx.sess, ps.span, E0132,
243 "start function is not allowed to have type parameters")
245 "start function cannot have type parameters")
255 let substs = tcx.intern_substs(&[]);
256 let se_ty = tcx.mk_fn_def(start_def_id, substs,
257 ty::Binder(tcx.mk_fn_sig(
260 tcx.mk_imm_ptr(tcx.mk_imm_ptr(tcx.types.u8))
264 hir::Unsafety::Normal,
271 &ObligationCause::new(start_span, start_id, ObligationCauseCode::StartFunctionType),
276 span_bug!(start_span,
277 "start has a non-function type: found `{}`",
283 fn check_for_entry_fn<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
284 if let Some((id, sp)) = *tcx.sess.entry_fn.borrow() {
285 match tcx.sess.entry_type.get() {
286 Some(config::EntryMain) => check_main_fn_ty(tcx, id, sp),
287 Some(config::EntryStart) => check_start_fn_ty(tcx, id, sp),
288 Some(config::EntryNone) => {}
289 None => bug!("entry function without a type")
294 pub fn provide(providers: &mut Providers) {
295 collect::provide(providers);
296 coherence::provide(providers);
297 check::provide(providers);
298 variance::provide(providers);
301 pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>)
302 -> Result<(), usize> {
303 let time_passes = tcx.sess.time_passes();
305 // this ensures that later parts of type checking can assume that items
306 // have valid types and not error
307 tcx.sess.track_errors(|| {
308 time(time_passes, "type collecting", ||
309 collect::collect_item_types(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 tcx.sess.track_errors(|| {
324 time(time_passes, "variance testing", ||
325 variance::test::test_variance(tcx));
328 time(time_passes, "wf checking", || check::check_wf_new(tcx))?;
330 time(time_passes, "item-types checking", || check::check_item_types(tcx))?;
332 time(time_passes, "item-bodies checking", || check::check_item_bodies(tcx))?;
334 check_unused::check_crate(tcx);
335 check_for_entry_fn(tcx);
337 let err_count = tcx.sess.err_count();
345 /// A quasi-deprecated helper used in rustdoc and save-analysis to get
346 /// the type from a HIR node.
347 pub fn hir_ty_to_ty<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, hir_ty: &hir::Ty) -> Ty<'tcx> {
348 // In case there are any projections etc, find the "environment"
349 // def-id that will be used to determine the traits/predicates in
350 // scope. This is derived from the enclosing item-like thing.
351 let env_node_id = tcx.hir.get_parent(hir_ty.id);
352 let env_def_id = tcx.hir.local_def_id(env_node_id);
353 let item_cx = self::collect::ItemCtxt::new(tcx, env_def_id);
354 item_cx.to_ty(hir_ty)
357 __build_diagnostic_array! { librustc_typeck, DIAGNOSTICS }