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