5 The type checker is responsible for:
7 1. Determining the type of each expression.
8 2. Resolving methods and traits.
9 3. Guaranteeing that most type rules are met. ("Most?", you say, "why most?"
10 Well, dear reader, read on)
12 The main entry point is `check_crate()`. Type checking operates in
15 1. The collect phase first passes over all items and determines their
16 type, without examining their "innards".
18 2. Variance inference then runs to compute the variance of each parameter.
20 3. Coherence checks for overlapping or orphaned impls.
22 4. Finally, the check phase then checks function bodies and so forth.
23 Within the check phase, we check each function body one at a time
24 (bodies of function expressions are checked as part of the
25 containing function). Inference is used to supply types wherever
26 they are unknown. The actual checking of a function itself has
27 several phases (check, regionck, writeback), as discussed in the
28 documentation for the `check` module.
30 The type checker is defined into various submodules which are documented
33 - astconv: converts the AST representation of types
34 into the `ty` representation.
36 - collect: computes the types of each top-level item and enters them into
37 the `tcx.types` table for later use.
39 - coherence: enforces coherence rules, builds some tables.
41 - variance: variance inference
43 - outlives: outlives inference
45 - check: walks over function bodies and type checks them, inferring types for
46 local variables, type parameters, etc as necessary.
48 - infer: finds the types to use for each type variable such that
49 all subtyping and assignment constraints are met. In essence, the check
50 module specifies the constraints, and the infer module solves them.
54 This API is completely unstable and subject to change.
58 #![doc(html_root_url = "https://doc.rust-lang.org/nightly/")]
60 #![allow(non_camel_case_types)]
62 #![feature(box_patterns)]
63 #![feature(box_syntax)]
64 #![feature(crate_visibility_modifier)]
65 #![feature(exhaustive_patterns)]
66 #![feature(in_band_lifetimes)]
68 #![feature(slice_patterns)]
69 #![feature(never_type)]
71 #![recursion_limit="256"]
73 #[macro_use] extern crate log;
74 #[macro_use] extern crate syntax;
76 #[macro_use] extern crate rustc;
85 mod constrained_generic_params;
86 mod structured_errors;
92 use rustc_target::spec::abi::Abi;
93 use rustc::hir::{self, Node};
94 use rustc::hir::def_id::{DefId, LOCAL_CRATE};
95 use rustc::infer::InferOk;
99 use rustc::util::common::ErrorReported;
100 use rustc::session::config::EntryFnType;
101 use rustc::traits::{ObligationCause, ObligationCauseCode, TraitEngine, TraitEngineExt};
102 use rustc::ty::subst::SubstsRef;
103 use rustc::ty::{self, Ty, TyCtxt};
104 use rustc::ty::query::Providers;
106 use syntax_pos::{DUMMY_SP, Span};
107 use util::common::time;
111 use astconv::{AstConv, Bounds};
112 pub use collect::checked_type_of;
114 pub struct TypeAndSubsts<'tcx> {
115 substs: SubstsRef<'tcx>,
119 fn require_c_abi_if_c_variadic(tcx: TyCtxt<'_>, decl: &hir::FnDecl, abi: Abi, span: Span) {
120 if decl.c_variadic && !(abi == Abi::C || abi == Abi::Cdecl) {
121 let mut err = struct_span_err!(tcx.sess, span, E0045,
122 "C-variadic function must have C or cdecl calling convention");
123 err.span_label(span, "C-variadics require C or cdecl calling convention").emit();
127 fn require_same_types<'tcx>(
129 cause: &ObligationCause<'tcx>,
133 tcx.infer_ctxt().enter(|ref infcx| {
134 let param_env = ty::ParamEnv::empty();
135 let mut fulfill_cx = TraitEngine::new(infcx.tcx);
136 match infcx.at(&cause, param_env).eq(expected, actual) {
137 Ok(InferOk { obligations, .. }) => {
138 fulfill_cx.register_predicate_obligations(infcx, obligations);
141 infcx.report_mismatched_types(cause, expected, actual, err).emit();
146 match fulfill_cx.select_all_or_error(infcx) {
149 infcx.report_fulfillment_errors(&errors, None, false);
156 fn check_main_fn_ty(tcx: TyCtxt<'_>, main_def_id: DefId) {
157 let main_id = tcx.hir().as_local_hir_id(main_def_id).unwrap();
158 let main_span = tcx.def_span(main_def_id);
159 let main_t = tcx.type_of(main_def_id);
162 if let Some(Node::Item(it)) = tcx.hir().find(main_id) {
163 if let hir::ItemKind::Fn(.., ref generics, _) = it.kind {
164 let mut error = false;
165 if !generics.params.is_empty() {
166 let msg = "`main` function is not allowed to have generic \
167 parameters".to_owned();
168 let label = "`main` cannot have generic parameters".to_string();
169 struct_span_err!(tcx.sess, generics.span, E0131, "{}", msg)
170 .span_label(generics.span, label)
174 if let Some(sp) = generics.where_clause.span() {
175 struct_span_err!(tcx.sess, sp, E0646,
176 "`main` function is not allowed to have a `where` clause")
177 .span_label(sp, "`main` cannot have a `where` clause")
187 let actual = tcx.fn_sig(main_def_id);
188 let expected_return_type = if tcx.lang_items().termination().is_some() {
189 // we take the return type of the given main function, the real check is done
191 actual.output().skip_binder()
193 // standard () main return type
197 let se_ty = tcx.mk_fn_ptr(ty::Binder::bind(
200 expected_return_type,
202 hir::Unsafety::Normal,
209 &ObligationCause::new(main_span, main_id, ObligationCauseCode::MainFunctionType),
211 tcx.mk_fn_ptr(actual));
215 "main has a non-function type: found `{}`",
221 fn check_start_fn_ty(tcx: TyCtxt<'_>, start_def_id: DefId) {
222 let start_id = tcx.hir().as_local_hir_id(start_def_id).unwrap();
223 let start_span = tcx.def_span(start_def_id);
224 let start_t = tcx.type_of(start_def_id);
227 if let Some(Node::Item(it)) = tcx.hir().find(start_id) {
228 if let hir::ItemKind::Fn(.., ref generics, _) = it.kind {
229 let mut error = false;
230 if !generics.params.is_empty() {
231 struct_span_err!(tcx.sess, generics.span, E0132,
232 "start function is not allowed to have type parameters")
233 .span_label(generics.span,
234 "start function cannot have type parameters")
238 if let Some(sp) = generics.where_clause.span() {
239 struct_span_err!(tcx.sess, sp, E0647,
240 "start function is not allowed to have a `where` clause")
241 .span_label(sp, "start function cannot have a `where` clause")
251 let se_ty = tcx.mk_fn_ptr(ty::Binder::bind(
255 tcx.mk_imm_ptr(tcx.mk_imm_ptr(tcx.types.u8))
259 hir::Unsafety::Normal,
266 &ObligationCause::new(start_span, start_id, ObligationCauseCode::StartFunctionType),
268 tcx.mk_fn_ptr(tcx.fn_sig(start_def_id)));
271 span_bug!(start_span,
272 "start has a non-function type: found `{}`",
278 fn check_for_entry_fn(tcx: TyCtxt<'_>) {
279 match tcx.entry_fn(LOCAL_CRATE) {
280 Some((def_id, EntryFnType::Main)) => check_main_fn_ty(tcx, def_id),
281 Some((def_id, EntryFnType::Start)) => check_start_fn_ty(tcx, def_id),
286 pub fn provide(providers: &mut Providers<'_>) {
287 collect::provide(providers);
288 coherence::provide(providers);
289 check::provide(providers);
290 variance::provide(providers);
291 outlives::provide(providers);
292 impl_wf_check::provide(providers);
295 pub fn check_crate(tcx: TyCtxt<'_>) -> Result<(), ErrorReported> {
296 let _prof_timer = tcx.prof.generic_activity("type_check_crate");
298 // this ensures that later parts of type checking can assume that items
299 // have valid types and not error
300 // FIXME(matthewjasper) We shouldn't need to do this.
301 tcx.sess.track_errors(|| {
302 time(tcx.sess, "type collecting", || {
303 for &module in tcx.hir().krate().modules.keys() {
304 tcx.ensure().collect_mod_item_types(tcx.hir().local_def_id(module));
309 if tcx.features().rustc_attrs {
310 tcx.sess.track_errors(|| {
311 time(tcx.sess, "outlives testing", ||
312 outlives::test::test_inferred_outlives(tcx));
316 tcx.sess.track_errors(|| {
317 time(tcx.sess, "impl wf inference", ||
318 impl_wf_check::impl_wf_check(tcx));
321 tcx.sess.track_errors(|| {
322 time(tcx.sess, "coherence checking", ||
323 coherence::check_coherence(tcx));
326 if tcx.features().rustc_attrs {
327 tcx.sess.track_errors(|| {
328 time(tcx.sess, "variance testing", ||
329 variance::test::test_variance(tcx));
333 tcx.sess.track_errors(|| {
334 time(tcx.sess, "wf checking", || check::check_wf_new(tcx));
337 time(tcx.sess, "item-types checking", || {
338 for &module in tcx.hir().krate().modules.keys() {
339 tcx.ensure().check_mod_item_types(tcx.hir().local_def_id(module));
343 time(tcx.sess, "item-bodies checking", || tcx.typeck_item_bodies(LOCAL_CRATE));
345 check_unused::check_crate(tcx);
346 check_for_entry_fn(tcx);
348 if tcx.sess.err_count() == 0 {
355 /// A quasi-deprecated helper used in rustdoc and clippy to get
356 /// the type from a HIR node.
357 pub fn hir_ty_to_ty<'tcx>(tcx: TyCtxt<'tcx>, hir_ty: &hir::Ty) -> Ty<'tcx> {
358 // In case there are any projections, etc., find the "environment"
359 // def-ID that will be used to determine the traits/predicates in
360 // scope. This is derived from the enclosing item-like thing.
361 let env_node_id = tcx.hir().get_parent_item(hir_ty.hir_id);
362 let env_def_id = tcx.hir().local_def_id(env_node_id);
363 let item_cx = self::collect::ItemCtxt::new(tcx, env_def_id);
365 astconv::AstConv::ast_ty_to_ty(&item_cx, hir_ty)
368 pub fn hir_trait_to_predicates<'tcx>(
370 hir_trait: &hir::TraitRef,
372 // In case there are any projections, etc., find the "environment"
373 // def-ID that will be used to determine the traits/predicates in
374 // scope. This is derived from the enclosing item-like thing.
375 let env_hir_id = tcx.hir().get_parent_item(hir_trait.hir_ref_id);
376 let env_def_id = tcx.hir().local_def_id(env_hir_id);
377 let item_cx = self::collect::ItemCtxt::new(tcx, env_def_id);
378 let mut bounds = Bounds::default();
379 let _ = AstConv::instantiate_poly_trait_ref_inner(
380 &item_cx, hir_trait, DUMMY_SP, tcx.types.err, &mut bounds, true