]> git.lizzy.rs Git - rust.git/blob - src/librustc_typeck/lib.rs
report the total number of errors on compilation failure
[rust.git] / src / librustc_typeck / lib.rs
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.
4 //
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.
10
11 /*!
12
13 typeck.rs, an introduction
14
15 The type checker is responsible for:
16
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)
21
22 The main entry point is `check_crate()`.  Type checking operates in
23 several major phases:
24
25 1. The collect phase first passes over all items and determines their
26    type, without examining their "innards".
27
28 2. Variance inference then runs to compute the variance of each parameter
29
30 3. Coherence checks for overlapping or orphaned impls
31
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.
39
40 The type checker is defined into various submodules which are documented
41 independently:
42
43 - astconv: converts the AST representation of types
44   into the `ty` representation
45
46 - collect: computes the types of each top-level item and enters them into
47   the `tcx.types` table for later use
48
49 - coherence: enforces coherence rules, builds some tables
50
51 - variance: variance inference
52
53 - check: walks over function bodies and type checks them, inferring types for
54   local variables, type parameters, etc as necessary.
55
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.
59
60 # Note
61
62 This API is completely unstable and subject to change.
63
64 */
65
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/")]
72 #![deny(warnings)]
73
74 #![allow(non_camel_case_types)]
75
76 #![feature(advanced_slice_patterns)]
77 #![feature(box_patterns)]
78 #![feature(box_syntax)]
79 #![feature(conservative_impl_trait)]
80 #![feature(never_type)]
81 #![feature(quote)]
82 #![feature(rustc_diagnostic_macros)]
83 #![feature(slice_patterns)]
84
85 #[macro_use] extern crate log;
86 #[macro_use] extern crate syntax;
87 extern crate syntax_pos;
88
89 extern crate arena;
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_data_structures;
96 extern crate rustc_errors as errors;
97
98 pub use rustc::dep_graph;
99 pub use rustc::hir;
100 pub use rustc::lint;
101 pub use rustc::middle;
102 pub use rustc::session;
103 pub use rustc::util;
104
105 use hir::map as hir_map;
106 use rustc::infer::InferOk;
107 use rustc::ty::subst::Substs;
108 use rustc::ty::{self, Ty, TyCtxt};
109 use rustc::ty::maps::Providers;
110 use rustc::traits::{FulfillmentContext, ObligationCause, ObligationCauseCode, Reveal};
111 use session::{CompileIncomplete, config};
112 use util::common::time;
113
114 use syntax::ast;
115 use syntax::abi::Abi;
116 use syntax_pos::Span;
117
118 use std::iter;
119 // NB: This module needs to be declared first so diagnostics are
120 // registered before they are used.
121 pub mod diagnostics;
122
123 mod check;
124 mod check_unused;
125 mod astconv;
126 mod collect;
127 mod constrained_type_params;
128 mod impl_wf_check;
129 mod coherence;
130 mod variance;
131
132 pub struct TypeAndSubsts<'tcx> {
133     pub substs: &'tcx Substs<'tcx>,
134     pub ty: Ty<'tcx>,
135 }
136
137 fn require_c_abi_if_variadic(tcx: TyCtxt,
138                              decl: &hir::FnDecl,
139                              abi: Abi,
140                              span: Span) {
141     if decl.variadic && !(abi == Abi::C || abi == Abi::Cdecl) {
142         let mut err = struct_span_err!(tcx.sess, span, E0045,
143                   "variadic function must have C or cdecl calling convention");
144         err.span_label(span, "variadics require C or cdecl calling convention").emit();
145     }
146 }
147
148 fn require_same_types<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
149                                 cause: &ObligationCause<'tcx>,
150                                 expected: Ty<'tcx>,
151                                 actual: Ty<'tcx>)
152                                 -> bool {
153     tcx.infer_ctxt().enter(|ref infcx| {
154         let param_env = ty::ParamEnv::empty(Reveal::UserFacing);
155         let mut fulfill_cx = FulfillmentContext::new();
156         match infcx.at(&cause, param_env).eq(expected, actual) {
157             Ok(InferOk { obligations, .. }) => {
158                 fulfill_cx.register_predicate_obligations(infcx, obligations);
159             }
160             Err(err) => {
161                 infcx.report_mismatched_types(cause, expected, actual, err).emit();
162                 return false;
163             }
164         }
165
166         match fulfill_cx.select_all_or_error(infcx) {
167             Ok(()) => true,
168             Err(errors) => {
169                 infcx.report_fulfillment_errors(&errors, None);
170                 false
171             }
172         }
173     })
174 }
175
176 fn check_main_fn_ty<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
177                               main_id: ast::NodeId,
178                               main_span: Span) {
179     let main_def_id = tcx.hir.local_def_id(main_id);
180     let main_t = tcx.type_of(main_def_id);
181     match main_t.sty {
182         ty::TyFnDef(..) => {
183             match tcx.hir.find(main_id) {
184                 Some(hir_map::NodeItem(it)) => {
185                     match it.node {
186                         hir::ItemFn(.., ref generics, _) => {
187                             if generics.is_parameterized() {
188                                 struct_span_err!(tcx.sess, generics.span, E0131,
189                                          "main function is not allowed to have type parameters")
190                                     .span_label(generics.span,
191                                                 "main cannot have type parameters")
192                                     .emit();
193                                 return;
194                             }
195                         }
196                         _ => ()
197                     }
198                 }
199                 _ => ()
200             }
201             let se_ty = tcx.mk_fn_ptr(ty::Binder(
202                 tcx.mk_fn_sig(
203                     iter::empty(),
204                     tcx.mk_nil(),
205                     false,
206                     hir::Unsafety::Normal,
207                     Abi::Rust
208                 )
209             ));
210
211             require_same_types(
212                 tcx,
213                 &ObligationCause::new(main_span, main_id, ObligationCauseCode::MainFunctionType),
214                 se_ty,
215                 tcx.mk_fn_ptr(tcx.fn_sig(main_def_id)));
216         }
217         _ => {
218             span_bug!(main_span,
219                       "main has a non-function type: found `{}`",
220                       main_t);
221         }
222     }
223 }
224
225 fn check_start_fn_ty<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
226                                start_id: ast::NodeId,
227                                start_span: Span) {
228     let start_def_id = tcx.hir.local_def_id(start_id);
229     let start_t = tcx.type_of(start_def_id);
230     match start_t.sty {
231         ty::TyFnDef(..) => {
232             match tcx.hir.find(start_id) {
233                 Some(hir_map::NodeItem(it)) => {
234                     match it.node {
235                         hir::ItemFn(..,ref ps,_)
236                         if ps.is_parameterized() => {
237                             struct_span_err!(tcx.sess, ps.span, E0132,
238                                 "start function is not allowed to have type parameters")
239                                 .span_label(ps.span,
240                                             "start function cannot have type parameters")
241                                 .emit();
242                             return;
243                         }
244                         _ => ()
245                     }
246                 }
247                 _ => ()
248             }
249
250             let se_ty = tcx.mk_fn_ptr(ty::Binder(
251                 tcx.mk_fn_sig(
252                     [
253                         tcx.types.isize,
254                         tcx.mk_imm_ptr(tcx.mk_imm_ptr(tcx.types.u8))
255                     ].iter().cloned(),
256                     tcx.types.isize,
257                     false,
258                     hir::Unsafety::Normal,
259                     Abi::Rust
260                 )
261             ));
262
263             require_same_types(
264                 tcx,
265                 &ObligationCause::new(start_span, start_id, ObligationCauseCode::StartFunctionType),
266                 se_ty,
267                 tcx.mk_fn_ptr(tcx.fn_sig(start_def_id)));
268         }
269         _ => {
270             span_bug!(start_span,
271                       "start has a non-function type: found `{}`",
272                       start_t);
273         }
274     }
275 }
276
277 fn check_for_entry_fn<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
278     if let Some((id, sp)) = *tcx.sess.entry_fn.borrow() {
279         match tcx.sess.entry_type.get() {
280             Some(config::EntryMain) => check_main_fn_ty(tcx, id, sp),
281             Some(config::EntryStart) => check_start_fn_ty(tcx, id, sp),
282             Some(config::EntryNone) => {}
283             None => bug!("entry function without a type")
284         }
285     }
286 }
287
288 pub fn provide(providers: &mut Providers) {
289     collect::provide(providers);
290     coherence::provide(providers);
291     check::provide(providers);
292     variance::provide(providers);
293 }
294
295 pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>)
296                              -> Result<(), CompileIncomplete>
297 {
298     let time_passes = tcx.sess.time_passes();
299
300     // this ensures that later parts of type checking can assume that items
301     // have valid types and not error
302     tcx.sess.track_errors(|| {
303         time(time_passes, "type collecting", ||
304              collect::collect_item_types(tcx));
305
306     })?;
307
308     tcx.sess.track_errors(|| {
309         time(time_passes, "impl wf inference", ||
310              impl_wf_check::impl_wf_check(tcx));
311     })?;
312
313     tcx.sess.track_errors(|| {
314       time(time_passes, "coherence checking", ||
315           coherence::check_coherence(tcx));
316     })?;
317
318     tcx.sess.track_errors(|| {
319         time(time_passes, "variance testing", ||
320              variance::test::test_variance(tcx));
321     })?;
322
323     time(time_passes, "wf checking", || check::check_wf_new(tcx))?;
324
325     time(time_passes, "item-types checking", || check::check_item_types(tcx))?;
326
327     time(time_passes, "item-bodies checking", || check::check_item_bodies(tcx))?;
328
329     check_unused::check_crate(tcx);
330     check_for_entry_fn(tcx);
331
332     tcx.sess.compile_status()
333 }
334
335 /// A quasi-deprecated helper used in rustdoc and save-analysis to get
336 /// the type from a HIR node.
337 pub fn hir_ty_to_ty<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, hir_ty: &hir::Ty) -> Ty<'tcx> {
338     // In case there are any projections etc, find the "environment"
339     // def-id that will be used to determine the traits/predicates in
340     // scope.  This is derived from the enclosing item-like thing.
341     let env_node_id = tcx.hir.get_parent(hir_ty.id);
342     let env_def_id = tcx.hir.local_def_id(env_node_id);
343     let item_cx = self::collect::ItemCtxt::new(tcx, env_def_id);
344     item_cx.to_ty(hir_ty)
345 }
346
347 __build_diagnostic_array! { librustc_typeck, DIAGNOSTICS }