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