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 - outlives: outlives inference
55 - check: walks over function bodies and type checks them, inferring types for
56 local variables, type parameters, etc as necessary.
58 - infer: finds the types to use for each type variable such that
59 all subtyping and assignment constraints are met. In essence, the check
60 module specifies the constraints, and the infer module solves them.
64 This API is completely unstable and subject to change.
68 #![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
69 html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
70 html_root_url = "https://doc.rust-lang.org/nightly/")]
73 #![allow(non_camel_case_types)]
75 #![cfg_attr(stage0, feature(advanced_slice_patterns))]
76 #![feature(box_patterns)]
77 #![feature(box_syntax)]
78 #![cfg_attr(stage0, feature(conservative_impl_trait))]
79 #![cfg_attr(stage0, feature(copy_closures, clone_closures))]
80 #![feature(crate_visibility_modifier)]
82 #![cfg_attr(stage0, feature(match_default_bindings))]
83 #![feature(exhaustive_patterns)]
84 #![feature(option_filter)]
86 #![feature(refcell_replace_swap)]
87 #![feature(rustc_diagnostic_macros)]
88 #![feature(slice_patterns)]
89 #![cfg_attr(stage0, feature(i128_type))]
90 #![cfg_attr(stage0, feature(never_type))]
91 #![feature(dyn_trait)]
93 #[macro_use] extern crate log;
94 #[macro_use] extern crate syntax;
95 extern crate syntax_pos;
98 #[macro_use] extern crate rustc;
99 extern crate rustc_platform_intrinsics as intrinsics;
100 extern crate rustc_const_math;
101 extern crate rustc_data_structures;
102 extern crate rustc_errors as errors;
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::{ObligationCause, ObligationCauseCode, TraitEngine};
116 use session::{CompileIncomplete, config};
117 use util::common::time;
120 use syntax::abi::Abi;
121 use syntax_pos::Span;
125 // NB: This module needs to be declared first so diagnostics are
126 // registered before they are used.
134 mod constrained_type_params;
135 mod structured_errors;
141 pub struct TypeAndSubsts<'tcx> {
142 substs: &'tcx Substs<'tcx>,
146 fn require_c_abi_if_variadic(tcx: TyCtxt,
150 if decl.variadic && !(abi == Abi::C || abi == Abi::Cdecl) {
151 let mut err = struct_span_err!(tcx.sess, span, E0045,
152 "variadic function must have C or cdecl calling convention");
153 err.span_label(span, "variadics require C or cdecl calling convention").emit();
157 fn require_same_types<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
158 cause: &ObligationCause<'tcx>,
162 tcx.infer_ctxt().enter(|ref infcx| {
163 let param_env = ty::ParamEnv::empty();
164 let mut fulfill_cx = TraitEngine::new(infcx.tcx);
165 match infcx.at(&cause, param_env).eq(expected, actual) {
166 Ok(InferOk { obligations, .. }) => {
167 fulfill_cx.register_predicate_obligations(infcx, obligations);
170 infcx.report_mismatched_types(cause, expected, actual, err).emit();
175 match fulfill_cx.select_all_or_error(infcx) {
178 infcx.report_fulfillment_errors(&errors, None, false);
185 fn check_main_fn_ty<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
186 main_id: ast::NodeId,
188 let main_def_id = tcx.hir.local_def_id(main_id);
189 let main_t = tcx.type_of(main_def_id);
192 match tcx.hir.find(main_id) {
193 Some(hir_map::NodeItem(it)) => {
195 hir::ItemFn(.., ref generics, _) => {
196 if !generics.params.is_empty() {
197 struct_span_err!(tcx.sess, generics.span, E0131,
198 "main function is not allowed to have type parameters")
199 .span_label(generics.span,
200 "main cannot have type parameters")
211 let actual = tcx.fn_sig(main_def_id);
212 let expected_return_type = if tcx.lang_items().termination().is_some() {
213 // we take the return type of the given main function, the real check is done
215 actual.output().skip_binder()
217 // standard () main return type
221 let se_ty = tcx.mk_fn_ptr(ty::Binder(
224 expected_return_type,
226 hir::Unsafety::Normal,
233 &ObligationCause::new(main_span, main_id, ObligationCauseCode::MainFunctionType),
235 tcx.mk_fn_ptr(actual));
239 "main has a non-function type: found `{}`",
245 fn check_start_fn_ty<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
246 start_id: ast::NodeId,
248 let start_def_id = tcx.hir.local_def_id(start_id);
249 let start_t = tcx.type_of(start_def_id);
252 match tcx.hir.find(start_id) {
253 Some(hir_map::NodeItem(it)) => {
255 hir::ItemFn(..,ref ps,_)
256 if !ps.params.is_empty() => {
257 struct_span_err!(tcx.sess, ps.span, E0132,
258 "start function is not allowed to have type parameters")
260 "start function cannot have type parameters")
270 let se_ty = tcx.mk_fn_ptr(ty::Binder(
274 tcx.mk_imm_ptr(tcx.mk_imm_ptr(tcx.types.u8))
278 hir::Unsafety::Normal,
285 &ObligationCause::new(start_span, start_id, ObligationCauseCode::StartFunctionType),
287 tcx.mk_fn_ptr(tcx.fn_sig(start_def_id)));
290 span_bug!(start_span,
291 "start has a non-function type: found `{}`",
297 fn check_for_entry_fn<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
298 if let Some((id, sp)) = *tcx.sess.entry_fn.borrow() {
299 match tcx.sess.entry_type.get() {
300 Some(config::EntryMain) => check_main_fn_ty(tcx, id, sp),
301 Some(config::EntryStart) => check_start_fn_ty(tcx, id, sp),
302 Some(config::EntryNone) => {}
303 None => bug!("entry function without a type")
308 pub fn provide(providers: &mut Providers) {
309 collect::provide(providers);
310 coherence::provide(providers);
311 check::provide(providers);
312 variance::provide(providers);
313 outlives::provide(providers);
316 pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>)
317 -> Result<(), CompileIncomplete>
319 // this ensures that later parts of type checking can assume that items
320 // have valid types and not error
321 tcx.sess.track_errors(|| {
322 time(tcx.sess, "type collecting", ||
323 collect::collect_item_types(tcx));
327 tcx.sess.track_errors(|| {
328 time(tcx.sess, "outlives testing", ||
329 outlives::test::test_inferred_outlives(tcx));
332 tcx.sess.track_errors(|| {
333 time(tcx.sess, "impl wf inference", ||
334 impl_wf_check::impl_wf_check(tcx));
337 tcx.sess.track_errors(|| {
338 time(tcx.sess, "coherence checking", ||
339 coherence::check_coherence(tcx));
342 tcx.sess.track_errors(|| {
343 time(tcx.sess, "variance testing", ||
344 variance::test::test_variance(tcx));
347 time(tcx.sess, "wf checking", || check::check_wf_new(tcx))?;
349 time(tcx.sess, "item-types checking", || check::check_item_types(tcx))?;
351 time(tcx.sess, "item-bodies checking", || check::check_item_bodies(tcx))?;
353 check_unused::check_crate(tcx);
354 check_for_entry_fn(tcx);
356 tcx.sess.compile_status()
359 /// A quasi-deprecated helper used in rustdoc and save-analysis to get
360 /// the type from a HIR node.
361 pub fn hir_ty_to_ty<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, hir_ty: &hir::Ty) -> Ty<'tcx> {
362 // In case there are any projections etc, find the "environment"
363 // def-id that will be used to determine the traits/predicates in
364 // scope. This is derived from the enclosing item-like thing.
365 let env_node_id = tcx.hir.get_parent(hir_ty.id);
366 let env_def_id = tcx.hir.local_def_id(env_node_id);
367 let item_cx = self::collect::ItemCtxt::new(tcx, env_def_id);
368 astconv::AstConv::ast_ty_to_ty(&item_cx, hir_ty)
371 pub fn hir_trait_to_predicates<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, hir_trait: &hir::TraitRef)
372 -> (ty::PolyTraitRef<'tcx>, Vec<ty::PolyProjectionPredicate<'tcx>>) {
373 // In case there are any projections etc, find the "environment"
374 // def-id that will be used to determine the traits/predicates in
375 // scope. This is derived from the enclosing item-like thing.
376 let env_node_id = tcx.hir.get_parent(hir_trait.ref_id);
377 let env_def_id = tcx.hir.local_def_id(env_node_id);
378 let item_cx = self::collect::ItemCtxt::new(tcx, env_def_id);
379 let mut projections = Vec::new();
380 let principal = astconv::AstConv::instantiate_poly_trait_ref_inner(
381 &item_cx, hir_trait, tcx.types.err, &mut projections, true
383 (principal, projections)
386 __build_diagnostic_array! { librustc_typeck, DIAGNOSTICS }