]> git.lizzy.rs Git - rust.git/blob - src/librustc_typeck/lib.rs
rustc: Remove #![unstable] annotation
[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 #![crate_type = "dylib"]
68 #![crate_type = "rlib"]
69 #![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
70       html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
71       html_root_url = "https://doc.rust-lang.org/nightly/")]
72 #![deny(warnings)]
73
74 #![allow(non_camel_case_types)]
75
76 #![feature(box_patterns)]
77 #![feature(box_syntax)]
78 #![feature(conservative_impl_trait)]
79 #![feature(loop_break_value)]
80 #![feature(never_type)]
81 #![feature(quote)]
82 #![feature(rustc_diagnostic_macros)]
83
84 #![cfg_attr(stage0, unstable(feature = "rustc_private", issue = "27812"))]
85 #![cfg_attr(stage0, feature(rustc_private))]
86 #![cfg_attr(stage0, feature(staged_api))]
87
88 #[macro_use] extern crate log;
89 #[macro_use] extern crate syntax;
90 extern crate syntax_pos;
91
92 extern crate arena;
93 extern crate fmt_macros;
94 #[macro_use] extern crate rustc;
95 extern crate rustc_platform_intrinsics as intrinsics;
96 extern crate rustc_back;
97 extern crate rustc_const_math;
98 extern crate rustc_data_structures;
99 extern crate rustc_errors as errors;
100
101 pub use rustc::dep_graph;
102 pub use rustc::hir;
103 pub use rustc::lint;
104 pub use rustc::middle;
105 pub use rustc::session;
106 pub use rustc::util;
107
108 use hir::map as hir_map;
109 use rustc::infer::InferOk;
110 use rustc::ty::subst::Substs;
111 use rustc::ty::{self, Ty, TyCtxt};
112 use rustc::ty::maps::Providers;
113 use rustc::traits::{FulfillmentContext, ObligationCause, ObligationCauseCode, Reveal};
114 use session::config;
115 use util::common::time;
116
117 use syntax::ast;
118 use syntax::abi::Abi;
119 use syntax_pos::Span;
120
121 use std::iter;
122 // NB: This module needs to be declared first so diagnostics are
123 // registered before they are used.
124 pub mod diagnostics;
125
126 mod check;
127 mod check_unused;
128 mod astconv;
129 mod collect;
130 mod constrained_type_params;
131 mod impl_wf_check;
132 mod coherence;
133 mod variance;
134
135 pub struct TypeAndSubsts<'tcx> {
136     pub substs: &'tcx Substs<'tcx>,
137     pub ty: Ty<'tcx>,
138 }
139
140 fn require_c_abi_if_variadic(tcx: TyCtxt,
141                              decl: &hir::FnDecl,
142                              abi: Abi,
143                              span: Span) {
144     if decl.variadic && abi != Abi::C {
145         let mut err = struct_span_err!(tcx.sess, span, E0045,
146                   "variadic function must have C calling convention");
147         err.span_label(span, "variadics require C calling conventions")
148             .emit();
149     }
150 }
151
152 fn require_same_types<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
153                                 cause: &ObligationCause<'tcx>,
154                                 expected: Ty<'tcx>,
155                                 actual: Ty<'tcx>)
156                                 -> bool {
157     tcx.infer_ctxt((), Reveal::UserFacing).enter(|ref infcx| {
158         let mut fulfill_cx = FulfillmentContext::new();
159         match infcx.eq_types(false, &cause, expected, actual) {
160             Ok(InferOk { obligations, .. }) => {
161                 fulfill_cx.register_predicate_obligations(infcx, obligations);
162             }
163             Err(err) => {
164                 infcx.report_mismatched_types(cause, expected, actual, err).emit();
165                 return false;
166             }
167         }
168
169         match fulfill_cx.select_all_or_error(infcx) {
170             Ok(()) => true,
171             Err(errors) => {
172                 infcx.report_fulfillment_errors(&errors);
173                 false
174             }
175         }
176     })
177 }
178
179 fn check_main_fn_ty<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
180                               main_id: ast::NodeId,
181                               main_span: Span) {
182     let main_def_id = tcx.hir.local_def_id(main_id);
183     let main_t = tcx.type_of(main_def_id);
184     match main_t.sty {
185         ty::TyFnDef(..) => {
186             match tcx.hir.find(main_id) {
187                 Some(hir_map::NodeItem(it)) => {
188                     match it.node {
189                         hir::ItemFn(.., ref generics, _) => {
190                             if generics.is_parameterized() {
191                                 struct_span_err!(tcx.sess, generics.span, E0131,
192                                          "main function is not allowed to have type parameters")
193                                     .span_label(generics.span,
194                                                 "main cannot have type parameters")
195                                     .emit();
196                                 return;
197                             }
198                         }
199                         _ => ()
200                     }
201                 }
202                 _ => ()
203             }
204             let substs = tcx.intern_substs(&[]);
205             let se_ty = tcx.mk_fn_def(main_def_id, substs,
206                 ty::Binder(tcx.mk_fn_sig(
207                     iter::empty(),
208                     tcx.mk_nil(),
209                     false,
210                     hir::Unsafety::Normal,
211                     Abi::Rust
212                 ))
213             );
214
215             require_same_types(
216                 tcx,
217                 &ObligationCause::new(main_span, main_id, ObligationCauseCode::MainFunctionType),
218                 se_ty,
219                 main_t);
220         }
221         _ => {
222             span_bug!(main_span,
223                       "main has a non-function type: found `{}`",
224                       main_t);
225         }
226     }
227 }
228
229 fn check_start_fn_ty<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
230                                start_id: ast::NodeId,
231                                start_span: Span) {
232     let start_def_id = tcx.hir.local_def_id(start_id);
233     let start_t = tcx.type_of(start_def_id);
234     match start_t.sty {
235         ty::TyFnDef(..) => {
236             match tcx.hir.find(start_id) {
237                 Some(hir_map::NodeItem(it)) => {
238                     match it.node {
239                         hir::ItemFn(..,ref ps,_)
240                         if ps.is_parameterized() => {
241                             struct_span_err!(tcx.sess, ps.span, E0132,
242                                 "start function is not allowed to have type parameters")
243                                 .span_label(ps.span,
244                                             "start function cannot have type parameters")
245                                 .emit();
246                             return;
247                         }
248                         _ => ()
249                     }
250                 }
251                 _ => ()
252             }
253
254             let substs = tcx.intern_substs(&[]);
255             let se_ty = tcx.mk_fn_def(start_def_id, substs,
256                 ty::Binder(tcx.mk_fn_sig(
257                     [
258                         tcx.types.isize,
259                         tcx.mk_imm_ptr(tcx.mk_imm_ptr(tcx.types.u8))
260                     ].iter().cloned(),
261                     tcx.types.isize,
262                     false,
263                     hir::Unsafety::Normal,
264                     Abi::Rust
265                 ))
266             );
267
268             require_same_types(
269                 tcx,
270                 &ObligationCause::new(start_span, start_id, ObligationCauseCode::StartFunctionType),
271                 se_ty,
272                 start_t);
273         }
274         _ => {
275             span_bug!(start_span,
276                       "start has a non-function type: found `{}`",
277                       start_t);
278         }
279     }
280 }
281
282 fn check_for_entry_fn<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
283     if let Some((id, sp)) = *tcx.sess.entry_fn.borrow() {
284         match tcx.sess.entry_type.get() {
285             Some(config::EntryMain) => check_main_fn_ty(tcx, id, sp),
286             Some(config::EntryStart) => check_start_fn_ty(tcx, id, sp),
287             Some(config::EntryNone) => {}
288             None => bug!("entry function without a type")
289         }
290     }
291 }
292
293 pub fn provide(providers: &mut Providers) {
294     collect::provide(providers);
295     coherence::provide(providers);
296     check::provide(providers);
297     variance::provide(providers);
298 }
299
300 pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>)
301                              -> Result<(), usize> {
302     let time_passes = tcx.sess.time_passes();
303
304     // this ensures that later parts of type checking can assume that items
305     // have valid types and not error
306     tcx.sess.track_errors(|| {
307         time(time_passes, "type collecting", ||
308              collect::collect_item_types(tcx));
309
310     })?;
311
312     tcx.sess.track_errors(|| {
313         time(time_passes, "impl wf inference", ||
314              impl_wf_check::impl_wf_check(tcx));
315     })?;
316
317     tcx.sess.track_errors(|| {
318       time(time_passes, "coherence checking", ||
319           coherence::check_coherence(tcx));
320     })?;
321
322     tcx.sess.track_errors(|| {
323         time(time_passes, "variance testing", ||
324              variance::test::test_variance(tcx));
325     })?;
326
327     time(time_passes, "wf checking", || check::check_wf_new(tcx))?;
328
329     time(time_passes, "item-types checking", || check::check_item_types(tcx))?;
330
331     time(time_passes, "item-bodies checking", || check::check_item_bodies(tcx))?;
332
333     check_unused::check_crate(tcx);
334     check_for_entry_fn(tcx);
335
336     let err_count = tcx.sess.err_count();
337     if err_count == 0 {
338         Ok(())
339     } else {
340         Err(err_count)
341     }
342 }
343
344 /// A quasi-deprecated helper used in rustdoc and save-analysis to get
345 /// the type from a HIR node.
346 pub fn hir_ty_to_ty<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, hir_ty: &hir::Ty) -> Ty<'tcx> {
347     // In case there are any projections etc, find the "environment"
348     // def-id that will be used to determine the traits/predicates in
349     // scope.  This is derived from the enclosing item-like thing.
350     let env_node_id = tcx.hir.get_parent(hir_ty.id);
351     let env_def_id = tcx.hir.local_def_id(env_node_id);
352     let item_cx = self::collect::ItemCtxt::new(tcx, env_def_id);
353     item_cx.to_ty(hir_ty)
354 }
355
356 __build_diagnostic_array! { librustc_typeck, DIAGNOSTICS }