• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #![allow(rustc::potential_query_instability)]
59 #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
60 #![feature(box_patterns)]
61 #![feature(control_flow_enum)]
62 #![feature(if_let_guard)]
63 #![feature(is_sorted)]
64 #![feature(iter_intersperse)]
65 #![feature(let_chains)]
66 #![feature(min_specialization)]
67 #![feature(never_type)]
68 #![feature(lazy_cell)]
69 #![feature(slice_partition_dedup)]
70 #![feature(try_blocks)]
71 #![feature(type_alias_impl_trait)]
72 #![recursion_limit = "256"]
73 
74 #[macro_use]
75 extern crate tracing;
76 
77 #[macro_use]
78 extern crate rustc_middle;
79 
80 // These are used by Clippy.
81 pub mod check;
82 
83 pub mod astconv;
84 pub mod autoderef;
85 mod bounds;
86 mod check_unused;
87 mod coherence;
88 // FIXME: This module shouldn't be public.
89 pub mod collect;
90 mod constrained_generic_params;
91 mod errors;
92 pub mod hir_wf_check;
93 mod impl_wf_check;
94 mod outlives;
95 pub mod structured_errors;
96 mod variance;
97 
98 use rustc_errors::ErrorGuaranteed;
99 use rustc_errors::{DiagnosticMessage, SubdiagnosticMessage};
100 use rustc_fluent_macro::fluent_messages;
101 use rustc_hir as hir;
102 use rustc_hir::Node;
103 use rustc_infer::infer::TyCtxtInferExt;
104 use rustc_middle::middle;
105 use rustc_middle::query::Providers;
106 use rustc_middle::ty::{self, Ty, TyCtxt};
107 use rustc_middle::util;
108 use rustc_session::{config::EntryFnType, parse::feature_err};
109 use rustc_span::def_id::{DefId, LocalDefId, CRATE_DEF_ID};
110 use rustc_span::{symbol::sym, Span, DUMMY_SP};
111 use rustc_target::spec::abi::Abi;
112 use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt as _;
113 use rustc_trait_selection::traits::{self, ObligationCause, ObligationCauseCode, ObligationCtxt};
114 
115 use std::ops::Not;
116 
117 use astconv::{AstConv, OnlySelfBounds};
118 use bounds::Bounds;
119 
120 fluent_messages! { "../messages.ftl" }
121 
require_c_abi_if_c_variadic(tcx: TyCtxt<'_>, decl: &hir::FnDecl<'_>, abi: Abi, span: Span)122 fn require_c_abi_if_c_variadic(tcx: TyCtxt<'_>, decl: &hir::FnDecl<'_>, abi: Abi, span: Span) {
123     const CONVENTIONS_UNSTABLE: &str = "`C`, `cdecl`, `win64`, `sysv64` or `efiapi`";
124     const CONVENTIONS_STABLE: &str = "`C` or `cdecl`";
125     const UNSTABLE_EXPLAIN: &str =
126         "using calling conventions other than `C` or `cdecl` for varargs functions is unstable";
127 
128     if !decl.c_variadic || matches!(abi, Abi::C { .. } | Abi::Cdecl { .. }) {
129         return;
130     }
131 
132     let extended_abi_support = tcx.features().extended_varargs_abi_support;
133     let conventions = match (extended_abi_support, abi.supports_varargs()) {
134         // User enabled additional ABI support for varargs and function ABI matches those ones.
135         (true, true) => return,
136 
137         // Using this ABI would be ok, if the feature for additional ABI support was enabled.
138         // Return CONVENTIONS_STABLE, because we want the other error to look the same.
139         (false, true) => {
140             feature_err(
141                 &tcx.sess.parse_sess,
142                 sym::extended_varargs_abi_support,
143                 span,
144                 UNSTABLE_EXPLAIN,
145             )
146             .emit();
147             CONVENTIONS_STABLE
148         }
149 
150         (false, false) => CONVENTIONS_STABLE,
151         (true, false) => CONVENTIONS_UNSTABLE,
152     };
153 
154     tcx.sess.emit_err(errors::VariadicFunctionCompatibleConvention { span, conventions });
155 }
156 
require_same_types<'tcx>( tcx: TyCtxt<'tcx>, cause: &ObligationCause<'tcx>, param_env: ty::ParamEnv<'tcx>, expected: Ty<'tcx>, actual: Ty<'tcx>, )157 fn require_same_types<'tcx>(
158     tcx: TyCtxt<'tcx>,
159     cause: &ObligationCause<'tcx>,
160     param_env: ty::ParamEnv<'tcx>,
161     expected: Ty<'tcx>,
162     actual: Ty<'tcx>,
163 ) {
164     let infcx = &tcx.infer_ctxt().build();
165     let ocx = ObligationCtxt::new(infcx);
166     match ocx.eq(cause, param_env, expected, actual) {
167         Ok(()) => {
168             let errors = ocx.select_all_or_error();
169             if !errors.is_empty() {
170                 infcx.err_ctxt().report_fulfillment_errors(&errors);
171             }
172         }
173         Err(err) => {
174             infcx.err_ctxt().report_mismatched_types(cause, expected, actual, err).emit();
175         }
176     }
177 }
178 
check_main_fn_ty(tcx: TyCtxt<'_>, main_def_id: DefId)179 fn check_main_fn_ty(tcx: TyCtxt<'_>, main_def_id: DefId) {
180     let main_fnsig = tcx.fn_sig(main_def_id).subst_identity();
181     let main_span = tcx.def_span(main_def_id);
182 
183     fn main_fn_diagnostics_def_id(tcx: TyCtxt<'_>, def_id: DefId, sp: Span) -> LocalDefId {
184         if let Some(local_def_id) = def_id.as_local() {
185             let hir_type = tcx.type_of(local_def_id).subst_identity();
186             if !matches!(hir_type.kind(), ty::FnDef(..)) {
187                 span_bug!(sp, "main has a non-function type: found `{}`", hir_type);
188             }
189             local_def_id
190         } else {
191             CRATE_DEF_ID
192         }
193     }
194 
195     fn main_fn_generics_params_span(tcx: TyCtxt<'_>, def_id: DefId) -> Option<Span> {
196         if !def_id.is_local() {
197             return None;
198         }
199         let hir_id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local());
200         match tcx.hir().find(hir_id) {
201             Some(Node::Item(hir::Item { kind: hir::ItemKind::Fn(_, generics, _), .. })) => {
202                 generics.params.is_empty().not().then_some(generics.span)
203             }
204             _ => {
205                 span_bug!(tcx.def_span(def_id), "main has a non-function type");
206             }
207         }
208     }
209 
210     fn main_fn_where_clauses_span(tcx: TyCtxt<'_>, def_id: DefId) -> Option<Span> {
211         if !def_id.is_local() {
212             return None;
213         }
214         let hir_id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local());
215         match tcx.hir().find(hir_id) {
216             Some(Node::Item(hir::Item { kind: hir::ItemKind::Fn(_, generics, _), .. })) => {
217                 Some(generics.where_clause_span)
218             }
219             _ => {
220                 span_bug!(tcx.def_span(def_id), "main has a non-function type");
221             }
222         }
223     }
224 
225     fn main_fn_asyncness_span(tcx: TyCtxt<'_>, def_id: DefId) -> Option<Span> {
226         if !def_id.is_local() {
227             return None;
228         }
229         Some(tcx.def_span(def_id))
230     }
231 
232     fn main_fn_return_type_span(tcx: TyCtxt<'_>, def_id: DefId) -> Option<Span> {
233         if !def_id.is_local() {
234             return None;
235         }
236         let hir_id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local());
237         match tcx.hir().find(hir_id) {
238             Some(Node::Item(hir::Item { kind: hir::ItemKind::Fn(fn_sig, _, _), .. })) => {
239                 Some(fn_sig.decl.output.span())
240             }
241             _ => {
242                 span_bug!(tcx.def_span(def_id), "main has a non-function type");
243             }
244         }
245     }
246 
247     let mut error = false;
248     let main_diagnostics_def_id = main_fn_diagnostics_def_id(tcx, main_def_id, main_span);
249     let main_fn_generics = tcx.generics_of(main_def_id);
250     let main_fn_predicates = tcx.predicates_of(main_def_id);
251     if main_fn_generics.count() != 0 || !main_fnsig.bound_vars().is_empty() {
252         let generics_param_span = main_fn_generics_params_span(tcx, main_def_id);
253         tcx.sess.emit_err(errors::MainFunctionGenericParameters {
254             span: generics_param_span.unwrap_or(main_span),
255             label_span: generics_param_span,
256         });
257         error = true;
258     } else if !main_fn_predicates.predicates.is_empty() {
259         // generics may bring in implicit predicates, so we skip this check if generics is present.
260         let generics_where_clauses_span = main_fn_where_clauses_span(tcx, main_def_id);
261         tcx.sess.emit_err(errors::WhereClauseOnMain {
262             span: generics_where_clauses_span.unwrap_or(main_span),
263             generics_span: generics_where_clauses_span,
264         });
265         error = true;
266     }
267 
268     let main_asyncness = tcx.asyncness(main_def_id);
269     if let hir::IsAsync::Async = main_asyncness {
270         let asyncness_span = main_fn_asyncness_span(tcx, main_def_id);
271         tcx.sess.emit_err(errors::MainFunctionAsync { span: main_span, asyncness: asyncness_span });
272         error = true;
273     }
274 
275     for attr in tcx.get_attrs(main_def_id, sym::track_caller) {
276         tcx.sess.emit_err(errors::TrackCallerOnMain { span: attr.span, annotated: main_span });
277         error = true;
278     }
279 
280     if !tcx.codegen_fn_attrs(main_def_id).target_features.is_empty()
281         // Calling functions with `#[target_feature]` is not unsafe on WASM, see #84988
282         && !tcx.sess.target.is_like_wasm
283         && !tcx.sess.opts.actually_rustdoc
284     {
285         tcx.sess.emit_err(errors::TargetFeatureOnMain { main: main_span });
286         error = true;
287     }
288 
289     if error {
290         return;
291     }
292 
293     // Main should have no WC, so empty param env is OK here.
294     let param_env = ty::ParamEnv::empty();
295     let expected_return_type;
296     if let Some(term_did) = tcx.lang_items().termination() {
297         let return_ty = main_fnsig.output();
298         let return_ty_span = main_fn_return_type_span(tcx, main_def_id).unwrap_or(main_span);
299         if !return_ty.bound_vars().is_empty() {
300             tcx.sess.emit_err(errors::MainFunctionReturnTypeGeneric { span: return_ty_span });
301             error = true;
302         }
303         let return_ty = return_ty.skip_binder();
304         let infcx = tcx.infer_ctxt().build();
305         let cause = traits::ObligationCause::new(
306             return_ty_span,
307             main_diagnostics_def_id,
308             ObligationCauseCode::MainFunctionType,
309         );
310         let ocx = traits::ObligationCtxt::new(&infcx);
311         let norm_return_ty = ocx.normalize(&cause, param_env, return_ty);
312         ocx.register_bound(cause, param_env, norm_return_ty, term_did);
313         let errors = ocx.select_all_or_error();
314         if !errors.is_empty() {
315             infcx.err_ctxt().report_fulfillment_errors(&errors);
316             error = true;
317         }
318         // now we can take the return type of the given main function
319         expected_return_type = main_fnsig.output();
320     } else {
321         // standard () main return type
322         expected_return_type = ty::Binder::dummy(Ty::new_unit(tcx));
323     }
324 
325     if error {
326         return;
327     }
328 
329     let se_ty = Ty::new_fn_ptr(
330         tcx,
331         expected_return_type.map_bound(|expected_return_type| {
332             tcx.mk_fn_sig([], expected_return_type, false, hir::Unsafety::Normal, Abi::Rust)
333         }),
334     );
335 
336     require_same_types(
337         tcx,
338         &ObligationCause::new(
339             main_span,
340             main_diagnostics_def_id,
341             ObligationCauseCode::MainFunctionType,
342         ),
343         param_env,
344         se_ty,
345         Ty::new_fn_ptr(tcx, main_fnsig),
346     );
347 }
check_start_fn_ty(tcx: TyCtxt<'_>, start_def_id: DefId)348 fn check_start_fn_ty(tcx: TyCtxt<'_>, start_def_id: DefId) {
349     let start_def_id = start_def_id.expect_local();
350     let start_id = tcx.hir().local_def_id_to_hir_id(start_def_id);
351     let start_span = tcx.def_span(start_def_id);
352     let start_t = tcx.type_of(start_def_id).subst_identity();
353     match start_t.kind() {
354         ty::FnDef(..) => {
355             if let Some(Node::Item(it)) = tcx.hir().find(start_id) {
356                 if let hir::ItemKind::Fn(sig, generics, _) = &it.kind {
357                     let mut error = false;
358                     if !generics.params.is_empty() {
359                         tcx.sess.emit_err(errors::StartFunctionParameters { span: generics.span });
360                         error = true;
361                     }
362                     if generics.has_where_clause_predicates {
363                         tcx.sess.emit_err(errors::StartFunctionWhere {
364                             span: generics.where_clause_span,
365                         });
366                         error = true;
367                     }
368                     if let hir::IsAsync::Async = sig.header.asyncness {
369                         let span = tcx.def_span(it.owner_id);
370                         tcx.sess.emit_err(errors::StartAsync { span: span });
371                         error = true;
372                     }
373 
374                     let attrs = tcx.hir().attrs(start_id);
375                     for attr in attrs {
376                         if attr.has_name(sym::track_caller) {
377                             tcx.sess.emit_err(errors::StartTrackCaller {
378                                 span: attr.span,
379                                 start: start_span,
380                             });
381                             error = true;
382                         }
383                         if attr.has_name(sym::target_feature)
384                             // Calling functions with `#[target_feature]` is
385                             // not unsafe on WASM, see #84988
386                             && !tcx.sess.target.is_like_wasm
387                             && !tcx.sess.opts.actually_rustdoc
388                         {
389                             tcx.sess.emit_err(errors::StartTargetFeature {
390                                 span: attr.span,
391                                 start: start_span,
392                             });
393                             error = true;
394                         }
395                     }
396 
397                     if error {
398                         return;
399                     }
400                 }
401             }
402 
403             let se_ty = Ty::new_fn_ptr(
404                 tcx,
405                 ty::Binder::dummy(tcx.mk_fn_sig(
406                     [tcx.types.isize, Ty::new_imm_ptr(tcx, Ty::new_imm_ptr(tcx, tcx.types.u8))],
407                     tcx.types.isize,
408                     false,
409                     hir::Unsafety::Normal,
410                     Abi::Rust,
411                 )),
412             );
413 
414             require_same_types(
415                 tcx,
416                 &ObligationCause::new(
417                     start_span,
418                     start_def_id,
419                     ObligationCauseCode::StartFunctionType,
420                 ),
421                 ty::ParamEnv::empty(), // start should not have any where bounds.
422                 se_ty,
423                 Ty::new_fn_ptr(tcx, tcx.fn_sig(start_def_id).subst_identity()),
424             );
425         }
426         _ => {
427             span_bug!(start_span, "start has a non-function type: found `{}`", start_t);
428         }
429     }
430 }
431 
check_for_entry_fn(tcx: TyCtxt<'_>)432 fn check_for_entry_fn(tcx: TyCtxt<'_>) {
433     match tcx.entry_fn(()) {
434         Some((def_id, EntryFnType::Main { .. })) => check_main_fn_ty(tcx, def_id),
435         Some((def_id, EntryFnType::Start)) => check_start_fn_ty(tcx, def_id),
436         _ => {}
437     }
438 }
439 
provide(providers: &mut Providers)440 pub fn provide(providers: &mut Providers) {
441     collect::provide(providers);
442     coherence::provide(providers);
443     check::provide(providers);
444     variance::provide(providers);
445     outlives::provide(providers);
446     impl_wf_check::provide(providers);
447     hir_wf_check::provide(providers);
448 }
449 
check_crate(tcx: TyCtxt<'_>) -> Result<(), ErrorGuaranteed>450 pub fn check_crate(tcx: TyCtxt<'_>) -> Result<(), ErrorGuaranteed> {
451     let _prof_timer = tcx.sess.timer("type_check_crate");
452 
453     // this ensures that later parts of type checking can assume that items
454     // have valid types and not error
455     // FIXME(matthewjasper) We shouldn't need to use `track_errors`.
456     tcx.sess.track_errors(|| {
457         tcx.sess.time("type_collecting", || {
458             tcx.hir().for_each_module(|module| tcx.ensure().collect_mod_item_types(module))
459         });
460     })?;
461 
462     if tcx.features().rustc_attrs {
463         tcx.sess.track_errors(|| {
464             tcx.sess.time("outlives_testing", || outlives::test::test_inferred_outlives(tcx));
465         })?;
466     }
467 
468     tcx.sess.track_errors(|| {
469         tcx.sess.time("impl_wf_inference", || {
470             tcx.hir().for_each_module(|module| tcx.ensure().check_mod_impl_wf(module))
471         });
472     })?;
473 
474     tcx.sess.track_errors(|| {
475         tcx.sess.time("coherence_checking", || {
476             for &trait_def_id in tcx.all_local_trait_impls(()).keys() {
477                 tcx.ensure().coherent_trait(trait_def_id);
478             }
479 
480             // these queries are executed for side-effects (error reporting):
481             tcx.ensure().crate_inherent_impls(());
482             tcx.ensure().crate_inherent_impls_overlap_check(());
483         });
484     })?;
485 
486     if tcx.features().rustc_attrs {
487         tcx.sess.track_errors(|| {
488             tcx.sess.time("variance_testing", || variance::test::test_variance(tcx));
489         })?;
490     }
491 
492     tcx.sess.track_errors(|| {
493         tcx.sess.time("wf_checking", || {
494             tcx.hir().par_for_each_module(|module| tcx.ensure().check_mod_type_wf(module))
495         });
496     })?;
497 
498     // NOTE: This is copy/pasted in librustdoc/core.rs and should be kept in sync.
499     tcx.sess.time("item_types_checking", || {
500         tcx.hir().for_each_module(|module| tcx.ensure().check_mod_item_types(module))
501     });
502 
503     check_unused::check_crate(tcx);
504     check_for_entry_fn(tcx);
505 
506     if let Some(reported) = tcx.sess.has_errors() { Err(reported) } else { Ok(()) }
507 }
508 
509 /// A quasi-deprecated helper used in rustdoc and clippy to get
510 /// the type from a HIR node.
hir_ty_to_ty<'tcx>(tcx: TyCtxt<'tcx>, hir_ty: &hir::Ty<'_>) -> Ty<'tcx>511 pub fn hir_ty_to_ty<'tcx>(tcx: TyCtxt<'tcx>, hir_ty: &hir::Ty<'_>) -> Ty<'tcx> {
512     // In case there are any projections, etc., find the "environment"
513     // def-ID that will be used to determine the traits/predicates in
514     // scope. This is derived from the enclosing item-like thing.
515     let env_def_id = tcx.hir().get_parent_item(hir_ty.hir_id);
516     let item_cx = self::collect::ItemCtxt::new(tcx, env_def_id.def_id);
517     item_cx.astconv().ast_ty_to_ty(hir_ty)
518 }
519 
hir_trait_to_predicates<'tcx>( tcx: TyCtxt<'tcx>, hir_trait: &hir::TraitRef<'_>, self_ty: Ty<'tcx>, ) -> Bounds<'tcx>520 pub fn hir_trait_to_predicates<'tcx>(
521     tcx: TyCtxt<'tcx>,
522     hir_trait: &hir::TraitRef<'_>,
523     self_ty: Ty<'tcx>,
524 ) -> Bounds<'tcx> {
525     // In case there are any projections, etc., find the "environment"
526     // def-ID that will be used to determine the traits/predicates in
527     // scope. This is derived from the enclosing item-like thing.
528     let env_def_id = tcx.hir().get_parent_item(hir_trait.hir_ref_id);
529     let item_cx = self::collect::ItemCtxt::new(tcx, env_def_id.def_id);
530     let mut bounds = Bounds::default();
531     let _ = &item_cx.astconv().instantiate_poly_trait_ref(
532         hir_trait,
533         DUMMY_SP,
534         ty::BoundConstness::NotConst,
535         ty::ImplPolarity::Positive,
536         self_ty,
537         &mut bounds,
538         true,
539         OnlySelfBounds(false),
540     );
541 
542     bounds
543 }
544