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