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