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#![cfg_attr(bootstrap, feature(let_chains))]
63#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
64#![doc(rust_logo)]
65#![feature(assert_matches)]
66#![feature(coroutines)]
67#![feature(debug_closure_helpers)]
68#![feature(if_let_guard)]
69#![feature(iter_from_coroutine)]
70#![feature(iter_intersperse)]
71#![feature(never_type)]
72#![feature(rustdoc_internals)]
73#![feature(slice_partition_dedup)]
74#![feature(try_blocks)]
75#![feature(unwrap_infallible)]
76// tidy-alphabetical-end
77
78// These are used by Clippy.
79pub mod check;
80
81pub mod autoderef;
82mod check_unused;
83mod coherence;
84mod collect;
85mod constrained_generic_params;
86mod delegation;
87mod errors;
88pub mod hir_ty_lowering;
89pub mod hir_wf_check;
90mod impl_wf_check;
91mod outlives;
92mod variance;
93
94pub use errors::NoVariantNamed;
95use rustc_abi::ExternAbi;
96use rustc_hir as hir;
97use rustc_hir::def::DefKind;
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    const CONVENTIONS_UNSTABLE: &str =
119        "`C`, `cdecl`, `system`, `aapcs`, `win64`, `sysv64` or `efiapi`";
120    const CONVENTIONS_STABLE: &str = "`C` or `cdecl`";
121    const UNSTABLE_EXPLAIN: &str =
122        "using calling conventions other than `C` or `cdecl` for varargs functions is unstable";
123
124    // ABIs which can stably use varargs
125    if !decl.c_variadic || matches!(abi, ExternAbi::C { .. } | ExternAbi::Cdecl { .. }) {
126        return;
127    }
128
129    // ABIs with feature-gated stability
130    let extended_abi_support = tcx.features().extended_varargs_abi_support();
131    let extern_system_varargs = tcx.features().extern_system_varargs();
132
133    // If the feature gate has been enabled, we can stop here
134    if extern_system_varargs && let ExternAbi::System { .. } = abi {
135        return;
136    };
137    if extended_abi_support && abi.supports_varargs() {
138        return;
139    };
140
141    // Looks like we need to pick an error to emit.
142    // Is there any feature which we could have enabled to make this work?
143    match abi {
144        ExternAbi::System { .. } => {
145            feature_err(&tcx.sess, sym::extern_system_varargs, span, UNSTABLE_EXPLAIN)
146        }
147        abi if abi.supports_varargs() => {
148            feature_err(&tcx.sess, sym::extended_varargs_abi_support, span, UNSTABLE_EXPLAIN)
149        }
150        _ => tcx.dcx().create_err(errors::VariadicFunctionCompatibleConvention {
151            span,
152            conventions: if tcx.sess.opts.unstable_features.is_nightly_build() {
153                CONVENTIONS_UNSTABLE
154            } else {
155                CONVENTIONS_STABLE
156            },
157        }),
158    }
159    .emit();
160}
161
162pub fn provide(providers: &mut Providers) {
163    collect::provide(providers);
164    coherence::provide(providers);
165    check::provide(providers);
166    check_unused::provide(providers);
167    variance::provide(providers);
168    outlives::provide(providers);
169    hir_wf_check::provide(providers);
170    *providers = Providers {
171        inherit_sig_for_delegation_item: delegation::inherit_sig_for_delegation_item,
172        enforce_impl_non_lifetime_params_are_constrained:
173            impl_wf_check::enforce_impl_non_lifetime_params_are_constrained,
174        ..*providers
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        tcx.par_hir_for_each_module(|module| {
187            let _: R = tcx.ensure_ok().check_mod_type_wf(module);
188        });
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    if tcx.features().rustc_attrs() {
199        tcx.sess.time("dumping_rustc_attr_data", || {
200            outlives::dump::inferred_outlives(tcx);
201            variance::dump::variances(tcx);
202            collect::dump::opaque_hidden_types(tcx);
203            collect::dump::predicates_and_item_bounds(tcx);
204            collect::dump::def_parents(tcx);
205            collect::dump::vtables(tcx);
206        });
207    }
208
209    // Make sure we evaluate all static and (non-associated) const items, even if unused.
210    // If any of these fail to evaluate, we do not want this crate to pass compilation.
211    tcx.par_hir_body_owners(|item_def_id| {
212        let def_kind = tcx.def_kind(item_def_id);
213        match def_kind {
214            DefKind::Static { .. } => {
215                tcx.ensure_ok().eval_static_initializer(item_def_id);
216                check::maybe_check_static_with_link_section(tcx, item_def_id);
217            }
218            DefKind::Const if tcx.generics_of(item_def_id).is_empty() => {
219                let instance = ty::Instance::new_raw(item_def_id.into(), ty::GenericArgs::empty());
220                let cid = GlobalId { instance, promoted: None };
221                let typing_env = ty::TypingEnv::fully_monomorphized();
222                tcx.ensure_ok().eval_to_const_value_raw(typing_env.as_query_input(cid));
223            }
224            _ => (),
225        }
226    });
227
228    tcx.par_hir_body_owners(|item_def_id| {
229        let def_kind = tcx.def_kind(item_def_id);
230        // Skip `AnonConst`s because we feed their `type_of`.
231        if !matches!(def_kind, DefKind::AnonConst) {
232            tcx.ensure_ok().typeck(item_def_id);
233        }
234    });
235
236    tcx.ensure_ok().check_unused_traits(());
237}
238
239/// Lower a [`hir::Ty`] to a [`Ty`].
240///
241/// <div class="warning">
242///
243/// This function is **quasi-deprecated**. It can cause ICEs if called inside of a body
244/// (of a function or constant) and especially if it contains inferred types (`_`).
245///
246/// It's used in rustdoc and Clippy.
247///
248/// </div>
249pub fn lower_ty<'tcx>(tcx: TyCtxt<'tcx>, hir_ty: &hir::Ty<'tcx>) -> Ty<'tcx> {
250    // In case there are any projections, etc., find the "environment"
251    // def-ID that will be used to determine the traits/predicates in
252    // scope. This is derived from the enclosing item-like thing.
253    let env_def_id = tcx.hir_get_parent_item(hir_ty.hir_id);
254    collect::ItemCtxt::new(tcx, env_def_id.def_id)
255        .lowerer()
256        .lower_ty_maybe_return_type_notation(hir_ty)
257}
258
259/// This is for rustdoc.
260// FIXME(const_generics): having special methods for rustdoc in `rustc_hir_analysis` is cursed
261pub fn lower_const_arg_for_rustdoc<'tcx>(
262    tcx: TyCtxt<'tcx>,
263    hir_ct: &hir::ConstArg<'tcx>,
264    feed: FeedConstTy<'_, 'tcx>,
265) -> Const<'tcx> {
266    let env_def_id = tcx.hir_get_parent_item(hir_ct.hir_id);
267    collect::ItemCtxt::new(tcx, env_def_id.def_id).lowerer().lower_const_arg(hir_ct, feed)
268}