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