]> git.lizzy.rs Git - rust.git/blob - src/librustc_typeck/lib.rs
Auto merge of #41433 - estebank:constructor, r=michaelwoerister
[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 #![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 #![deny(warnings)]
74
75 #![allow(non_camel_case_types)]
76
77 #![feature(box_patterns)]
78 #![feature(box_syntax)]
79 #![feature(conservative_impl_trait)]
80 #![feature(loop_break_value)]
81 #![feature(never_type)]
82 #![feature(quote)]
83 #![feature(rustc_diagnostic_macros)]
84 #![feature(rustc_private)]
85 #![feature(staged_api)]
86
87 #[macro_use] extern crate log;
88 #[macro_use] extern crate syntax;
89 extern crate syntax_pos;
90
91 extern crate arena;
92 extern crate fmt_macros;
93 #[macro_use] extern crate rustc;
94 extern crate rustc_platform_intrinsics as intrinsics;
95 extern crate rustc_back;
96 extern crate rustc_const_math;
97 extern crate rustc_data_structures;
98 extern crate rustc_errors as errors;
99
100 pub use rustc::dep_graph;
101 pub use rustc::hir;
102 pub use rustc::lint;
103 pub use rustc::middle;
104 pub use rustc::session;
105 pub use rustc::util;
106
107 use hir::map as hir_map;
108 use rustc::infer::InferOk;
109 use rustc::ty::subst::Substs;
110 use rustc::ty::{self, Ty, TyCtxt};
111 use rustc::ty::maps::Providers;
112 use rustc::traits::{FulfillmentContext, ObligationCause, ObligationCauseCode, Reveal};
113 use session::config;
114 use util::common::time;
115
116 use syntax::ast;
117 use syntax::abi::Abi;
118 use syntax_pos::Span;
119
120 use std::iter;
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 astconv;
128 pub mod collect;
129 mod constrained_type_params;
130 mod impl_wf_check;
131 pub mod coherence;
132 pub mod variance;
133
134 pub struct TypeAndSubsts<'tcx> {
135     pub substs: &'tcx Substs<'tcx>,
136     pub ty: Ty<'tcx>,
137 }
138
139 fn require_c_abi_if_variadic(tcx: TyCtxt,
140                              decl: &hir::FnDecl,
141                              abi: Abi,
142                              span: Span) {
143     if decl.variadic && abi != Abi::C {
144         let mut err = struct_span_err!(tcx.sess, span, E0045,
145                   "variadic function must have C calling convention");
146         err.span_label(span, &("variadics require C calling conventions").to_string())
147             .emit();
148     }
149 }
150
151 fn require_same_types<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
152                                 cause: &ObligationCause<'tcx>,
153                                 expected: Ty<'tcx>,
154                                 actual: Ty<'tcx>)
155                                 -> bool {
156     tcx.infer_ctxt((), Reveal::UserFacing).enter(|ref infcx| {
157         let mut fulfill_cx = FulfillmentContext::new();
158         match infcx.eq_types(false, &cause, expected, actual) {
159             Ok(InferOk { obligations, .. }) => {
160                 fulfill_cx.register_predicate_obligations(infcx, obligations);
161             }
162             Err(err) => {
163                 infcx.report_mismatched_types(cause, expected, actual, err).emit();
164                 return false;
165             }
166         }
167
168         match fulfill_cx.select_all_or_error(infcx) {
169             Ok(()) => true,
170             Err(errors) => {
171                 infcx.report_fulfillment_errors(&errors);
172                 false
173             }
174         }
175     })
176 }
177
178 fn check_main_fn_ty<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
179                               main_id: ast::NodeId,
180                               main_span: Span) {
181     let main_def_id = tcx.hir.local_def_id(main_id);
182     let main_t = tcx.type_of(main_def_id);
183     match main_t.sty {
184         ty::TyFnDef(..) => {
185             match tcx.hir.find(main_id) {
186                 Some(hir_map::NodeItem(it)) => {
187                     match it.node {
188                         hir::ItemFn(.., ref generics, _) => {
189                             if generics.is_parameterized() {
190                                 struct_span_err!(tcx.sess, generics.span, E0131,
191                                          "main function is not allowed to have type parameters")
192                                     .span_label(generics.span,
193                                                 &format!("main cannot have type parameters"))
194                                     .emit();
195                                 return;
196                             }
197                         }
198                         _ => ()
199                     }
200                 }
201                 _ => ()
202             }
203             let substs = tcx.intern_substs(&[]);
204             let se_ty = tcx.mk_fn_def(main_def_id, substs,
205                 ty::Binder(tcx.mk_fn_sig(
206                     iter::empty(),
207                     tcx.mk_nil(),
208                     false,
209                     hir::Unsafety::Normal,
210                     Abi::Rust
211                 ))
212             );
213
214             require_same_types(
215                 tcx,
216                 &ObligationCause::new(main_span, main_id, ObligationCauseCode::MainFunctionType),
217                 se_ty,
218                 main_t);
219         }
220         _ => {
221             span_bug!(main_span,
222                       "main has a non-function type: found `{}`",
223                       main_t);
224         }
225     }
226 }
227
228 fn check_start_fn_ty<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
229                                start_id: ast::NodeId,
230                                start_span: Span) {
231     let start_def_id = tcx.hir.local_def_id(start_id);
232     let start_t = tcx.type_of(start_def_id);
233     match start_t.sty {
234         ty::TyFnDef(..) => {
235             match tcx.hir.find(start_id) {
236                 Some(hir_map::NodeItem(it)) => {
237                     match it.node {
238                         hir::ItemFn(..,ref ps,_)
239                         if ps.is_parameterized() => {
240                             struct_span_err!(tcx.sess, ps.span, E0132,
241                                 "start function is not allowed to have type parameters")
242                                 .span_label(ps.span,
243                                             &format!("start function cannot have type parameters"))
244                                 .emit();
245                             return;
246                         }
247                         _ => ()
248                     }
249                 }
250                 _ => ()
251             }
252
253             let substs = tcx.intern_substs(&[]);
254             let se_ty = tcx.mk_fn_def(start_def_id, substs,
255                 ty::Binder(tcx.mk_fn_sig(
256                     [
257                         tcx.types.isize,
258                         tcx.mk_imm_ptr(tcx.mk_imm_ptr(tcx.types.u8))
259                     ].iter().cloned(),
260                     tcx.types.isize,
261                     false,
262                     hir::Unsafety::Normal,
263                     Abi::Rust
264                 ))
265             );
266
267             require_same_types(
268                 tcx,
269                 &ObligationCause::new(start_span, start_id, ObligationCauseCode::StartFunctionType),
270                 se_ty,
271                 start_t);
272         }
273         _ => {
274             span_bug!(start_span,
275                       "start has a non-function type: found `{}`",
276                       start_t);
277         }
278     }
279 }
280
281 fn check_for_entry_fn<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
282     if let Some((id, sp)) = *tcx.sess.entry_fn.borrow() {
283         match tcx.sess.entry_type.get() {
284             Some(config::EntryMain) => check_main_fn_ty(tcx, id, sp),
285             Some(config::EntryStart) => check_start_fn_ty(tcx, id, sp),
286             Some(config::EntryNone) => {}
287             None => bug!("entry function without a type")
288         }
289     }
290 }
291
292 pub fn provide(providers: &mut Providers) {
293     collect::provide(providers);
294     coherence::provide(providers);
295     check::provide(providers);
296 }
297
298 pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>)
299                              -> Result<(), usize> {
300     let time_passes = tcx.sess.time_passes();
301
302     // this ensures that later parts of type checking can assume that items
303     // have valid types and not error
304     tcx.sess.track_errors(|| {
305         time(time_passes, "type collecting", ||
306              collect::collect_item_types(tcx));
307
308     })?;
309
310     time(time_passes, "variance inference", ||
311          variance::infer_variance(tcx));
312
313     tcx.sess.track_errors(|| {
314         time(time_passes, "impl wf inference", ||
315              impl_wf_check::impl_wf_check(tcx));
316     })?;
317
318     tcx.sess.track_errors(|| {
319       time(time_passes, "coherence checking", ||
320           coherence::check_coherence(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     let err_count = tcx.sess.err_count();
333     if err_count == 0 {
334         Ok(())
335     } else {
336         Err(err_count)
337     }
338 }
339
340 __build_diagnostic_array! { librustc_typeck, DIAGNOSTICS }