]> git.lizzy.rs Git - rust.git/blob - src/librustc_typeck/lib.rs
Rollup merge of #42408 - bjorn3:patch-2, 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 #![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().enter(|ref infcx| {
159         let param_env = ty::ParamEnv::empty(Reveal::UserFacing);
160         let mut fulfill_cx = FulfillmentContext::new();
161         match infcx.at(&cause, param_env).eq(expected, actual) {
162             Ok(InferOk { obligations, .. }) => {
163                 fulfill_cx.register_predicate_obligations(infcx, obligations);
164             }
165             Err(err) => {
166                 infcx.report_mismatched_types(cause, expected, actual, err).emit();
167                 return false;
168             }
169         }
170
171         match fulfill_cx.select_all_or_error(infcx) {
172             Ok(()) => true,
173             Err(errors) => {
174                 infcx.report_fulfillment_errors(&errors);
175                 false
176             }
177         }
178     })
179 }
180
181 fn check_main_fn_ty<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
182                               main_id: ast::NodeId,
183                               main_span: Span) {
184     let main_def_id = tcx.hir.local_def_id(main_id);
185     let main_t = tcx.type_of(main_def_id);
186     match main_t.sty {
187         ty::TyFnDef(..) => {
188             match tcx.hir.find(main_id) {
189                 Some(hir_map::NodeItem(it)) => {
190                     match it.node {
191                         hir::ItemFn(.., ref generics, _) => {
192                             if generics.is_parameterized() {
193                                 struct_span_err!(tcx.sess, generics.span, E0131,
194                                          "main function is not allowed to have type parameters")
195                                     .span_label(generics.span,
196                                                 "main cannot have type parameters")
197                                     .emit();
198                                 return;
199                             }
200                         }
201                         _ => ()
202                     }
203                 }
204                 _ => ()
205             }
206             let substs = tcx.intern_substs(&[]);
207             let se_ty = tcx.mk_fn_def(main_def_id, substs,
208                 ty::Binder(tcx.mk_fn_sig(
209                     iter::empty(),
210                     tcx.mk_nil(),
211                     false,
212                     hir::Unsafety::Normal,
213                     Abi::Rust
214                 ))
215             );
216
217             require_same_types(
218                 tcx,
219                 &ObligationCause::new(main_span, main_id, ObligationCauseCode::MainFunctionType),
220                 se_ty,
221                 main_t);
222         }
223         _ => {
224             span_bug!(main_span,
225                       "main has a non-function type: found `{}`",
226                       main_t);
227         }
228     }
229 }
230
231 fn check_start_fn_ty<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
232                                start_id: ast::NodeId,
233                                start_span: Span) {
234     let start_def_id = tcx.hir.local_def_id(start_id);
235     let start_t = tcx.type_of(start_def_id);
236     match start_t.sty {
237         ty::TyFnDef(..) => {
238             match tcx.hir.find(start_id) {
239                 Some(hir_map::NodeItem(it)) => {
240                     match it.node {
241                         hir::ItemFn(..,ref ps,_)
242                         if ps.is_parameterized() => {
243                             struct_span_err!(tcx.sess, ps.span, E0132,
244                                 "start function is not allowed to have type parameters")
245                                 .span_label(ps.span,
246                                             "start function cannot have type parameters")
247                                 .emit();
248                             return;
249                         }
250                         _ => ()
251                     }
252                 }
253                 _ => ()
254             }
255
256             let substs = tcx.intern_substs(&[]);
257             let se_ty = tcx.mk_fn_def(start_def_id, substs,
258                 ty::Binder(tcx.mk_fn_sig(
259                     [
260                         tcx.types.isize,
261                         tcx.mk_imm_ptr(tcx.mk_imm_ptr(tcx.types.u8))
262                     ].iter().cloned(),
263                     tcx.types.isize,
264                     false,
265                     hir::Unsafety::Normal,
266                     Abi::Rust
267                 ))
268             );
269
270             require_same_types(
271                 tcx,
272                 &ObligationCause::new(start_span, start_id, ObligationCauseCode::StartFunctionType),
273                 se_ty,
274                 start_t);
275         }
276         _ => {
277             span_bug!(start_span,
278                       "start has a non-function type: found `{}`",
279                       start_t);
280         }
281     }
282 }
283
284 fn check_for_entry_fn<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
285     if let Some((id, sp)) = *tcx.sess.entry_fn.borrow() {
286         match tcx.sess.entry_type.get() {
287             Some(config::EntryMain) => check_main_fn_ty(tcx, id, sp),
288             Some(config::EntryStart) => check_start_fn_ty(tcx, id, sp),
289             Some(config::EntryNone) => {}
290             None => bug!("entry function without a type")
291         }
292     }
293 }
294
295 pub fn provide(providers: &mut Providers) {
296     collect::provide(providers);
297     coherence::provide(providers);
298     check::provide(providers);
299     variance::provide(providers);
300 }
301
302 pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>)
303                              -> Result<(), usize> {
304     let time_passes = tcx.sess.time_passes();
305
306     // this ensures that later parts of type checking can assume that items
307     // have valid types and not error
308     tcx.sess.track_errors(|| {
309         time(time_passes, "type collecting", ||
310              collect::collect_item_types(tcx));
311
312     })?;
313
314     tcx.sess.track_errors(|| {
315         time(time_passes, "impl wf inference", ||
316              impl_wf_check::impl_wf_check(tcx));
317     })?;
318
319     tcx.sess.track_errors(|| {
320       time(time_passes, "coherence checking", ||
321           coherence::check_coherence(tcx));
322     })?;
323
324     tcx.sess.track_errors(|| {
325         time(time_passes, "variance testing", ||
326              variance::test::test_variance(tcx));
327     })?;
328
329     time(time_passes, "wf checking", || check::check_wf_new(tcx))?;
330
331     time(time_passes, "item-types checking", || check::check_item_types(tcx))?;
332
333     time(time_passes, "item-bodies checking", || check::check_item_bodies(tcx))?;
334
335     check_unused::check_crate(tcx);
336     check_for_entry_fn(tcx);
337
338     let err_count = tcx.sess.err_count();
339     if err_count == 0 {
340         Ok(())
341     } else {
342         Err(err_count)
343     }
344 }
345
346 /// A quasi-deprecated helper used in rustdoc and save-analysis to get
347 /// the type from a HIR node.
348 pub fn hir_ty_to_ty<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, hir_ty: &hir::Ty) -> Ty<'tcx> {
349     // In case there are any projections etc, find the "environment"
350     // def-id that will be used to determine the traits/predicates in
351     // scope.  This is derived from the enclosing item-like thing.
352     let env_node_id = tcx.hir.get_parent(hir_ty.id);
353     let env_def_id = tcx.hir.local_def_id(env_node_id);
354     let item_cx = self::collect::ItemCtxt::new(tcx, env_def_id);
355     item_cx.to_ty(hir_ty)
356 }
357
358 __build_diagnostic_array! { librustc_typeck, DIAGNOSTICS }