]> git.lizzy.rs Git - rust.git/blob - src/librustc_typeck/lib.rs
Auto merge of #29140 - sorear:dst-document-on-sized, r=alexcrichton
[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 // Do not remove on snapshot creation. Needed for bootstrap. (Issue #22364)
66 #![cfg_attr(stage0, feature(custom_attribute))]
67 #![crate_name = "rustc_typeck"]
68 #![unstable(feature = "rustc_private", issue = "27812")]
69 #![staged_api]
70 #![crate_type = "dylib"]
71 #![crate_type = "rlib"]
72 #![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
73       html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
74       html_root_url = "https://doc.rust-lang.org/nightly/")]
75
76 #![allow(non_camel_case_types)]
77
78 #![feature(box_patterns)]
79 #![feature(box_syntax)]
80 #![feature(drain)]
81 #![feature(iter_cmp)]
82 #![feature(iter_arith)]
83 #![feature(quote)]
84 #![feature(ref_slice)]
85 #![feature(rustc_diagnostic_macros)]
86 #![feature(rustc_private)]
87 #![feature(slice_splits)]
88 #![feature(staged_api)]
89 #![feature(vec_push_all)]
90 #![feature(cell_extras)]
91
92 #[macro_use] extern crate log;
93 #[macro_use] extern crate syntax;
94
95 extern crate arena;
96 extern crate fmt_macros;
97 extern crate rustc;
98 extern crate rustc_platform_intrinsics as intrinsics;
99 extern crate rustc_front;
100
101 pub use rustc::front;
102 pub use rustc::lint;
103 pub use rustc::metadata;
104 pub use rustc::middle;
105 pub use rustc::session;
106 pub use rustc::util;
107
108 use front::map as hir_map;
109 use middle::def;
110 use middle::infer;
111 use middle::subst;
112 use middle::ty::{self, Ty, HasTypeFlags};
113 use session::config;
114 use util::common::time;
115 use rustc_front::hir;
116
117 use syntax::codemap::Span;
118 use syntax::print::pprust::*;
119 use syntax::{ast, abi};
120
121 use std::cell::RefCell;
122
123 // NB: This module needs to be declared first so diagnostics are
124 // registered before they are used.
125 pub mod diagnostics;
126
127 pub mod check;
128 mod rscope;
129 mod astconv;
130 pub mod collect;
131 mod constrained_type_params;
132 pub mod coherence;
133 pub mod variance;
134
135 pub struct TypeAndSubsts<'tcx> {
136     pub substs: subst::Substs<'tcx>,
137     pub ty: Ty<'tcx>,
138 }
139
140 pub struct CrateCtxt<'a, 'tcx: 'a> {
141     // A mapping from method call sites to traits that have that method.
142     pub trait_map: ty::TraitMap,
143     /// A vector of every trait accessible in the whole crate
144     /// (i.e. including those from subcrates). This is used only for
145     /// error reporting, and so is lazily initialised and generally
146     /// shouldn't taint the common path (hence the RefCell).
147     pub all_traits: RefCell<Option<check::method::AllTraitsVec>>,
148     pub tcx: &'a ty::ctxt<'tcx>,
149 }
150
151 // Functions that write types into the node type table
152 fn write_ty_to_tcx<'tcx>(tcx: &ty::ctxt<'tcx>, node_id: ast::NodeId, ty: Ty<'tcx>) {
153     debug!("write_ty_to_tcx({}, {:?})", node_id,  ty);
154     assert!(!ty.needs_infer());
155     tcx.node_type_insert(node_id, ty);
156 }
157
158 fn write_substs_to_tcx<'tcx>(tcx: &ty::ctxt<'tcx>,
159                                  node_id: ast::NodeId,
160                                  item_substs: ty::ItemSubsts<'tcx>) {
161     if !item_substs.is_noop() {
162         debug!("write_substs_to_tcx({}, {:?})",
163                node_id,
164                item_substs);
165
166         assert!(!item_substs.substs.types.needs_infer());
167
168         tcx.tables.borrow_mut().item_substs.insert(node_id, item_substs);
169     }
170 }
171
172 fn lookup_full_def(tcx: &ty::ctxt, sp: Span, id: ast::NodeId) -> def::Def {
173     match tcx.def_map.borrow().get(&id) {
174         Some(x) => x.full_def(),
175         None => {
176             span_fatal!(tcx.sess, sp, E0242, "internal error looking up a definition")
177         }
178     }
179 }
180
181 fn require_c_abi_if_variadic(tcx: &ty::ctxt,
182                              decl: &hir::FnDecl,
183                              abi: abi::Abi,
184                              span: Span) {
185     if decl.variadic && abi != abi::C {
186         span_err!(tcx.sess, span, E0045,
187                   "variadic function must have C calling convention");
188     }
189 }
190
191 fn require_same_types<'a, 'tcx, M>(tcx: &ty::ctxt<'tcx>,
192                                    maybe_infcx: Option<&infer::InferCtxt<'a, 'tcx>>,
193                                    t1_is_expected: bool,
194                                    span: Span,
195                                    t1: Ty<'tcx>,
196                                    t2: Ty<'tcx>,
197                                    msg: M)
198                                    -> bool where
199     M: FnOnce() -> String,
200 {
201     let result = match maybe_infcx {
202         None => {
203             let infcx = infer::new_infer_ctxt(tcx, &tcx.tables, None, false);
204             infer::mk_eqty(&infcx, t1_is_expected, infer::Misc(span), t1, t2)
205         }
206         Some(infcx) => {
207             infer::mk_eqty(infcx, t1_is_expected, infer::Misc(span), t1, t2)
208         }
209     };
210
211     match result {
212         Ok(_) => true,
213         Err(ref terr) => {
214             span_err!(tcx.sess, span, E0211, "{}: {}", msg(), terr);
215             tcx.note_and_explain_type_err(terr, span);
216             false
217         }
218     }
219 }
220
221 fn check_main_fn_ty(ccx: &CrateCtxt,
222                     main_id: ast::NodeId,
223                     main_span: Span) {
224     let tcx = ccx.tcx;
225     let main_t = tcx.node_id_to_type(main_id);
226     match main_t.sty {
227         ty::TyBareFn(..) => {
228             match tcx.map.find(main_id) {
229                 Some(hir_map::NodeItem(it)) => {
230                     match it.node {
231                         hir::ItemFn(_, _, _, _, ref ps, _)
232                         if ps.is_parameterized() => {
233                             span_err!(ccx.tcx.sess, main_span, E0131,
234                                       "main function is not allowed to have type parameters");
235                             return;
236                         }
237                         _ => ()
238                     }
239                 }
240                 _ => ()
241             }
242             let main_def_id = tcx.map.local_def_id(main_id);
243             let se_ty = tcx.mk_fn(Some(main_def_id), tcx.mk_bare_fn(ty::BareFnTy {
244                 unsafety: hir::Unsafety::Normal,
245                 abi: abi::Rust,
246                 sig: ty::Binder(ty::FnSig {
247                     inputs: Vec::new(),
248                     output: ty::FnConverging(tcx.mk_nil()),
249                     variadic: false
250                 })
251             }));
252
253             require_same_types(tcx, None, false, main_span, main_t, se_ty,
254                 || {
255                     format!("main function expects type: `{}`",
256                              se_ty)
257                 });
258         }
259         _ => {
260             tcx.sess.span_bug(main_span,
261                               &format!("main has a non-function type: found `{}`",
262                                        main_t));
263         }
264     }
265 }
266
267 fn check_start_fn_ty(ccx: &CrateCtxt,
268                      start_id: ast::NodeId,
269                      start_span: Span) {
270     let tcx = ccx.tcx;
271     let start_t = tcx.node_id_to_type(start_id);
272     match start_t.sty {
273         ty::TyBareFn(..) => {
274             match tcx.map.find(start_id) {
275                 Some(hir_map::NodeItem(it)) => {
276                     match it.node {
277                         hir::ItemFn(_,_,_,_,ref ps,_)
278                         if ps.is_parameterized() => {
279                             span_err!(tcx.sess, start_span, E0132,
280                                       "start function is not allowed to have type parameters");
281                             return;
282                         }
283                         _ => ()
284                     }
285                 }
286                 _ => ()
287             }
288
289             let se_ty = tcx.mk_fn(Some(ccx.tcx.map.local_def_id(start_id)),
290                                   tcx.mk_bare_fn(ty::BareFnTy {
291                 unsafety: hir::Unsafety::Normal,
292                 abi: abi::Rust,
293                 sig: ty::Binder(ty::FnSig {
294                     inputs: vec!(
295                         tcx.types.isize,
296                         tcx.mk_imm_ptr(tcx.mk_imm_ptr(tcx.types.u8))
297                     ),
298                     output: ty::FnConverging(tcx.types.isize),
299                     variadic: false,
300                 }),
301             }));
302
303             require_same_types(tcx, None, false, start_span, start_t, se_ty,
304                 || {
305                     format!("start function expects type: `{}`",
306                              se_ty)
307                 });
308
309         }
310         _ => {
311             tcx.sess.span_bug(start_span,
312                               &format!("start has a non-function type: found `{}`",
313                                        start_t));
314         }
315     }
316 }
317
318 fn check_for_entry_fn(ccx: &CrateCtxt) {
319     let tcx = ccx.tcx;
320     match *tcx.sess.entry_fn.borrow() {
321         Some((id, sp)) => match tcx.sess.entry_type.get() {
322             Some(config::EntryMain) => check_main_fn_ty(ccx, id, sp),
323             Some(config::EntryStart) => check_start_fn_ty(ccx, id, sp),
324             Some(config::EntryNone) => {}
325             None => tcx.sess.bug("entry function without a type")
326         },
327         None => {}
328     }
329 }
330
331 pub fn check_crate(tcx: &ty::ctxt, trait_map: ty::TraitMap) {
332     let time_passes = tcx.sess.time_passes();
333     let ccx = CrateCtxt {
334         trait_map: trait_map,
335         all_traits: RefCell::new(None),
336         tcx: tcx
337     };
338
339     time(time_passes, "type collecting", ||
340          collect::collect_item_types(tcx));
341
342     // this ensures that later parts of type checking can assume that items
343     // have valid types and not error
344     tcx.sess.abort_if_errors();
345
346     time(time_passes, "variance inference", ||
347          variance::infer_variance(tcx));
348
349     time(time_passes, "coherence checking", ||
350         coherence::check_coherence(&ccx));
351
352     time(time_passes, "wf checking (old)", ||
353         check::check_wf_old(&ccx));
354
355     time(time_passes, "item-types checking", ||
356         check::check_item_types(&ccx));
357
358     time(time_passes, "item-bodies checking", ||
359         check::check_item_bodies(&ccx));
360
361     time(time_passes, "drop-impl checking", ||
362         check::check_drop_impls(&ccx));
363
364     // Do this last so that if there are errors in the old code, they
365     // get reported, and we don't get extra warnings.
366     time(time_passes, "wf checking (new)", ||
367         check::check_wf_new(&ccx));
368
369     check_for_entry_fn(&ccx);
370     tcx.sess.abort_if_errors();
371 }
372
373 __build_diagnostic_array! { librustc_typeck, DIAGNOSTICS }