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