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