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