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