]> git.lizzy.rs Git - rust.git/blob - src/librustc_typeck/lib.rs
Auto merge of #35525 - jonathandturner:rollup, r=jonathandturner
[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 `cx.tcache` 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 #![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))]
74
75 #![allow(non_camel_case_types)]
76
77 #![feature(box_patterns)]
78 #![feature(box_syntax)]
79 #![feature(quote)]
80 #![feature(rustc_diagnostic_macros)]
81 #![feature(rustc_private)]
82 #![feature(staged_api)]
83 #![feature(question_mark)]
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_const_eval;
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 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::ProjectionMode;
111 use session::{config, CompileResult};
112 use util::common::time;
113
114 use syntax::ast;
115 use syntax::abi::Abi;
116 use syntax_pos::Span;
117
118 use std::cell::RefCell;
119 use util::nodemap::NodeMap;
120
121 // NB: This module needs to be declared first so diagnostics are
122 // registered before they are used.
123 pub mod diagnostics;
124
125 pub mod check;
126 pub mod check_unused;
127 mod rscope;
128 mod astconv;
129 pub mod collect;
130 mod constrained_type_params;
131 pub mod coherence;
132 pub mod variance;
133
134 pub struct TypeAndSubsts<'tcx> {
135     pub substs: Substs<'tcx>,
136     pub ty: Ty<'tcx>,
137 }
138
139 pub struct CrateCtxt<'a, 'tcx: 'a> {
140     ast_ty_to_ty_cache: RefCell<NodeMap<Ty<'tcx>>>,
141
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>>,
147
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>>,
151
152     pub tcx: TyCtxt<'a, 'tcx, 'tcx>,
153 }
154
155 // Functions that write types into the node type table
156 fn write_ty_to_tcx<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, node_id: ast::NodeId, ty: Ty<'tcx>) {
157     debug!("write_ty_to_tcx({}, {:?})", node_id,  ty);
158     assert!(!ty.needs_infer());
159     ccx.tcx.node_type_insert(node_id, ty);
160 }
161
162 fn write_substs_to_tcx<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
163                                  node_id: ast::NodeId,
164                                  item_substs: ty::ItemSubsts<'tcx>) {
165     if !item_substs.is_noop() {
166         debug!("write_substs_to_tcx({}, {:?})",
167                node_id,
168                item_substs);
169
170         assert!(!item_substs.substs.types.needs_infer());
171
172         ccx.tcx.tables.borrow_mut().item_substs.insert(node_id, item_substs);
173     }
174 }
175
176 fn require_c_abi_if_variadic(tcx: TyCtxt,
177                              decl: &hir::FnDecl,
178                              abi: Abi,
179                              span: Span) {
180     if decl.variadic && abi != Abi::C {
181         span_err!(tcx.sess, span, E0045,
182                   "variadic function must have C calling convention");
183     }
184 }
185
186 fn require_same_types<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
187                                 origin: TypeOrigin,
188                                 t1: Ty<'tcx>,
189                                 t2: Ty<'tcx>)
190                                 -> bool {
191     ccx.tcx.infer_ctxt(None, None, ProjectionMode::AnyFinal).enter(|infcx| {
192         if let Err(err) = infcx.eq_types(false, origin.clone(), t1, t2) {
193             infcx.report_mismatched_types(origin, t1, t2, err);
194             false
195         } else {
196             true
197         }
198     })
199 }
200
201 fn check_main_fn_ty(ccx: &CrateCtxt,
202                     main_id: ast::NodeId,
203                     main_span: Span) {
204     let tcx = ccx.tcx;
205     let main_t = tcx.node_id_to_type(main_id);
206     match main_t.sty {
207         ty::TyFnDef(..) => {
208             match tcx.map.find(main_id) {
209                 Some(hir_map::NodeItem(it)) => {
210                     match it.node {
211                         hir::ItemFn(_, _, _, _, ref generics, _) => {
212                             if let Some(gen_span) = generics.span() {
213                                 struct_span_err!(ccx.tcx.sess, gen_span, E0131,
214                                          "main function is not allowed to have type parameters")
215                                     .span_label(gen_span,
216                                                 &format!("main cannot have type parameters"))
217                                     .emit();
218                                 return;
219                             }
220                         }
221                         _ => ()
222                     }
223                 }
224                 _ => ()
225             }
226             let main_def_id = tcx.map.local_def_id(main_id);
227             let substs = tcx.mk_substs(Substs::empty());
228             let se_ty = tcx.mk_fn_def(main_def_id, substs,
229                                       tcx.mk_bare_fn(ty::BareFnTy {
230                 unsafety: hir::Unsafety::Normal,
231                 abi: Abi::Rust,
232                 sig: ty::Binder(ty::FnSig {
233                     inputs: Vec::new(),
234                     output: ty::FnConverging(tcx.mk_nil()),
235                     variadic: false
236                 })
237             }));
238
239             require_same_types(
240                 ccx,
241                 TypeOrigin::MainFunctionType(main_span),
242                 main_t,
243                 se_ty);
244         }
245         _ => {
246             span_bug!(main_span,
247                       "main has a non-function type: found `{}`",
248                       main_t);
249         }
250     }
251 }
252
253 fn check_start_fn_ty(ccx: &CrateCtxt,
254                      start_id: ast::NodeId,
255                      start_span: Span) {
256     let tcx = ccx.tcx;
257     let start_t = tcx.node_id_to_type(start_id);
258     match start_t.sty {
259         ty::TyFnDef(..) => {
260             match tcx.map.find(start_id) {
261                 Some(hir_map::NodeItem(it)) => {
262                     match it.node {
263                         hir::ItemFn(_,_,_,_,ref ps,_)
264                         if ps.is_parameterized() => {
265                             let sp = if let Some(sp) = ps.span() { sp } else { start_span };
266                             struct_span_err!(tcx.sess, sp, E0132,
267                                 "start function is not allowed to have type parameters")
268                                 .span_label(sp,
269                                             &format!("start function cannot have type parameters"))
270                                 .emit();
271                             return;
272                         }
273                         _ => ()
274                     }
275                 }
276                 _ => ()
277             }
278
279             let start_def_id = ccx.tcx.map.local_def_id(start_id);
280             let substs = tcx.mk_substs(Substs::empty());
281             let se_ty = tcx.mk_fn_def(start_def_id, substs,
282                                       tcx.mk_bare_fn(ty::BareFnTy {
283                 unsafety: hir::Unsafety::Normal,
284                 abi: Abi::Rust,
285                 sig: ty::Binder(ty::FnSig {
286                     inputs: vec!(
287                         tcx.types.isize,
288                         tcx.mk_imm_ptr(tcx.mk_imm_ptr(tcx.types.u8))
289                     ),
290                     output: ty::FnConverging(tcx.types.isize),
291                     variadic: false,
292                 }),
293             }));
294
295             require_same_types(
296                 ccx,
297                 TypeOrigin::StartFunctionType(start_span),
298                 start_t,
299                 se_ty);
300         }
301         _ => {
302             span_bug!(start_span,
303                       "start has a non-function type: found `{}`",
304                       start_t);
305         }
306     }
307 }
308
309 fn check_for_entry_fn(ccx: &CrateCtxt) {
310     let tcx = ccx.tcx;
311     let _task = tcx.dep_graph.in_task(DepNode::CheckEntryFn);
312     if let Some((id, sp)) = *tcx.sess.entry_fn.borrow() {
313         match tcx.sess.entry_type.get() {
314             Some(config::EntryMain) => check_main_fn_ty(ccx, id, sp),
315             Some(config::EntryStart) => check_start_fn_ty(ccx, id, sp),
316             Some(config::EntryNone) => {}
317             None => bug!("entry function without a type")
318         }
319     }
320 }
321
322 pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>)
323                              -> CompileResult {
324     let time_passes = tcx.sess.time_passes();
325     let ccx = CrateCtxt {
326         ast_ty_to_ty_cache: RefCell::new(NodeMap()),
327         all_traits: RefCell::new(None),
328         stack: RefCell::new(Vec::new()),
329         tcx: tcx
330     };
331
332     // this ensures that later parts of type checking can assume that items
333     // have valid types and not error
334     tcx.sess.track_errors(|| {
335         time(time_passes, "type collecting", ||
336              collect::collect_item_types(&ccx));
337
338     })?;
339
340     time(time_passes, "variance inference", ||
341          variance::infer_variance(tcx));
342
343     tcx.sess.track_errors(|| {
344       time(time_passes, "coherence checking", ||
345           coherence::check_coherence(&ccx));
346     })?;
347
348     time(time_passes, "wf checking", || check::check_wf_new(&ccx))?;
349
350     time(time_passes, "item-types checking", || check::check_item_types(&ccx))?;
351
352     time(time_passes, "item-bodies checking", || check::check_item_bodies(&ccx))?;
353
354     time(time_passes, "drop-impl checking", || check::check_drop_impls(&ccx))?;
355
356     check_unused::check_crate(tcx);
357     check_for_entry_fn(&ccx);
358
359     let err_count = tcx.sess.err_count();
360     if err_count == 0 {
361         Ok(())
362     } else {
363         Err(err_count)
364     }
365 }
366
367 __build_diagnostic_array! { librustc_typeck, DIAGNOSTICS }