Skip to main content

rustc_hir_analysis/
lib.rs

1/*!
2
3# typeck
4
5The type checker is responsible for:
6
71. Determining the type of each expression.
82. Resolving methods and traits.
93. Guaranteeing that most type rules are met. ("Most?", you say, "why most?"
10   Well, dear reader, read on.)
11
12The main entry point is [`check_crate()`]. Type checking operates in
13several major phases:
14
151. The collect phase first passes over all items and determines their
16   type, without examining their "innards".
17
182. Variance inference then runs to compute the variance of each parameter.
19
203. Coherence checks for overlapping or orphaned impls.
21
224. 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
30The type checker is defined into various submodules which are documented
31independently:
32
33- hir_ty_lowering: lowers type-system entities from the [HIR][hir] to the
34  [`rustc_middle::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
54This API is completely unstable and subject to change.
55
56*/
57
58// tidy-alphabetical-start
59#![cfg_attr(bootstrap, feature(never_type))]
60#![cfg_attr(bootstrap, feature(unwrap_infallible))]
61#![feature(default_field_values)]
62#![feature(gen_blocks)]
63#![feature(iter_intersperse)]
64#![feature(slice_partition_dedup)]
65#![feature(try_blocks)]
66// tidy-alphabetical-end
67
68// These are used by Clippy.
69pub mod check;
70
71pub mod autoderef;
72mod check_unused;
73mod coherence;
74mod collect;
75mod constrained_generic_params;
76pub mod delegation;
77pub mod diagnostics;
78pub mod hir_ty_lowering;
79pub mod hir_wf_check;
80mod impl_wf_check;
81mod outlives;
82mod variance;
83
84use rustc_abi::{CVariadicStatus, ExternAbi};
85use rustc_hir as hir;
86use rustc_hir::def::DefKind;
87use rustc_middle::mir::interpret::GlobalId;
88use rustc_middle::query::Providers;
89use rustc_middle::ty::{Const, Ty, TyCtxt};
90use rustc_middle::{middle, ty};
91use rustc_session::diagnostics::feature_err;
92use rustc_span::{ErrorGuaranteed, Span};
93use rustc_trait_selection::traits;
94
95pub use crate::collect::suggest_impl_trait;
96use crate::hir_ty_lowering::HirTyLowerer;
97
98fn check_c_variadic_abi(tcx: TyCtxt<'_>, decl: &hir::FnDecl<'_>, abi: ExternAbi, span: Span) {
99    if !decl.c_variadic() {
100        // Not even a variadic function.
101        return;
102    }
103
104    match abi.supports_c_variadic() {
105        CVariadicStatus::Stable => {}
106        CVariadicStatus::NotSupported => {
107            tcx.dcx().emit_err(diagnostics::VariadicFunctionCompatibleConvention {
108                span,
109                convention: &::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("{0}", abi))
    })format!("{abi}"),
110            });
111        }
112        CVariadicStatus::Unstable { feature } => {
113            if !tcx.features().enabled(feature) {
114                feature_err(
115                    &tcx.sess,
116                    feature,
117                    span,
118                    ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("C-variadic functions with the {0} calling convention are unstable",
                abi))
    })format!("C-variadic functions with the {abi} calling convention are unstable"),
