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(coroutines)]
66#![feature(debug_closure_helpers)]
67#![feature(if_let_guard)]
68#![feature(iter_from_coroutine)]
69#![feature(iter_intersperse)]
70#![feature(let_chains)]
71#![feature(never_type)]
72#![feature(rustdoc_internals)]
73#![feature(slice_partition_dedup)]
74#![feature(try_blocks)]
75#![feature(unwrap_infallible)]
76#![warn(unreachable_pub)]
77// tidy-alphabetical-end
78
79// These are used by Clippy.
80pub mod check;
81
82pub mod autoderef;
83mod bounds;
84mod check_unused;
85mod coherence;
86mod collect;
87mod constrained_generic_params;
88mod delegation;
89mod errors;
90pub mod hir_ty_lowering;
91pub mod hir_wf_check;
92mod impl_wf_check;
93mod outlives;
94mod variance;
95
96use rustc_abi::ExternAbi;
97use rustc_hir as hir;
98use rustc_hir::def::DefKind;
99use rustc_middle::middle;
100use rustc_middle::mir::interpret::GlobalId;
101use rustc_middle::query::Providers;
102use rustc_middle::ty::{self, Const, Ty, TyCtxt};
103use rustc_session::parse::feature_err;
104use rustc_span::symbol::sym;
105use rustc_span::{ErrorGuaranteed, Span};
106use rustc_trait_selection::traits;
107
108pub use crate::collect::suggest_impl_trait;
109use crate::hir_ty_lowering::{FeedConstTy, HirTyLowerer};
110
111rustc_fluent_macro::fluent_messages! { "../messages.ftl" }
112
113fn require_c_abi_if_c_variadic(
114    tcx: TyCtxt<'_>,
115    decl: &hir::FnDecl<'_>,
116    abi: ExternAbi,
117    span: Span,
118) {
119    const CONVENTIONS_UNSTABLE: &str =
120        "`C`, `cdecl`, `system`, `aapcs`, `win64`, `sysv64` or `efiapi`";
121    const CONVENTIONS_STABLE: &str = "`C` or `cdecl`";
122    const UNSTABLE_EXPLAIN: &str =
123        "using calling conventions other than `C` or `cdecl` for varargs functions is unstable";
124
125    // ABIs which can stably use varargs
126    if !decl.c_variadic || matches!(abi, ExternAbi::C { .. } | ExternAbi::Cdecl { .. }) {
127        return;
128    }
129
130    // ABIs with feature-gated stability
131    let extended_abi_support = tcx.features().extended_varargs_abi_support();
132    let extern_system_varargs = tcx.features().extern_system_varargs();
133
134    // If the feature gate has been enabled, we can stop here
135    if extern_system_varargs && let ExternAbi::System { .. } = abi {
136        return;
137    };
138    if extended_abi_support && abi.supports_varargs() {
139        return;
140    };
141
142    // Looks like we need to pick an error to emit.
143    // Is there any feature which we could have enabled to make this work?
144    match abi {
145        ExternAbi::System { .. } => {
146            feature_err(&tcx.sess, sym::extern_system_varargs, span, UNSTABLE_EXPLAIN)
147        }
148        abi if abi.supports_varargs() => {
149            feature_err(&tcx.sess, sym::extended_varargs_abi_support, span, UNSTABLE_EXPLAIN)
150        }
151        _ => tcx.dcx().create_err(errors::VariadicFunctionCompatibleConvention {
152            span,
153            conventions: if tcx.sess.opts.unstable_features.is_nightly_build() {
154                CONVENTIONS_UNSTABLE
155            } else {
156                CONVENTIONS_STABLE
157            },
158        }),
159    }
160    .emit();
161}
162
163pub fn provide(providers: &mut Providers) {
164    collect::provide(providers);
165    coherence::provide(providers);
166    check::provide(providers);
167    check_unused::provide(providers);
168    variance::provide(providers);
169    outlives::provide(providers);
170    hir_wf_check::provide(providers);
171    *providers = Providers {
172        inherit_sig_for_delegation_item: delegation::inherit_sig_for_delegation_item,
173        enforce_impl_non_lifetime_params_are_constrained:
174            impl_wf_check::enforce_impl_non_lifetime_params_are_constrained,
175        ..*providers
176    };
177}
178
179pub fn check_crate(tcx: TyCtxt<'_>) {
180    let _prof_timer = tcx.sess.timer("type_check_crate");
181
182    tcx.sess.time("coherence_checking", || {
183        // When discarding query call results, use an explicit type to indicate
184        // what we are intending to discard, to help future type-based refactoring.
185        type R = Result<(), ErrorGuaranteed>;
186
187        tcx.hir().par_for_each_module(|module| {
188            let _: R = tcx.ensure_ok().check_mod_type_wf(module);
189        });
190
191        for &trait_def_id in tcx.all_local_trait_impls(()).keys() {
192            let _: R = tcx.ensure_ok().coherent_trait(trait_def_id);
193        }
194        // these queries are executed for side-effects (error reporting):
195        let _: R = tcx.ensure_ok().crate_inherent_impls_validity_check(());
196        let _: R = tcx.ensure_ok().crate_inherent_impls_overlap_check(());
197    });
198
199    if tcx.features().rustc_attrs() {
200        tcx.sess.time("dumping_rustc_attr_data", || {
201            outlives::dump::inferred_outlives(tcx);
202            variance::dump::variances(tcx);
203            collect::dump::opaque_hidden_types(tcx);
204            collect::dump::predicates_and_item_bounds(tcx);
205            collect::dump::def_parents(tcx);
206            collect::dump::vtables(tcx);
207        });
208    }
209
210    // Make sure we evaluate all static and (non-associated) const items, even if unused.
211    // If any of these fail to evaluate, we do not want this crate to pass compilation.
212    tcx.hir().par_body_owners(|item_def_id| {
213        let def_kind = tcx.def_kind(item_def_id);
214        match def_kind {
215            DefKind::Static { .. } => tcx.ensure_ok().eval_static_initializer(item_def_id),
216            DefKind::Const if tcx.generics_of(item_def_id).is_empty() => {
217                let instance = ty::Instance::new(item_def_id.into(), ty::GenericArgs::empty());
218                let cid = GlobalId { instance, promoted: None };
219                let typing_env = ty::TypingEnv::fully_monomorphized();
220                tcx.ensure_ok().eval_to_const_value_raw(typing_env.as_query_input(cid));
221            }
222            _ => (),
223        }
224    });
225
226    // FIXME: Remove this when we implement creating `DefId`s
227    // for anon constants during their parents' typeck.
228    // Typeck all body owners in parallel will produce queries
229    // cycle errors because it may typeck on anon constants directly.
230    tcx.hir().par_body_owners(|item_def_id| {
231        let def_kind = tcx.def_kind(item_def_id);
232        if !matches!(def_kind, DefKind::AnonConst) {
233            tcx.ensure_ok().typeck(item_def_id);
234        }
235    });
236
237    tcx.ensure_ok().check_unused_traits(());
238}
239
240/// Lower a [`hir::Ty`] to a [`Ty`].
241///
242/// <div class="warning">
243///
244/// This function is **quasi-deprecated**. It can cause ICEs if called inside of a body
245/// (of a function or constant) and especially if it contains inferred types (`_`).
246///
247/// It's used in rustdoc and Clippy.
248///
249/// </div>
250pub fn lower_ty<'tcx>(tcx: TyCtxt<'tcx>, hir_ty: &hir::Ty<'tcx>) -> Ty<'tcx> {
251    // In case there are any projections, etc., find the "environment"
252    // def-ID that will be used to determine the traits/predicates in
253    // scope. This is derived from the enclosing item-like thing.
254    let env_def_id = tcx.hir().get_parent_item(hir_ty.hir_id);
255    collect::ItemCtxt::new(tcx, env_def_id.def_id).lower_ty(hir_ty)
256}
257
258/// This is for rustdoc.
259// FIXME(const_generics): having special methods for rustdoc in `rustc_hir_analysis` is cursed
260pub fn lower_const_arg_for_rustdoc<'tcx>(
261    tcx: TyCtxt<'tcx>,
262    hir_ct: &hir::ConstArg<'tcx>,
263    feed: FeedConstTy,
264) -> Const<'tcx> {
265    let env_def_id = tcx.hir().get_parent_item(hir_ct.hir_id);
266    collect::ItemCtxt::new(tcx, env_def_id.def_id).lowerer().lower_const_arg(hir_ct, feed)
267}