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