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