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(assert_matches))]
60#![feature(default_field_values)]
61#![feature(gen_blocks)]
62#![feature(if_let_guard)]
63#![feature(iter_intersperse)]
64#![feature(never_type)]
65#![feature(slice_partition_dedup)]
66#![feature(try_blocks)]
67#![feature(unwrap_infallible)]
68// tidy-alphabetical-end
69
70// These are used by Clippy.
71pub mod check;
72
73pub mod autoderef;
74mod check_unused;
75mod coherence;
76mod collect;
77mod constrained_generic_params;
78mod delegation;
79pub mod errors;
80pub mod hir_ty_lowering;
81pub mod hir_wf_check;
82mod impl_wf_check;
83mod outlives;
84mod variance;
85
86pub use errors::NoVariantNamed;
87use rustc_abi::{CVariadicStatus, ExternAbi};
88use rustc_hir as hir;
89use rustc_hir::def::DefKind;
90use rustc_hir::lints::DelayedLint;
91use rustc_middle::mir::interpret::GlobalId;
92use rustc_middle::query::Providers;
93use rustc_middle::ty::{Const, Ty, TyCtxt};
94use rustc_middle::{middle, ty};
95use rustc_session::parse::feature_err;
96use rustc_span::{ErrorGuaranteed, Span};
97use rustc_trait_selection::traits;
98
99pub use crate::collect::suggest_impl_trait;
100use crate::hir_ty_lowering::HirTyLowerer;
101
102fn check_c_variadic_abi(tcx: TyCtxt<'_>, decl: &hir::FnDecl<'_>, abi: ExternAbi, span: Span) {
103    if !decl.c_variadic {
104        // Not even a variadic function.
105        return;
106    }
107
108    match abi.supports_c_variadic() {
109        CVariadicStatus::Stable => {}
110        CVariadicStatus::NotSupported => {
111            tcx.dcx()
112                .create_err(errors::VariadicFunctionCompatibleConvention {
113                    span,
114                    convention: &::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("{0}", abi))
    })format!("{abi}"),
115                })
116                .emit();
117        }
118        CVariadicStatus::Unstable { feature } => {
119            if !tcx.features().enabled(feature) {
120                feature_err(
121                    &tcx.sess,
122                    feature,
123                    span,
124                    ::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"),
125                )
126                .emit();
127            }
128        }
129    }
130}
131
132/// Adds query implementations to the [Providers] vtable, see [`rustc_middle::query`]
133pub fn provide(providers: &mut Providers) {
134    collect::provide(providers);
135    coherence::provide(providers);
136    check::provide(providers);
137    *providers = Providers {
138        check_unused_traits: check_unused::check_unused_traits,
139        diagnostic_hir_wf_check: hir_wf_check::diagnostic_hir_wf_check,
140        inferred_outlives_crate: outlives::inferred_outlives_crate,
141        inferred_outlives_of: outlives::inferred_outlives_of,
142        inherit_sig_for_delegation_item: delegation::inherit_sig_for_delegation_item,
143        enforce_impl_non_lifetime_params_are_constrained:
144            impl_wf_check::enforce_impl_non_lifetime_params_are_constrained,
145        crate_variances: variance::crate_variances,
146        variances_of: variance::variances_of,
147        ..*providers
148    };
149}
150
151fn emit_delayed_lint(lint: &DelayedLint, tcx: TyCtxt<'_>) {
152    match lint {
153        DelayedLint::AttributeParsing(attribute_lint) => {
154            tcx.node_span_lint(
155                attribute_lint.lint_id.lint,
156                attribute_lint.id,
157                attribute_lint.span,
158                |diag| {
159                    rustc_lint::decorate_attribute_lint(
160                        tcx.sess,
161                        Some(tcx),
162                        &attribute_lint.kind,
163                        diag,
164                    );
165                },
166            );
167        }
168    }
169}
170
171pub fn check_crate(tcx: TyCtxt<'_>) {
172    let _prof_timer = tcx.sess.timer("type_check_crate");
173
174    tcx.sess.time("coherence_checking", || {
175        // When discarding query call results, use an explicit type to indicate
176        // what we are intending to discard, to help future type-based refactoring.
177        type R = Result<(), ErrorGuaranteed>;
178
179        let _: R = tcx.ensure_ok().check_type_wf(());
180
181        for &trait_def_id in tcx.all_local_trait_impls(()).keys() {
182            let _: R = tcx.ensure_ok().coherent_trait(trait_def_id);
183        }
184        // these queries are executed for side-effects (error reporting):
185        let _: R = tcx.ensure_ok().crate_inherent_impls_validity_check(());
186        let _: R = tcx.ensure_ok().crate_inherent_impls_overlap_check(());
187    });
188
189    tcx.sess.time("emit_ast_lowering_delayed_lints", || {
190        // sanity check in debug mode that all lints are really noticed
191        // and we really will emit them all in the loop right below.
192        //
193        // during ast lowering, when creating items, foreign items, trait items and impl items
194        // we store in them whether they have any lints in their owner node that should be
195        // picked up by `hir_crate_items`. However, theoretically code can run between that
196        // boolean being inserted into the item and the owner node being created.
197        // We don't want any new lints to be emitted there
198        // (though honestly, you have to really try to manage to do that but still),
199        // but this check is there to catch that.
200        #[cfg(debug_assertions)]
201        {
202            // iterate over all owners
203            for owner_id in tcx.hir_crate_items(()).owners() {
204                // if it has delayed lints
205                if let Some(delayed_lints) = tcx.opt_ast_lowering_delayed_lints(owner_id) {
206                    if !delayed_lints.lints.is_empty() {
207                        // assert that delayed_lint_items also picked up this item to have lints
208                        if !tcx.hir_crate_items(()).delayed_lint_items().any(|i| i == owner_id) {
    ::core::panicking::panic("assertion failed: tcx.hir_crate_items(()).delayed_lint_items().any(|i| i == owner_id)")
};assert!(
209                            tcx.hir_crate_items(()).delayed_lint_items().any(|i| i == owner_id)
210                        );
211                    }
212                }
213            }
214        }
215
216        for owner_id in tcx.hir_crate_items(()).delayed_lint_items() {
217            if let Some(delayed_lints) = tcx.opt_ast_lowering_delayed_lints(owner_id) {
218                for lint in &delayed_lints.lints {
219                    emit_delayed_lint(lint, tcx);
220                }
221            }
222        }
223    });
224
225    tcx.par_hir_body_owners(|item_def_id| {
226        let def_kind = tcx.def_kind(item_def_id);
227        // Make sure we evaluate all static and (non-associated) const items, even if unused.
228        // If any of these fail to evaluate, we do not want this crate to pass compilation.
229        match def_kind {
230            DefKind::Static { .. } => {
231                tcx.ensure_ok().eval_static_initializer(item_def_id);
232                check::maybe_check_static_with_link_section(tcx, item_def_id);
233            }
234            DefKind::Const
235                if !tcx.generics_of(item_def_id).own_requires_monomorphization()
236                    && !tcx.is_type_const(item_def_id) =>
237            {
238                // FIXME(generic_const_items): Passing empty instead of identity args is fishy but
239                //                             seems to be fine for now. Revisit this!
240                let instance = ty::Instance::new_raw(item_def_id.into(), ty::GenericArgs::empty());
241                let cid = GlobalId { instance, promoted: None };
242                let typing_env = ty::TypingEnv::fully_monomorphized();
243                tcx.ensure_ok().eval_to_const_value_raw(typing_env.as_query_input(cid));
244            }
245            _ => (),
246        }
247        // Skip `AnonConst`s because we feed their `type_of`.
248        // Also skip items for which typeck forwards to parent typeck.
249        if !(#[allow(non_exhaustive_omitted_patterns)] match def_kind {
    DefKind::AnonConst => true,
    _ => false,
}matches!(def_kind, DefKind::AnonConst) || def_kind.is_typeck_child()) {
250            tcx.ensure_ok().typeck(item_def_id);
251        }
252        // Ensure we generate the new `DefId` before finishing `check_crate`.
253        // Afterwards we freeze the list of `DefId`s.
254        if tcx.needs_coroutine_by_move_body_def_id(item_def_id.to_def_id()) {
255            tcx.ensure_done().coroutine_by_move_body_def_id(item_def_id);
256        }
257    });
258
259    if tcx.features().rustc_attrs() {
260        tcx.sess.time("dumping_rustc_attr_data", || {
261            outlives::dump::inferred_outlives(tcx);
262            variance::dump::variances(tcx);
263            collect::dump::opaque_hidden_types(tcx);
264            collect::dump::predicates_and_item_bounds(tcx);
265            collect::dump::def_parents(tcx);
266            collect::dump::vtables(tcx);
267        });
268    }
269
270    tcx.ensure_ok().check_unused_traits(());
271}
272
273/// Lower a [`hir::Ty`] to a [`Ty`].
274///
275/// <div class="warning">
276///
277/// This function is **quasi-deprecated**. It can cause ICEs if called inside of a body
278/// (of a function or constant) and especially if it contains inferred types (`_`).
279///
280/// It's used in rustdoc and Clippy.
281///
282/// </div>
283pub fn lower_ty<'tcx>(tcx: TyCtxt<'tcx>, hir_ty: &hir::Ty<'tcx>) -> Ty<'tcx> {
284    // In case there are any projections, etc., find the "environment"
285    // def-ID that will be used to determine the traits/predicates in
286    // scope. This is derived from the enclosing item-like thing.
287    let env_def_id = tcx.hir_get_parent_item(hir_ty.hir_id);
288    collect::ItemCtxt::new(tcx, env_def_id.def_id)
289        .lowerer()
290        .lower_ty_maybe_return_type_notation(hir_ty)
291}
292
293/// This is for rustdoc.
294// FIXME(const_generics): having special methods for rustdoc in `rustc_hir_analysis` is cursed
295pub fn lower_const_arg_for_rustdoc<'tcx>(
296    tcx: TyCtxt<'tcx>,
297    hir_ct: &hir::ConstArg<'tcx>,
298    ty: Ty<'tcx>,
299) -> Const<'tcx> {
300    let env_def_id = tcx.hir_get_parent_item(hir_ct.hir_id);
301    collect::ItemCtxt::new(tcx, env_def_id.def_id).lowerer().lower_const_arg(hir_ct, ty)
302}