]> git.lizzy.rs Git - rust.git/blob - src/librustc_typeck/lib.rs
Unify API of `Scalar` and `ScalarMaybeUndef`
[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 - outlives: outlives inference
54
55 - check: walks over function bodies and type checks them, inferring types for
56   local variables, type parameters, etc as necessary.
57
58 - infer: finds the types to use for each type variable such that
59   all subtyping and assignment constraints are met.  In essence, the check
60   module specifies the constraints, and the infer module solves them.
61
62 # Note
63
64 This API is completely unstable and subject to change.
65
66 */
67
68 #![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
69       html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
70       html_root_url = "https://doc.rust-lang.org/nightly/")]
71
72 #![allow(non_camel_case_types)]
73
74 #![feature(box_patterns)]
75 #![feature(box_syntax)]
76 #![feature(crate_visibility_modifier)]
77 #![feature(from_ref)]
78 #![feature(exhaustive_patterns)]
79 #![feature(iterator_find_map)]
80 #![feature(quote)]
81 #![feature(refcell_replace_swap)]
82 #![feature(rustc_diagnostic_macros)]
83 #![feature(slice_patterns)]
84 #![feature(slice_sort_by_cached_key)]
85 #![feature(never_type)]
86
87 #![recursion_limit="256"]
88
89 #[macro_use] extern crate log;
90 #[macro_use] extern crate syntax;
91 extern crate syntax_pos;
92
93 extern crate arena;
94 #[macro_use] extern crate rustc;
95 extern crate rustc_platform_intrinsics as intrinsics;
96 extern crate rustc_data_structures;
97 extern crate rustc_errors as errors;
98 extern crate rustc_target;
99
100 use rustc::hir;
101 use rustc::lint;
102 use rustc::middle;
103 use rustc::session;
104 use rustc::util;
105
106 use hir::map as hir_map;
107 use rustc::infer::InferOk;
108 use rustc::ty::subst::Substs;
109 use rustc::ty::{self, Ty, TyCtxt};
110 use rustc::ty::query::Providers;
111 use rustc::traits::{ObligationCause, ObligationCauseCode, TraitEngine, TraitEngineExt};
112 use session::{CompileIncomplete, config};
113 use util::common::time;
114
115 use syntax::ast;
116 use rustc_target::spec::abi::Abi;
117 use syntax_pos::Span;
118
119 use std::iter;
120
121 // NB: This module needs to be declared first so diagnostics are
122 // registered before they are used.
123 mod diagnostics;
124
125 mod astconv;
126 mod check;
127 mod check_unused;
128 mod coherence;
129 mod collect;
130 mod constrained_type_params;
131 mod structured_errors;
132 mod impl_wf_check;
133 mod namespace;
134 mod outlives;
135 mod variance;
136
137 pub struct TypeAndSubsts<'tcx> {
138     substs: &'tcx Substs<'tcx>,
139     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();
160         let mut fulfill_cx = TraitEngine::new(infcx.tcx);
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, None, false);
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::ItemKind::Fn(.., ref generics, _) => {
192                             let mut error = false;
193                             if !generics.params.is_empty() {
194                                 let msg = "`main` function is not allowed to have generic \
195                                            parameters".to_string();
196                                 let label = "`main` cannot have generic parameters".to_string();
197                                 struct_span_err!(tcx.sess, generics.span, E0131, "{}", msg)
198                                     .span_label(generics.span, label)
199                                     .emit();
200                                 error = true;
201                             }
202                             if let Some(sp) = generics.where_clause.span() {
203                                 struct_span_err!(tcx.sess, sp, E0646,
204                                     "`main` function is not allowed to have a `where` clause")
205                                     .span_label(sp, "`main` cannot have a `where` clause")
206                                     .emit();
207                                 error = true;
208                             }
209                             if error {
210                                 return;
211                             }
212                         }
213                         _ => ()
214                     }
215                 }
216                 _ => ()
217             }
218
219             let actual = tcx.fn_sig(main_def_id);
220             let expected_return_type = if tcx.lang_items().termination().is_some() {
221                 // we take the return type of the given main function, the real check is done
222                 // in `check_fn`
223                 actual.output().skip_binder()
224             } else {
225                 // standard () main return type
226                 tcx.mk_nil()
227             };
228
229             let se_ty = tcx.mk_fn_ptr(ty::Binder::bind(
230                 tcx.mk_fn_sig(
231                     iter::empty(),
232                     expected_return_type,
233                     false,
234                     hir::Unsafety::Normal,
235                     Abi::Rust
236                 )
237             ));
238
239             require_same_types(
240                 tcx,
241                 &ObligationCause::new(main_span, main_id, ObligationCauseCode::MainFunctionType),
242                 se_ty,
243                 tcx.mk_fn_ptr(actual));
244         }
245         _ => {
246             span_bug!(main_span,
247                       "main has a non-function type: found `{}`",
248                       main_t);
249         }
250     }
251 }
252
253 fn check_start_fn_ty<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
254                                start_id: ast::NodeId,
255                                start_span: Span) {
256     let start_def_id = tcx.hir.local_def_id(start_id);
257     let start_t = tcx.type_of(start_def_id);
258     match start_t.sty {
259         ty::TyFnDef(..) => {
260             match tcx.hir.find(start_id) {
261                 Some(hir_map::NodeItem(it)) => {
262                     match it.node {
263                         hir::ItemKind::Fn(.., ref generics, _) => {
264                             let mut error = false;
265                             if !generics.params.is_empty() {
266                                 struct_span_err!(tcx.sess, generics.span, E0132,
267                                     "start function is not allowed to have type parameters")
268                                     .span_label(generics.span,
269                                                 "start function cannot have type parameters")
270                                     .emit();
271                                 error = true;
272                             }
273                             if let Some(sp) = generics.where_clause.span() {
274                                 struct_span_err!(tcx.sess, sp, E0647,
275                                     "start function is not allowed to have a `where` clause")
276                                     .span_label(sp, "start function cannot have a `where` clause")
277                                     .emit();
278                                 error = true;
279                             }
280                             if error {
281                                 return;
282                             }
283                         }
284                         _ => ()
285                     }
286                 }
287                 _ => ()
288             }
289
290             let se_ty = tcx.mk_fn_ptr(ty::Binder::bind(
291                 tcx.mk_fn_sig(
292                     [
293                         tcx.types.isize,
294                         tcx.mk_imm_ptr(tcx.mk_imm_ptr(tcx.types.u8))
295                     ].iter().cloned(),
296                     tcx.types.isize,
297                     false,
298                     hir::Unsafety::Normal,
299                     Abi::Rust
300                 )
301             ));
302
303             require_same_types(
304                 tcx,
305                 &ObligationCause::new(start_span, start_id, ObligationCauseCode::StartFunctionType),
306                 se_ty,
307                 tcx.mk_fn_ptr(tcx.fn_sig(start_def_id)));
308         }
309         _ => {
310             span_bug!(start_span,
311                       "start has a non-function type: found `{}`",
312                       start_t);
313         }
314     }
315 }
316
317 fn check_for_entry_fn<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
318     if let Some((id, sp, entry_type)) = *tcx.sess.entry_fn.borrow() {
319         match entry_type {
320             config::EntryMain => check_main_fn_ty(tcx, id, sp),
321             config::EntryStart => check_start_fn_ty(tcx, id, sp),
322         }
323     }
324 }
325
326 pub fn provide(providers: &mut Providers) {
327     collect::provide(providers);
328     coherence::provide(providers);
329     check::provide(providers);
330     variance::provide(providers);
331     outlives::provide(providers);
332 }
333
334 pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>)
335                              -> Result<(), CompileIncomplete>
336 {
337     // this ensures that later parts of type checking can assume that items
338     // have valid types and not error
339     tcx.sess.track_errors(|| {
340         time(tcx.sess, "type collecting", ||
341              collect::collect_item_types(tcx));
342
343     })?;
344
345     tcx.sess.track_errors(|| {
346         time(tcx.sess, "outlives testing", ||
347             outlives::test::test_inferred_outlives(tcx));
348     })?;
349
350     tcx.sess.track_errors(|| {
351         time(tcx.sess, "impl wf inference", ||
352              impl_wf_check::impl_wf_check(tcx));
353     })?;
354
355     tcx.sess.track_errors(|| {
356       time(tcx.sess, "coherence checking", ||
357           coherence::check_coherence(tcx));
358     })?;
359
360     tcx.sess.track_errors(|| {
361         time(tcx.sess, "variance testing", ||
362              variance::test::test_variance(tcx));
363     })?;
364
365     time(tcx.sess, "wf checking", || check::check_wf_new(tcx))?;
366
367     time(tcx.sess, "item-types checking", || check::check_item_types(tcx))?;
368
369     time(tcx.sess, "item-bodies checking", || check::check_item_bodies(tcx))?;
370
371     check_unused::check_crate(tcx);
372     check_for_entry_fn(tcx);
373
374     tcx.sess.compile_status()
375 }
376
377 /// A quasi-deprecated helper used in rustdoc and save-analysis to get
378 /// the type from a HIR node.
379 pub fn hir_ty_to_ty<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, hir_ty: &hir::Ty) -> Ty<'tcx> {
380     // In case there are any projections etc, find the "environment"
381     // def-id that will be used to determine the traits/predicates in
382     // scope.  This is derived from the enclosing item-like thing.
383     let env_node_id = tcx.hir.get_parent(hir_ty.id);
384     let env_def_id = tcx.hir.local_def_id(env_node_id);
385     let item_cx = self::collect::ItemCtxt::new(tcx, env_def_id);
386     astconv::AstConv::ast_ty_to_ty(&item_cx, hir_ty)
387 }
388
389 pub fn hir_trait_to_predicates<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, hir_trait: &hir::TraitRef)
390         -> (ty::PolyTraitRef<'tcx>, Vec<ty::PolyProjectionPredicate<'tcx>>) {
391     // In case there are any projections etc, find the "environment"
392     // def-id that will be used to determine the traits/predicates in
393     // scope.  This is derived from the enclosing item-like thing.
394     let env_node_id = tcx.hir.get_parent(hir_trait.ref_id);
395     let env_def_id = tcx.hir.local_def_id(env_node_id);
396     let item_cx = self::collect::ItemCtxt::new(tcx, env_def_id);
397     let mut projections = Vec::new();
398     let principal = astconv::AstConv::instantiate_poly_trait_ref_inner(
399         &item_cx, hir_trait, tcx.types.err, &mut projections, true
400     );
401     (principal, projections)
402 }
403
404 __build_diagnostic_array! { librustc_typeck, DIAGNOSTICS }