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