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