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