|  | /*! | 
|  |  | 
|  | # typeck | 
|  |  | 
|  | The type checker is responsible for: | 
|  |  | 
|  | 1. Determining the type of each expression. | 
|  | 2. Resolving methods and traits. | 
|  | 3. Guaranteeing that most type rules are met. ("Most?", you say, "why most?" | 
|  | Well, dear reader, read on.) | 
|  |  | 
|  | The main entry point is [`check_crate()`]. Type checking operates in | 
|  | several major phases: | 
|  |  | 
|  | 1. The collect phase first passes over all items and determines their | 
|  | type, without examining their "innards". | 
|  |  | 
|  | 2. Variance inference then runs to compute the variance of each parameter. | 
|  |  | 
|  | 3. Coherence checks for overlapping or orphaned impls. | 
|  |  | 
|  | 4. Finally, the check phase then checks function bodies and so forth. | 
|  | Within the check phase, we check each function body one at a time | 
|  | (bodies of function expressions are checked as part of the | 
|  | containing function). Inference is used to supply types wherever | 
|  | they are unknown. The actual checking of a function itself has | 
|  | several phases (check, regionck, writeback), as discussed in the | 
|  | documentation for the [`check`] module. | 
|  |  | 
|  | The type checker is defined into various submodules which are documented | 
|  | independently: | 
|  |  | 
|  | - hir_ty_lowering: lowers type-system entities from the [HIR][hir] to the | 
|  | [`rustc_middle::ty`] representation. | 
|  |  | 
|  | - collect: computes the types of each top-level item and enters them into | 
|  | the `tcx.types` table for later use. | 
|  |  | 
|  | - coherence: enforces coherence rules, builds some tables. | 
|  |  | 
|  | - variance: variance inference | 
|  |  | 
|  | - outlives: outlives inference | 
|  |  | 
|  | - check: walks over function bodies and type checks them, inferring types for | 
|  | local variables, type parameters, etc as necessary. | 
|  |  | 
|  | - infer: finds the types to use for each type variable such that | 
|  | all subtyping and assignment constraints are met. In essence, the check | 
|  | module specifies the constraints, and the infer module solves them. | 
|  |  | 
|  | ## Note | 
|  |  | 
|  | This API is completely unstable and subject to change. | 
|  |  | 
|  | */ | 
|  |  | 
|  | // tidy-alphabetical-start | 
|  | #![allow(internal_features)] | 
|  | #![allow(rustc::diagnostic_outside_of_impl)] | 
|  | #![allow(rustc::untranslatable_diagnostic)] | 
|  | #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] | 
|  | #![doc(rust_logo)] | 
|  | #![feature(assert_matches)] | 
|  | #![feature(debug_closure_helpers)] | 
|  | #![feature(gen_blocks)] | 
|  | #![feature(if_let_guard)] | 
|  | #![feature(iter_intersperse)] | 
|  | #![feature(never_type)] | 
|  | #![feature(rustdoc_internals)] | 
|  | #![feature(slice_partition_dedup)] | 
|  | #![feature(try_blocks)] | 
|  | #![feature(unwrap_infallible)] | 
|  | // tidy-alphabetical-end | 
|  |  | 
|  | // These are used by Clippy. | 
|  | pub mod check; | 
|  |  | 
|  | pub mod autoderef; | 
|  | mod check_unused; | 
|  | mod coherence; | 
|  | mod collect; | 
|  | mod constrained_generic_params; | 
|  | mod delegation; | 
|  | mod errors; | 
|  | pub mod hir_ty_lowering; | 
|  | pub mod hir_wf_check; | 
|  | mod impl_wf_check; | 
|  | mod outlives; | 
|  | mod variance; | 
|  |  | 
|  | pub use errors::NoVariantNamed; | 
|  | use rustc_abi::ExternAbi; | 
|  | use rustc_hir::def::DefKind; | 
|  | use rustc_hir::lints::DelayedLint; | 
|  | use rustc_hir::{self as hir}; | 
|  | use rustc_middle::middle; | 
|  | use rustc_middle::mir::interpret::GlobalId; | 
|  | use rustc_middle::query::Providers; | 
|  | use rustc_middle::ty::{self, Const, Ty, TyCtxt}; | 
|  | use rustc_session::parse::feature_err; | 
|  | use rustc_span::symbol::sym; | 
|  | use rustc_span::{ErrorGuaranteed, Span}; | 
|  | use rustc_trait_selection::traits; | 
|  |  | 
|  | pub use crate::collect::suggest_impl_trait; | 
|  | use crate::hir_ty_lowering::{FeedConstTy, HirTyLowerer}; | 
|  |  | 
|  | rustc_fluent_macro::fluent_messages! { "../messages.ftl" } | 
|  |  | 
|  | fn require_c_abi_if_c_variadic( | 
|  | tcx: TyCtxt<'_>, | 
|  | decl: &hir::FnDecl<'_>, | 
|  | abi: ExternAbi, | 
|  | span: Span, | 
|  | ) { | 
|  | // ABIs which can stably use varargs | 
|  | if !decl.c_variadic || matches!(abi, ExternAbi::C { .. } | ExternAbi::Cdecl { .. }) { | 
|  | return; | 
|  | } | 
|  |  | 
|  | // ABIs with feature-gated stability | 
|  | let extended_abi_support = tcx.features().extended_varargs_abi_support(); | 
|  | let extern_system_varargs = tcx.features().extern_system_varargs(); | 
|  |  | 
|  | // If the feature gate has been enabled, we can stop here | 
|  | if extern_system_varargs && let ExternAbi::System { .. } = abi { | 
|  | return; | 
|  | }; | 
|  | if extended_abi_support && abi.supports_varargs() { | 
|  | return; | 
|  | }; | 
|  |  | 
|  | // Looks like we need to pick an error to emit. | 
|  | // Is there any feature which we could have enabled to make this work? | 
|  | let unstable_explain = | 
|  | format!("C-variadic functions with the {abi} calling convention are unstable"); | 
|  | match abi { | 
|  | ExternAbi::System { .. } => { | 
|  | feature_err(&tcx.sess, sym::extern_system_varargs, span, unstable_explain) | 
|  | } | 
|  | abi if abi.supports_varargs() => { | 
|  | feature_err(&tcx.sess, sym::extended_varargs_abi_support, span, unstable_explain) | 
|  | } | 
|  | _ => tcx.dcx().create_err(errors::VariadicFunctionCompatibleConvention { | 
|  | span, | 
|  | convention: &format!("{abi}"), | 
|  | }), | 
|  | } | 
|  | .emit(); | 
|  | } | 
|  |  | 
|  | /// Adds query implementations to the [Providers] vtable, see [`rustc_middle::query`] | 
|  | pub fn provide(providers: &mut Providers) { | 
|  | collect::provide(providers); | 
|  | coherence::provide(providers); | 
|  | check::provide(providers); | 
|  | *providers = Providers { | 
|  | check_unused_traits: check_unused::check_unused_traits, | 
|  | diagnostic_hir_wf_check: hir_wf_check::diagnostic_hir_wf_check, | 
|  | inferred_outlives_crate: outlives::inferred_outlives_crate, | 
|  | inferred_outlives_of: outlives::inferred_outlives_of, | 
|  | inherit_sig_for_delegation_item: delegation::inherit_sig_for_delegation_item, | 
|  | enforce_impl_non_lifetime_params_are_constrained: | 
|  | impl_wf_check::enforce_impl_non_lifetime_params_are_constrained, | 
|  | crate_variances: variance::crate_variances, | 
|  | variances_of: variance::variances_of, | 
|  | ..*providers | 
|  | }; | 
|  | } | 
|  |  | 
|  | fn emit_delayed_lint(lint: &DelayedLint, tcx: TyCtxt<'_>) { | 
|  | match lint { | 
|  | DelayedLint::AttributeParsing(attribute_lint) => { | 
|  | rustc_attr_parsing::emit_attribute_lint(attribute_lint, tcx) | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | pub fn check_crate(tcx: TyCtxt<'_>) { | 
|  | let _prof_timer = tcx.sess.timer("type_check_crate"); | 
|  |  | 
|  | tcx.sess.time("coherence_checking", || { | 
|  | // When discarding query call results, use an explicit type to indicate | 
|  | // what we are intending to discard, to help future type-based refactoring. | 
|  | type R = Result<(), ErrorGuaranteed>; | 
|  |  | 
|  | let _: R = tcx.ensure_ok().check_type_wf(()); | 
|  |  | 
|  | for &trait_def_id in tcx.all_local_trait_impls(()).keys() { | 
|  | let _: R = tcx.ensure_ok().coherent_trait(trait_def_id); | 
|  | } | 
|  | // these queries are executed for side-effects (error reporting): | 
|  | let _: R = tcx.ensure_ok().crate_inherent_impls_validity_check(()); | 
|  | let _: R = tcx.ensure_ok().crate_inherent_impls_overlap_check(()); | 
|  | }); | 
|  |  | 
|  | tcx.sess.time("emit_ast_lowering_delayed_lints", || { | 
|  | // sanity check in debug mode that all lints are really noticed | 
|  | // and we really will emit them all in the loop right below. | 
|  | // | 
|  | // during ast lowering, when creating items, foreign items, trait items and impl items | 
|  | // we store in them whether they have any lints in their owner node that should be | 
|  | // picked up by `hir_crate_items`. However, theoretically code can run between that | 
|  | // boolean being inserted into the item and the owner node being created. | 
|  | // We don't want any new lints to be emitted there | 
|  | // (though honestly, you have to really try to manage to do that but still), | 
|  | // but this check is there to catch that. | 
|  | #[cfg(debug_assertions)] | 
|  | { | 
|  | // iterate over all owners | 
|  | for owner_id in tcx.hir_crate_items(()).owners() { | 
|  | // if it has delayed lints | 
|  | if let Some(delayed_lints) = tcx.opt_ast_lowering_delayed_lints(owner_id) { | 
|  | if !delayed_lints.lints.is_empty() { | 
|  | // assert that delayed_lint_items also picked up this item to have lints | 
|  | assert!( | 
|  | tcx.hir_crate_items(()).delayed_lint_items().any(|i| i == owner_id) | 
|  | ); | 
|  | } | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | for owner_id in tcx.hir_crate_items(()).delayed_lint_items() { | 
|  | if let Some(delayed_lints) = tcx.opt_ast_lowering_delayed_lints(owner_id) { | 
|  | for lint in &delayed_lints.lints { | 
|  | emit_delayed_lint(lint, tcx); | 
|  | } | 
|  | } | 
|  | } | 
|  | }); | 
|  |  | 
|  | tcx.par_hir_body_owners(|item_def_id| { | 
|  | let def_kind = tcx.def_kind(item_def_id); | 
|  | // Make sure we evaluate all static and (non-associated) const items, even if unused. | 
|  | // If any of these fail to evaluate, we do not want this crate to pass compilation. | 
|  | match def_kind { | 
|  | DefKind::Static { .. } => { | 
|  | tcx.ensure_ok().eval_static_initializer(item_def_id); | 
|  | check::maybe_check_static_with_link_section(tcx, item_def_id); | 
|  | } | 
|  | DefKind::Const if !tcx.generics_of(item_def_id).own_requires_monomorphization() => { | 
|  | // FIXME(generic_const_items): Passing empty instead of identity args is fishy but | 
|  | //                             seems to be fine for now. Revisit this! | 
|  | let instance = ty::Instance::new_raw(item_def_id.into(), ty::GenericArgs::empty()); | 
|  | let cid = GlobalId { instance, promoted: None }; | 
|  | let typing_env = ty::TypingEnv::fully_monomorphized(); | 
|  | tcx.ensure_ok().eval_to_const_value_raw(typing_env.as_query_input(cid)); | 
|  | } | 
|  | _ => (), | 
|  | } | 
|  | // Skip `AnonConst`s because we feed their `type_of`. | 
|  | if !matches!(def_kind, DefKind::AnonConst) { | 
|  | tcx.ensure_ok().typeck(item_def_id); | 
|  | } | 
|  | // Ensure we generate the new `DefId` before finishing `check_crate`. | 
|  | // Afterwards we freeze the list of `DefId`s. | 
|  | if tcx.needs_coroutine_by_move_body_def_id(item_def_id.to_def_id()) { | 
|  | tcx.ensure_done().coroutine_by_move_body_def_id(item_def_id); | 
|  | } | 
|  | }); | 
|  |  | 
|  | if tcx.features().rustc_attrs() { | 
|  | tcx.sess.time("dumping_rustc_attr_data", || { | 
|  | outlives::dump::inferred_outlives(tcx); | 
|  | variance::dump::variances(tcx); | 
|  | collect::dump::opaque_hidden_types(tcx); | 
|  | collect::dump::predicates_and_item_bounds(tcx); | 
|  | collect::dump::def_parents(tcx); | 
|  | collect::dump::vtables(tcx); | 
|  | }); | 
|  | } | 
|  |  | 
|  | tcx.ensure_ok().check_unused_traits(()); | 
|  | } | 
|  |  | 
|  | /// Lower a [`hir::Ty`] to a [`Ty`]. | 
|  | /// | 
|  | /// <div class="warning"> | 
|  | /// | 
|  | /// This function is **quasi-deprecated**. It can cause ICEs if called inside of a body | 
|  | /// (of a function or constant) and especially if it contains inferred types (`_`). | 
|  | /// | 
|  | /// It's used in rustdoc and Clippy. | 
|  | /// | 
|  | /// </div> | 
|  | pub fn lower_ty<'tcx>(tcx: TyCtxt<'tcx>, hir_ty: &hir::Ty<'tcx>) -> Ty<'tcx> { | 
|  | // In case there are any projections, etc., find the "environment" | 
|  | // def-ID that will be used to determine the traits/predicates in | 
|  | // scope. This is derived from the enclosing item-like thing. | 
|  | let env_def_id = tcx.hir_get_parent_item(hir_ty.hir_id); | 
|  | collect::ItemCtxt::new(tcx, env_def_id.def_id) | 
|  | .lowerer() | 
|  | .lower_ty_maybe_return_type_notation(hir_ty) | 
|  | } | 
|  |  | 
|  | /// This is for rustdoc. | 
|  | // FIXME(const_generics): having special methods for rustdoc in `rustc_hir_analysis` is cursed | 
|  | pub fn lower_const_arg_for_rustdoc<'tcx>( | 
|  | tcx: TyCtxt<'tcx>, | 
|  | hir_ct: &hir::ConstArg<'tcx>, | 
|  | feed: FeedConstTy<'_, 'tcx>, | 
|  | ) -> Const<'tcx> { | 
|  | let env_def_id = tcx.hir_get_parent_item(hir_ct.hir_id); | 
|  | collect::ItemCtxt::new(tcx, env_def_id.def_id).lowerer().lower_const_arg(hir_ct, feed) | 
|  | } |