]> git.lizzy.rs Git - rust.git/blob - src/librustc_typeck/lib.rs
Rollup merge of #67313 - oli-obk:document_all_the_t̶h̶i̶n̶g̶s̶dataflow, r=ecstatic...
[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 #![allow(non_camel_case_types)]
60 #![feature(bool_to_option)]
61 #![feature(box_patterns)]
62 #![feature(box_syntax)]
63 #![feature(crate_visibility_modifier)]
64 #![feature(exhaustive_patterns)]
65 #![feature(in_band_lifetimes)]
66 #![feature(nll)]
67 #![feature(slice_patterns)]
68 #![feature(try_blocks)]
69 #![feature(never_type)]
70 #![recursion_limit = "256"]
71
72 #[macro_use]
73 extern crate log;
74
75 #[macro_use]
76 extern crate rustc;
77
78 // This is used by Clippy.
79 pub mod expr_use_visitor;
80
81 mod astconv;
82 mod check;
83 mod check_unused;
84 mod coherence;
85 mod collect;
86 mod constrained_generic_params;
87 mod impl_wf_check;
88 mod mem_categorization;
89 mod namespace;
90 mod outlives;
91 mod structured_errors;
92 mod variance;
93
94 use rustc::infer::InferOk;
95 use rustc::lint;
96 use rustc::middle;
97 use rustc::session;
98 use rustc::session::config::EntryFnType;
99 use rustc::traits::{ObligationCause, ObligationCauseCode, TraitEngine, TraitEngineExt};
100 use rustc::ty::query::Providers;
101 use rustc::ty::subst::SubstsRef;
102 use rustc::ty::{self, Ty, TyCtxt};
103 use rustc::util;
104 use rustc::util::common::ErrorReported;
105 use rustc_errors::struct_span_err;
106 use rustc_hir as hir;
107 use rustc_hir::def_id::{DefId, LOCAL_CRATE};
108 use rustc_hir::Node;
109 use rustc_span::{Span, DUMMY_SP};
110 use rustc_target::spec::abi::Abi;
111
112 use rustc_error_codes::*;
113
114 use std::iter;
115
116 use astconv::{AstConv, Bounds};
117 pub struct TypeAndSubsts<'tcx> {
118     substs: SubstsRef<'tcx>,
119     ty: Ty<'tcx>,
120 }
121
122 fn require_c_abi_if_c_variadic(tcx: TyCtxt<'_>, decl: &hir::FnDecl<'_>, abi: Abi, span: Span) {
123     if decl.c_variadic && !(abi == Abi::C || abi == Abi::Cdecl) {
124         let mut err = struct_span_err!(
125             tcx.sess,
126             span,
127             E0045,
128             "C-variadic function must have C or cdecl calling convention"
129         );
130         err.span_label(span, "C-variadics require C or cdecl calling convention").emit();
131     }
132 }
133
134 fn require_same_types<'tcx>(
135     tcx: TyCtxt<'tcx>,
136     cause: &ObligationCause<'tcx>,
137     expected: Ty<'tcx>,
138     actual: Ty<'tcx>,
139 ) -> bool {
140     tcx.infer_ctxt().enter(|ref infcx| {
141         let param_env = ty::ParamEnv::empty();
142         let mut fulfill_cx = TraitEngine::new(infcx.tcx);
143         match infcx.at(&cause, param_env).eq(expected, actual) {
144             Ok(InferOk { obligations, .. }) => {
145                 fulfill_cx.register_predicate_obligations(infcx, obligations);
146             }
147             Err(err) => {
148                 infcx.report_mismatched_types(cause, expected, actual, err).emit();
149                 return false;
150             }
151         }
152
153         match fulfill_cx.select_all_or_error(infcx) {
154             Ok(()) => true,
155             Err(errors) => {
156                 infcx.report_fulfillment_errors(&errors, None, false);
157                 false
158             }
159         }
160     })
161 }
162
163 fn check_main_fn_ty(tcx: TyCtxt<'_>, main_def_id: DefId) {
164     let main_id = tcx.hir().as_local_hir_id(main_def_id).unwrap();
165     let main_span = tcx.def_span(main_def_id);
166     let main_t = tcx.type_of(main_def_id);
167     match main_t.kind {
168         ty::FnDef(..) => {
169             if let Some(Node::Item(it)) = tcx.hir().find(main_id) {
170                 if let hir::ItemKind::Fn(.., ref generics, _) = it.kind {
171                     let mut error = false;
172                     if !generics.params.is_empty() {
173                         let msg = "`main` function is not allowed to have generic \
174                                    parameters"
175                             .to_owned();
176                         let label = "`main` cannot have generic parameters".to_string();
177                         struct_span_err!(tcx.sess, generics.span, E0131, "{}", msg)
178                             .span_label(generics.span, label)
179                             .emit();
180                         error = true;
181                     }
182                     if let Some(sp) = generics.where_clause.span() {
183                         struct_span_err!(
184                             tcx.sess,
185                             sp,
186                             E0646,
187                             "`main` function is not allowed to have a `where` clause"
188                         )
189                         .span_label(sp, "`main` cannot have a `where` clause")
190                         .emit();
191                         error = true;
192                     }
193                     if error {
194                         return;
195                     }
196                 }
197             }
198
199             let actual = tcx.fn_sig(main_def_id);
200             let expected_return_type = if tcx.lang_items().termination().is_some() {
201                 // we take the return type of the given main function, the real check is done
202                 // in `check_fn`
203                 actual.output().skip_binder()
204             } else {
205                 // standard () main return type
206                 tcx.mk_unit()
207             };
208
209             let se_ty = tcx.mk_fn_ptr(ty::Binder::bind(tcx.mk_fn_sig(
210                 iter::empty(),
211                 expected_return_type,
212                 false,
213                 hir::Unsafety::Normal,
214                 Abi::Rust,
215             )));
216
217             require_same_types(
218                 tcx,
219                 &ObligationCause::new(main_span, main_id, ObligationCauseCode::MainFunctionType),
220                 se_ty,
221                 tcx.mk_fn_ptr(actual),
222             );
223         }
224         _ => {
225             span_bug!(main_span, "main has a non-function type: found `{}`", main_t);
226         }
227     }
228 }
229
230 fn check_start_fn_ty(tcx: TyCtxt<'_>, start_def_id: DefId) {
231     let start_id = tcx.hir().as_local_hir_id(start_def_id).unwrap();
232     let start_span = tcx.def_span(start_def_id);
233     let start_t = tcx.type_of(start_def_id);
234     match start_t.kind {
235         ty::FnDef(..) => {
236             if let Some(Node::Item(it)) = tcx.hir().find(start_id) {
237                 if let hir::ItemKind::Fn(.., ref generics, _) = it.kind {
238                     let mut error = false;
239                     if !generics.params.is_empty() {
240                         struct_span_err!(
241                             tcx.sess,
242                             generics.span,
243                             E0132,
244                             "start function is not allowed to have type parameters"
245                         )
246                         .span_label(generics.span, "start function cannot have type parameters")
247                         .emit();
248                         error = true;
249                     }
250                     if let Some(sp) = generics.where_clause.span() {
251                         struct_span_err!(
252                             tcx.sess,
253                             sp,
254                             E0647,
255                             "start function is not allowed to have a `where` clause"
256                         )
257                         .span_label(sp, "start function cannot have a `where` clause")
258                         .emit();
259                         error = true;
260                     }
261                     if error {
262                         return;
263                     }
264                 }
265             }
266
267             let se_ty = tcx.mk_fn_ptr(ty::Binder::bind(tcx.mk_fn_sig(
268                 [tcx.types.isize, tcx.mk_imm_ptr(tcx.mk_imm_ptr(tcx.types.u8))].iter().cloned(),
269                 tcx.types.isize,
270                 false,
271                 hir::Unsafety::Normal,
272                 Abi::Rust,
273             )));
274
275             require_same_types(
276                 tcx,
277                 &ObligationCause::new(start_span, start_id, ObligationCauseCode::StartFunctionType),
278                 se_ty,
279                 tcx.mk_fn_ptr(tcx.fn_sig(start_def_id)),
280             );
281         }
282         _ => {
283             span_bug!(start_span, "start has a non-function type: found `{}`", start_t);
284         }
285     }
286 }
287
288 fn check_for_entry_fn(tcx: TyCtxt<'_>) {
289     match tcx.entry_fn(LOCAL_CRATE) {
290         Some((def_id, EntryFnType::Main)) => check_main_fn_ty(tcx, def_id),
291         Some((def_id, EntryFnType::Start)) => check_start_fn_ty(tcx, def_id),
292         _ => {}
293     }
294 }
295
296 pub fn provide(providers: &mut Providers<'_>) {
297     collect::provide(providers);
298     coherence::provide(providers);
299     check::provide(providers);
300     variance::provide(providers);
301     outlives::provide(providers);
302     impl_wf_check::provide(providers);
303 }
304
305 pub fn check_crate(tcx: TyCtxt<'_>) -> Result<(), ErrorReported> {
306     let _prof_timer = tcx.sess.timer("type_check_crate");
307
308     // this ensures that later parts of type checking can assume that items
309     // have valid types and not error
310     // FIXME(matthewjasper) We shouldn't need to do this.
311     tcx.sess.track_errors(|| {
312         tcx.sess.time("type_collecting", || {
313             for &module in tcx.hir().krate().modules.keys() {
314                 tcx.ensure().collect_mod_item_types(tcx.hir().local_def_id(module));
315             }
316         });
317     })?;
318
319     if tcx.features().rustc_attrs {
320         tcx.sess.track_errors(|| {
321             tcx.sess.time("outlives_testing", || outlives::test::test_inferred_outlives(tcx));
322         })?;
323     }
324
325     tcx.sess.track_errors(|| {
326         tcx.sess.time("impl_wf_inference", || impl_wf_check::impl_wf_check(tcx));
327     })?;
328
329     tcx.sess.track_errors(|| {
330         tcx.sess.time("coherence_checking", || coherence::check_coherence(tcx));
331     })?;
332
333     if tcx.features().rustc_attrs {
334         tcx.sess.track_errors(|| {
335             tcx.sess.time("variance_testing", || variance::test::test_variance(tcx));
336         })?;
337     }
338
339     tcx.sess.track_errors(|| {
340         tcx.sess.time("wf_checking", || check::check_wf_new(tcx));
341     })?;
342
343     tcx.sess.time("item_types_checking", || {
344         for &module in tcx.hir().krate().modules.keys() {
345             tcx.ensure().check_mod_item_types(tcx.hir().local_def_id(module));
346         }
347     });
348
349     tcx.sess.time("item_bodies_checking", || tcx.typeck_item_bodies(LOCAL_CRATE));
350
351     check_unused::check_crate(tcx);
352     check_for_entry_fn(tcx);
353
354     if tcx.sess.err_count() == 0 { Ok(()) } else { Err(ErrorReported) }
355 }
356
357 /// A quasi-deprecated helper used in rustdoc and clippy to get
358 /// the type from a HIR node.
359 pub fn hir_ty_to_ty<'tcx>(tcx: TyCtxt<'tcx>, hir_ty: &hir::Ty<'_>) -> Ty<'tcx> {
360     // In case there are any projections, etc., find the "environment"
361     // def-ID that will be used to determine the traits/predicates in
362     // scope.  This is derived from the enclosing item-like thing.
363     let env_node_id = tcx.hir().get_parent_item(hir_ty.hir_id);
364     let env_def_id = tcx.hir().local_def_id(env_node_id);
365     let item_cx = self::collect::ItemCtxt::new(tcx, env_def_id);
366
367     astconv::AstConv::ast_ty_to_ty(&item_cx, hir_ty)
368 }
369
370 pub fn hir_trait_to_predicates<'tcx>(
371     tcx: TyCtxt<'tcx>,
372     hir_trait: &hir::TraitRef<'_>,
373 ) -> Bounds<'tcx> {
374     // In case there are any projections, etc., find the "environment"
375     // def-ID that will be used to determine the traits/predicates in
376     // scope.  This is derived from the enclosing item-like thing.
377     let env_hir_id = tcx.hir().get_parent_item(hir_trait.hir_ref_id);
378     let env_def_id = tcx.hir().local_def_id(env_hir_id);
379     let item_cx = self::collect::ItemCtxt::new(tcx, env_def_id);
380     let mut bounds = Bounds::default();
381     let _ = AstConv::instantiate_poly_trait_ref_inner(
382         &item_cx,
383         hir_trait,
384         DUMMY_SP,
385         tcx.types.err,
386         &mut bounds,
387         true,
388     );
389
390     bounds
391 }