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