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