]> git.lizzy.rs Git - rust.git/blob - src/librustc_typeck/lib.rs
Don't ICE on tuple struct ctor with incorrect arg count
[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(quote)]
80 #![feature(refcell_replace_swap)]
81 #![feature(rustc_diagnostic_macros)]
82 #![feature(slice_patterns)]
83 #![feature(slice_sort_by_cached_key)]
84 #![feature(dyn_trait)]
85 #![feature(never_type)]
86
87 #[macro_use] extern crate log;
88 #[macro_use] extern crate syntax;
89 extern crate syntax_pos;
90
91 extern crate arena;
92 #[macro_use] extern crate rustc;
93 extern crate rustc_platform_intrinsics as intrinsics;
94 extern crate rustc_const_math;
95 extern crate rustc_data_structures;
96 extern crate rustc_errors as errors;
97 extern crate rustc_target;
98
99 use rustc::hir;
100 use rustc::lint;
101 use rustc::middle;
102 use rustc::session;
103 use rustc::util;
104
105 use hir::map as hir_map;
106 use rustc::infer::InferOk;
107 use rustc::ty::subst::Substs;
108 use rustc::ty::{self, Ty, TyCtxt};
109 use rustc::ty::maps::Providers;
110 use rustc::traits::{ObligationCause, ObligationCauseCode, TraitEngine};
111 use session::{CompileIncomplete, config};
112 use util::common::time;
113
114 use syntax::ast;
115 use rustc_target::spec::abi::Abi;
116 use syntax_pos::Span;
117
118 use std::iter;
119
120 // NB: This module needs to be declared first so diagnostics are
121 // registered before they are used.
122 mod diagnostics;
123
124 mod astconv;
125 mod check;
126 mod check_unused;
127 mod coherence;
128 mod collect;
129 mod constrained_type_params;
130 mod structured_errors;
131 mod impl_wf_check;
132 mod namespace;
133 mod outlives;
134 mod variance;
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::TyFnDef(..) => {
187             match tcx.hir.find(main_id) {
188                 Some(hir_map::NodeItem(it)) => {
189                     match it.node {
190                         hir::ItemFn(.., ref generics, _) => {
191                             if !generics.params.is_empty() {
192                                 struct_span_err!(tcx.sess, generics.span, E0131,
193                                          "main function is not allowed to have type parameters")
194                                     .span_label(generics.span,
195                                                 "main cannot have type parameters")
196                                     .emit();
197                                 return;
198                             }
199                         }
200                         _ => ()
201                     }
202                 }
203                 _ => ()
204             }
205
206             let actual = tcx.fn_sig(main_def_id);
207             let expected_return_type = if tcx.lang_items().termination().is_some() {
208                 // we take the return type of the given main function, the real check is done
209                 // in `check_fn`
210                 actual.output().skip_binder()
211             } else {
212                 // standard () main return type
213                 tcx.mk_nil()
214             };
215
216             let se_ty = tcx.mk_fn_ptr(ty::Binder::bind(
217                 tcx.mk_fn_sig(
218                     iter::empty(),
219                     expected_return_type,
220                     false,
221                     hir::Unsafety::Normal,
222                     Abi::Rust
223                 )
224             ));
225
226             require_same_types(
227                 tcx,
228                 &ObligationCause::new(main_span, main_id, ObligationCauseCode::MainFunctionType),
229                 se_ty,
230                 tcx.mk_fn_ptr(actual));
231         }
232         _ => {
233             span_bug!(main_span,
234                       "main has a non-function type: found `{}`",
235                       main_t);
236         }
237     }
238 }
239
240 fn check_start_fn_ty<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
241                                start_id: ast::NodeId,
242                                start_span: Span) {
243     let start_def_id = tcx.hir.local_def_id(start_id);
244     let start_t = tcx.type_of(start_def_id);
245     match start_t.sty {
246         ty::TyFnDef(..) => {
247             match tcx.hir.find(start_id) {
248                 Some(hir_map::NodeItem(it)) => {
249                     match it.node {
250                         hir::ItemFn(..,ref ps,_)
251                         if !ps.params.is_empty() => {
252                             struct_span_err!(tcx.sess, ps.span, E0132,
253                                 "start function is not allowed to have type parameters")
254                                 .span_label(ps.span,
255                                             "start function cannot have type parameters")
256                                 .emit();
257                             return;
258                         }
259                         _ => ()
260                     }
261                 }
262                 _ => ()
263             }
264
265             let se_ty = tcx.mk_fn_ptr(ty::Binder::bind(
266                 tcx.mk_fn_sig(
267                     [
268                         tcx.types.isize,
269                         tcx.mk_imm_ptr(tcx.mk_imm_ptr(tcx.types.u8))
270                     ].iter().cloned(),
271                     tcx.types.isize,
272                     false,
273                     hir::Unsafety::Normal,
274                     Abi::Rust
275                 )
276             ));
277
278             require_same_types(
279                 tcx,
280                 &ObligationCause::new(start_span, start_id, ObligationCauseCode::StartFunctionType),
281                 se_ty,
282                 tcx.mk_fn_ptr(tcx.fn_sig(start_def_id)));
283         }
284         _ => {
285             span_bug!(start_span,
286                       "start has a non-function type: found `{}`",
287                       start_t);
288         }
289     }
290 }
291
292 fn check_for_entry_fn<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
293     if let Some((id, sp, entry_type)) = *tcx.sess.entry_fn.borrow() {
294         match entry_type {
295             config::EntryMain => check_main_fn_ty(tcx, id, sp),
296             config::EntryStart => check_start_fn_ty(tcx, id, sp),
297         }
298     }
299 }
300
301 pub fn provide(providers: &mut Providers) {
302     collect::provide(providers);
303     coherence::provide(providers);
304     check::provide(providers);
305     variance::provide(providers);
306     outlives::provide(providers);
307 }
308
309 pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>)
310                              -> Result<(), CompileIncomplete>
311 {
312     // this ensures that later parts of type checking can assume that items
313     // have valid types and not error
314     tcx.sess.track_errors(|| {
315         time(tcx.sess, "type collecting", ||
316              collect::collect_item_types(tcx));
317
318     })?;
319
320     tcx.sess.track_errors(|| {
321         time(tcx.sess, "outlives testing", ||
322             outlives::test::test_inferred_outlives(tcx));
323     })?;
324
325     tcx.sess.track_errors(|| {
326         time(tcx.sess, "impl wf inference", ||
327              impl_wf_check::impl_wf_check(tcx));
328     })?;
329
330     tcx.sess.track_errors(|| {
331       time(tcx.sess, "coherence checking", ||
332           coherence::check_coherence(tcx));
333     })?;
334
335     tcx.sess.track_errors(|| {
336         time(tcx.sess, "variance testing", ||
337              variance::test::test_variance(tcx));
338     })?;
339
340     time(tcx.sess, "wf checking", || check::check_wf_new(tcx))?;
341
342     time(tcx.sess, "item-types checking", || check::check_item_types(tcx))?;
343
344     time(tcx.sess, "item-bodies checking", || check::check_item_bodies(tcx))?;
345
346     check_unused::check_crate(tcx);
347     check_for_entry_fn(tcx);
348
349     tcx.sess.compile_status()
350 }
351
352 /// A quasi-deprecated helper used in rustdoc and save-analysis to get
353 /// the type from a HIR node.
354 pub fn hir_ty_to_ty<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, hir_ty: &hir::Ty) -> Ty<'tcx> {
355     // In case there are any projections etc, find the "environment"
356     // def-id that will be used to determine the traits/predicates in
357     // scope.  This is derived from the enclosing item-like thing.
358     let env_node_id = tcx.hir.get_parent(hir_ty.id);
359     let env_def_id = tcx.hir.local_def_id(env_node_id);
360     let item_cx = self::collect::ItemCtxt::new(tcx, env_def_id);
361     astconv::AstConv::ast_ty_to_ty(&item_cx, hir_ty)
362 }
363
364 pub fn hir_trait_to_predicates<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, hir_trait: &hir::TraitRef)
365         -> (ty::PolyTraitRef<'tcx>, Vec<ty::PolyProjectionPredicate<'tcx>>) {
366     // In case there are any projections etc, find the "environment"
367     // def-id that will be used to determine the traits/predicates in
368     // scope.  This is derived from the enclosing item-like thing.
369     let env_node_id = tcx.hir.get_parent(hir_trait.ref_id);
370     let env_def_id = tcx.hir.local_def_id(env_node_id);
371     let item_cx = self::collect::ItemCtxt::new(tcx, env_def_id);
372     let mut projections = Vec::new();
373     let principal = astconv::AstConv::instantiate_poly_trait_ref_inner(
374         &item_cx, hir_trait, tcx.types.err, &mut projections, true
375     );
376     (principal, projections)
377 }
378
379 __build_diagnostic_array! { librustc_typeck, DIAGNOSTICS }