]> git.lizzy.rs Git - rust.git/blob - src/librustc_typeck/lib.rs
Auto merge of #65188 - matthewjasper:stabilize-const-constructor, r=Centril
[rust.git] / src / librustc_typeck / lib.rs
1 /*!
2
3 # typeck
4
5 The type checker is responsible for:
6
7 1. Determining the type of each expression.
8 2. Resolving methods and traits.
9 3. Guaranteeing that most type rules are met. ("Most?", you say, "why most?"
10    Well, dear reader, read on)
11
12 The main entry point is `check_crate()`. Type checking operates in
13 several major phases:
14
15 1. The collect phase first passes over all items and determines their
16    type, without examining their "innards".
17
18 2. Variance inference then runs to compute the variance of each parameter.
19
20 3. Coherence checks for overlapping or orphaned impls.
21
22 4. Finally, the check phase then checks function bodies and so forth.
23    Within the check phase, we check each function body one at a time
24    (bodies of function expressions are checked as part of the
25    containing function).  Inference is used to supply types wherever
26    they are unknown. The actual checking of a function itself has
27    several phases (check, regionck, writeback), as discussed in the
28    documentation for the `check` module.
29
30 The type checker is defined into various submodules which are documented
31 independently:
32
33 - astconv: converts the AST representation of types
34   into the `ty` representation.
35
36 - collect: computes the types of each top-level item and enters them into
37   the `tcx.types` table for later use.
38
39 - coherence: enforces coherence rules, builds some tables.
40
41 - variance: variance inference
42
43 - outlives: outlives inference
44
45 - check: walks over function bodies and type checks them, inferring types for
46   local variables, type parameters, etc as necessary.
47
48 - infer: finds the types to use for each type variable such that
49   all subtyping and assignment constraints are met.  In essence, the check
50   module specifies the constraints, and the infer module solves them.
51
52 ## Note
53
54 This API is completely unstable and subject to change.
55
56 */
57
58 #![doc(html_root_url = "https://doc.rust-lang.org/nightly/")]
59
60 #![allow(non_camel_case_types)]
61
62 #![feature(box_patterns)]
63 #![feature(box_syntax)]
64 #![feature(crate_visibility_modifier)]
65 #![feature(exhaustive_patterns)]
66 #![feature(in_band_lifetimes)]
67 #![feature(nll)]
68 #![feature(slice_patterns)]
69 #![feature(never_type)]
70
71 #![recursion_limit="256"]
72
73 #[macro_use] extern crate log;
74 #[macro_use] extern crate syntax;
75
76 #[macro_use] extern crate rustc;
77
78 pub mod error_codes;
79
80 mod astconv;
81 mod check;
82 mod check_unused;
83 mod coherence;
84 mod collect;
85 mod constrained_generic_params;
86 mod structured_errors;
87 mod impl_wf_check;
88 mod namespace;
89 mod outlives;
90 mod variance;
91
92 use rustc_target::spec::abi::Abi;
93 use rustc::hir::{self, Node};
94 use rustc::hir::def_id::{DefId, LOCAL_CRATE};
95 use rustc::infer::InferOk;
96 use rustc::lint;
97 use rustc::middle;
98 use rustc::session;
99 use rustc::util::common::ErrorReported;
100 use rustc::session::config::EntryFnType;
101 use rustc::traits::{ObligationCause, ObligationCauseCode, TraitEngine, TraitEngineExt};
102 use rustc::ty::subst::SubstsRef;
103 use rustc::ty::{self, Ty, TyCtxt};
104 use rustc::ty::query::Providers;
105 use rustc::util;
106 use syntax_pos::{DUMMY_SP, Span};
107 use util::common::time;
108
109 use std::iter;
110
111 use astconv::{AstConv, Bounds};
112 pub use collect::checked_type_of;
113
114 pub struct TypeAndSubsts<'tcx> {
115     substs: SubstsRef<'tcx>,
116     ty: Ty<'tcx>,
117 }
118
119 fn require_c_abi_if_c_variadic(tcx: TyCtxt<'_>, decl: &hir::FnDecl, abi: Abi, span: Span) {
120     if decl.c_variadic && !(abi == Abi::C || abi == Abi::Cdecl) {
121         let mut err = struct_span_err!(tcx.sess, span, E0045,
122             "C-variadic function must have C or cdecl calling convention");
123         err.span_label(span, "C-variadics require C or cdecl calling convention").emit();
124     }
125 }
126
127 fn require_same_types<'tcx>(
128     tcx: TyCtxt<'tcx>,
129     cause: &ObligationCause<'tcx>,
130     expected: Ty<'tcx>,
131     actual: Ty<'tcx>,
132 ) -> bool {
133     tcx.infer_ctxt().enter(|ref infcx| {
134         let param_env = ty::ParamEnv::empty();
135         let mut fulfill_cx = TraitEngine::new(infcx.tcx);
136         match infcx.at(&cause, param_env).eq(expected, actual) {
137             Ok(InferOk { obligations, .. }) => {
138                 fulfill_cx.register_predicate_obligations(infcx, obligations);
139             }
140             Err(err) => {
141                 infcx.report_mismatched_types(cause, expected, actual, err).emit();
142                 return false;
143             }
144         }
145
146         match fulfill_cx.select_all_or_error(infcx) {
147             Ok(()) => true,
148             Err(errors) => {
149                 infcx.report_fulfillment_errors(&errors, None, false);
150                 false
151             }
152         }
153     })
154 }
155
156 fn check_main_fn_ty(tcx: TyCtxt<'_>, main_def_id: DefId) {
157     let main_id = tcx.hir().as_local_hir_id(main_def_id).unwrap();
158     let main_span = tcx.def_span(main_def_id);
159     let main_t = tcx.type_of(main_def_id);
160     match main_t.kind {
161         ty::FnDef(..) => {
162             if let Some(Node::Item(it)) = tcx.hir().find(main_id) {
163                 if let hir::ItemKind::Fn(.., ref generics, _) = it.kind {
164                     let mut error = false;
165                     if !generics.params.is_empty() {
166                         let msg = "`main` function is not allowed to have generic \
167                                    parameters".to_owned();
168                         let label = "`main` cannot have generic parameters".to_string();
169                         struct_span_err!(tcx.sess, generics.span, E0131, "{}", msg)
170                             .span_label(generics.span, label)
171                             .emit();
172                         error = true;
173                     }
174                     if let Some(sp) = generics.where_clause.span() {
175                         struct_span_err!(tcx.sess, sp, E0646,
176                             "`main` function is not allowed to have a `where` clause")
177                             .span_label(sp, "`main` cannot have a `where` clause")
178                             .emit();
179                         error = true;
180                     }
181                     if error {
182                         return;
183                     }
184                 }
185             }
186
187             let actual = tcx.fn_sig(main_def_id);
188             let expected_return_type = if tcx.lang_items().termination().is_some() {
189                 // we take the return type of the given main function, the real check is done
190                 // in `check_fn`
191                 actual.output().skip_binder()
192             } else {
193                 // standard () main return type
194                 tcx.mk_unit()
195             };
196
197             let se_ty = tcx.mk_fn_ptr(ty::Binder::bind(
198                 tcx.mk_fn_sig(
199                     iter::empty(),
200                     expected_return_type,
201                     false,
202                     hir::Unsafety::Normal,
203                     Abi::Rust
204                 )
205             ));
206
207             require_same_types(
208                 tcx,
209                 &ObligationCause::new(main_span, main_id, ObligationCauseCode::MainFunctionType),
210                 se_ty,
211                 tcx.mk_fn_ptr(actual));
212         }
213         _ => {
214             span_bug!(main_span,
215                       "main has a non-function type: found `{}`",
216                       main_t);
217         }
218     }
219 }
220
221 fn check_start_fn_ty(tcx: TyCtxt<'_>, start_def_id: DefId) {
222     let start_id = tcx.hir().as_local_hir_id(start_def_id).unwrap();
223     let start_span = tcx.def_span(start_def_id);
224     let start_t = tcx.type_of(start_def_id);
225     match start_t.kind {
226         ty::FnDef(..) => {
227             if let Some(Node::Item(it)) = tcx.hir().find(start_id) {
228                 if let hir::ItemKind::Fn(.., ref generics, _) = it.kind {
229                     let mut error = false;
230                     if !generics.params.is_empty() {
231                         struct_span_err!(tcx.sess, generics.span, E0132,
232                             "start function is not allowed to have type parameters")
233                             .span_label(generics.span,
234                                         "start function cannot have type parameters")
235                             .emit();
236                         error = true;
237                     }
238                     if let Some(sp) = generics.where_clause.span() {
239                         struct_span_err!(tcx.sess, sp, E0647,
240                             "start function is not allowed to have a `where` clause")
241                             .span_label(sp, "start function cannot have a `where` clause")
242                             .emit();
243                         error = true;
244                     }
245                     if error {
246                         return;
247                     }
248                 }
249             }
250
251             let se_ty = tcx.mk_fn_ptr(ty::Binder::bind(
252                 tcx.mk_fn_sig(
253                     [
254                         tcx.types.isize,
255                         tcx.mk_imm_ptr(tcx.mk_imm_ptr(tcx.types.u8))
256                     ].iter().cloned(),
257                     tcx.types.isize,
258                     false,
259                     hir::Unsafety::Normal,
260                     Abi::Rust
261                 )
262             ));
263
264             require_same_types(
265                 tcx,
266                 &ObligationCause::new(start_span, start_id, ObligationCauseCode::StartFunctionType),
267                 se_ty,
268                 tcx.mk_fn_ptr(tcx.fn_sig(start_def_id)));
269         }
270         _ => {
271             span_bug!(start_span,
272                       "start has a non-function type: found `{}`",
273                       start_t);
274         }
275     }
276 }
277
278 fn check_for_entry_fn(tcx: TyCtxt<'_>) {
279     match tcx.entry_fn(LOCAL_CRATE) {
280         Some((def_id, EntryFnType::Main)) => check_main_fn_ty(tcx, def_id),
281         Some((def_id, EntryFnType::Start)) => check_start_fn_ty(tcx, def_id),
282         _ => {}
283     }
284 }
285
286 pub fn provide(providers: &mut Providers<'_>) {
287     collect::provide(providers);
288     coherence::provide(providers);
289     check::provide(providers);
290     variance::provide(providers);
291     outlives::provide(providers);
292     impl_wf_check::provide(providers);
293 }
294
295 pub fn check_crate(tcx: TyCtxt<'_>) -> Result<(), ErrorReported> {
296     let _prof_timer = tcx.prof.generic_activity("type_check_crate");
297
298     // this ensures that later parts of type checking can assume that items
299     // have valid types and not error
300     // FIXME(matthewjasper) We shouldn't need to do this.
301     tcx.sess.track_errors(|| {
302         time(tcx.sess, "type collecting", || {
303             for &module in tcx.hir().krate().modules.keys() {
304                 tcx.ensure().collect_mod_item_types(tcx.hir().local_def_id(module));
305             }
306         });
307     })?;
308
309     if tcx.features().rustc_attrs {
310         tcx.sess.track_errors(|| {
311             time(tcx.sess, "outlives testing", ||
312                 outlives::test::test_inferred_outlives(tcx));
313         })?;
314     }
315
316     tcx.sess.track_errors(|| {
317         time(tcx.sess, "impl wf inference", ||
318              impl_wf_check::impl_wf_check(tcx));
319     })?;
320
321     tcx.sess.track_errors(|| {
322       time(tcx.sess, "coherence checking", ||
323           coherence::check_coherence(tcx));
324     })?;
325
326     if tcx.features().rustc_attrs {
327         tcx.sess.track_errors(|| {
328             time(tcx.sess, "variance testing", ||
329                 variance::test::test_variance(tcx));
330         })?;
331     }
332
333     tcx.sess.track_errors(|| {
334         time(tcx.sess, "wf checking", || check::check_wf_new(tcx));
335     })?;
336
337     time(tcx.sess, "item-types checking", || {
338         for &module in tcx.hir().krate().modules.keys() {
339             tcx.ensure().check_mod_item_types(tcx.hir().local_def_id(module));
340         }
341     });
342
343     time(tcx.sess, "item-bodies checking", || tcx.typeck_item_bodies(LOCAL_CRATE));
344
345     check_unused::check_crate(tcx);
346     check_for_entry_fn(tcx);
347
348     if tcx.sess.err_count() == 0 {
349         Ok(())
350     } else {
351         Err(ErrorReported)
352     }
353 }
354
355 /// A quasi-deprecated helper used in rustdoc and clippy to get
356 /// the type from a HIR node.
357 pub fn hir_ty_to_ty<'tcx>(tcx: TyCtxt<'tcx>, hir_ty: &hir::Ty) -> Ty<'tcx> {
358     // In case there are any projections, etc., find the "environment"
359     // def-ID that will be used to determine the traits/predicates in
360     // scope.  This is derived from the enclosing item-like thing.
361     let env_node_id = tcx.hir().get_parent_item(hir_ty.hir_id);
362     let env_def_id = tcx.hir().local_def_id(env_node_id);
363     let item_cx = self::collect::ItemCtxt::new(tcx, env_def_id);
364
365     astconv::AstConv::ast_ty_to_ty(&item_cx, hir_ty)
366 }
367
368 pub fn hir_trait_to_predicates<'tcx>(
369     tcx: TyCtxt<'tcx>,
370     hir_trait: &hir::TraitRef,
371 ) -> Bounds<'tcx> {
372     // In case there are any projections, etc., find the "environment"
373     // def-ID that will be used to determine the traits/predicates in
374     // scope.  This is derived from the enclosing item-like thing.
375     let env_hir_id = tcx.hir().get_parent_item(hir_trait.hir_ref_id);
376     let env_def_id = tcx.hir().local_def_id(env_hir_id);
377     let item_cx = self::collect::ItemCtxt::new(tcx, env_def_id);
378     let mut bounds = Bounds::default();
379     let _ = AstConv::instantiate_poly_trait_ref_inner(
380         &item_cx, hir_trait, DUMMY_SP, tcx.types.err, &mut bounds, true
381     );
382
383     bounds
384 }