119                )
120                .emit();
121            }
122        }
123    }
124}
125
126/// Adds query implementations to the [Providers] vtable, see [`rustc_middle::query`]
127pub fn provide(providers: &mut Providers) {
128    collect::provide(providers);
129    coherence::provide(providers);
130    check::provide(providers);
131    *providers = Providers {
132        check_unused_traits: check_unused::check_unused_traits,
133        diagnostic_hir_wf_check: hir_wf_check::diagnostic_hir_wf_check,
134        inferred_outlives_crate: outlives::inferred_outlives_crate,
135        inferred_outlives_of: outlives::inferred_outlives_of,
136        inherit_sig_for_delegation_item: delegation::inherit_sig_for_delegation_item,
137        delegation_user_specified_args: delegation::delegation_user_specified_args,
138        enforce_impl_non_lifetime_params_are_constrained:
139            impl_wf_check::enforce_impl_non_lifetime_params_are_constrained,
140        crate_variances: variance::crate_variances,
141        variances_of: variance::variances_of,
142        ..*providers
143    };
144}
145
146pub fn check_crate(tcx: TyCtxt<'_>) {
147    let _prof_timer = tcx.sess.timer("type_check_crate");
148
149    tcx.sess.time("coherence_checking", || {
150        // When discarding query call results, use an explicit type to indicate
151        // what we are intending to discard, to help future type-based refactoring.
152        type R = Result<(), ErrorGuaranteed>;
153
154        let _: R = tcx.ensure_result().check_type_wf(());
155
156        for &trait_def_id in tcx.all_local_trait_impls(()).keys() {
157            let _: R = tcx.ensure_result().coherent_trait(trait_def_id);
158        }
159        // these queries are executed for side-effects (error reporting):
160        let _: R = tcx.ensure_result().crate_inherent_impls_validity_check(());
161        let _: R = tcx.ensure_result().crate_inherent_impls_overlap_check(());
162    });
163
164    tcx.par_hir_body_owners(|item_def_id| {
165        let def_kind = tcx.def_kind(item_def_id);
166        // Make sure we evaluate all static and (non-associated) const items, even if unused.
167        // If any of these fail to evaluate, we do not want this crate to pass compilation.
168        match def_kind {
169            DefKind::Static { .. } => {
170                tcx.ensure_ok().eval_static_initializer(item_def_id);
171                check::maybe_check_static_with_link_section(tcx, item_def_id);
172            }
173            DefKind::Const
174                if !tcx.generics_of(item_def_id).own_requires_monomorphization()
175                    && tcx.const_of_item(item_def_id).is_none() =>
176            {
177                // FIXME(generic_const_items): Passing empty instead of identity args is fishy but
178                //                             seems to be fine for now. Revisit this!
179                let instance = ty::Instance::new_raw(item_def_id.into(), ty::GenericArgs::empty());
180                let cid = GlobalId { instance, promoted: None };
181                let typing_env = ty::TypingEnv::fully_monomorphized();
182                tcx.ensure_ok().eval_to_const_value_raw(typing_env.as_query_input(cid));
183            }
184            _ => (),
185        }
186        // Skip `AnonConst`s and type system `InlineConst`s because we feed their `type_of` in
187        // `feed_anon_const_type`.
188        // Also skip items for which typeck forwards to parent typeck.
189        if !(def_kind == DefKind::AnonConst
190            && tcx.anon_const_kind(item_def_id) != ty::AnonConstKind::NonTypeSystemInline
191            || tcx.is_typeck_child(item_def_id.to_def_id()))
192        {
193            tcx.ensure_ok().typeck(item_def_id);
194        }
195    });
196
197    // This has to be a second pass over the body owners, after every body has been
198    // type-checked above. `needs_coroutine_by_move_body_def_id` asks for `type_of`, and for a
199    // body owner nested inside a const argument's anon const that goes through `typeck` of the
200    // anon const, which needs the anon const's own type. That type is never computed, only fed
201    // while the enclosing body is type-checked. Doing this in the pass above lets the parallel
202    // front end reach the nested body owner first, computing (and caching) an error type for
203    // the anon const that then conflicts with the type fed later on.
204    //
205    // This must not be parallelized since `coroutine_by_move_body_def_id` creates new `DefId`-s
206    // inside, which must be done in deterministic order to have reproducible binaries.
207    tcx.hir_body_owners().for_each(|item_def_id| {
208        // Ensure we generate the new `DefId` before finishing `check_crate`.
209        // Afterwards we freeze the list of `DefId`s.
210        if tcx.needs_coroutine_by_move_body_def_id(item_def_id.to_def_id()) {
211            tcx.ensure_done().coroutine_by_move_body_def_id(item_def_id);
212        }
213    });
214
215    if tcx.features().rustc_attrs() {
216        tcx.sess.time("dumping_rustc_attr_data", || {
217            // tidy-alphabetical-start
218            collect::dump::clauses_and_item_bounds(tcx);
219            collect::dump::def_parents(tcx);
220            collect::dump::generics(tcx);
221            collect::dump::object_lifetime_defaults(tcx);
222            collect::dump::opaque_hidden_types(tcx);
223            collect::dump::vtables(tcx);
224            outlives::dump::inferred_outlives(tcx);
225            variance::dump::variances(tcx);
226            // tidy-alphabetical-end
227        });
228    }
229
230    tcx.ensure_ok().check_unused_traits(());
231}
232
233/// Lower a [`hir::Ty`] to a [`Ty`].
234///
235/// <div class="warning">
236///
237/// This function is **quasi-deprecated**. It can cause ICEs if called inside of a body
238/// (of a function or constant) and especially if it contains inferred types (`_`).
239///
240/// It's used in rustdoc and Clippy.
241///
242/// </div>
243pub fn lower_ty<'tcx>(tcx: TyCtxt<'tcx>, hir_ty: &hir::Ty<'_>) -> Ty<'tcx> {
244    // In case there are any projections, etc., find the "environment"
245    // def-ID that will be used to determine the traits/predicates in
246    // scope. This is derived from the enclosing item-like thing.
247    let env_def_id = tcx.hir_get_parent_item(hir_ty.hir_id);
248    collect::ItemCtxt::new(tcx, env_def_id.def_id)
249        .lowerer()
250        .lower_ty_maybe_return_type_notation(hir_ty)
251}
252
253/// This is for rustdoc.
254// FIXME(const_generics): having special methods for rustdoc in `rustc_hir_analysis` is cursed
255pub fn lower_const_arg_for_rustdoc<'tcx>(
256    tcx: TyCtxt<'tcx>,
257    hir_ct: &hir::ConstArg<'_>,
258    ty: Ty<'tcx>,
259) -> Const<'tcx> {
260    let env_def_id = tcx.hir_get_parent_item(hir_ct.hir_id);
261    collect::ItemCtxt::new(tcx, env_def_id.def_id).lowerer().lower_const_arg(hir_ct, ty)
262}