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