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(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 as hir;
96use rustc_hir::def::DefKind;
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    const CONVENTIONS_UNSTABLE: &str =
118        "`C`, `cdecl`, `system`, `aapcs`, `win64`, `sysv64` or `efiapi`";
119    const CONVENTIONS_STABLE: &str = "`C` or `cdecl`";
120    const UNSTABLE_EXPLAIN: &str =
121        "using calling conventions other than `C` or `cdecl` for varargs functions is unstable";
122
123    // ABIs which can stably use varargs
124    if !decl.c_variadic || matches!(abi, ExternAbi::C { .. } | ExternAbi::Cdecl { .. }) {
125        return;
126    }
127
128    // ABIs with feature-gated stability
129    let extended_abi_support = tcx.features().extended_varargs_abi_support();
130    let extern_system_varargs = tcx.features().extern_system_varargs();
131
132    // If the feature gate has been enabled, we can stop here
133    if extern_system_varargs && let ExternAbi::System { .. } = abi {
134        return;
135    };
136    if extended_abi_support && abi.supports_varargs() {
137        return;
138    };
139
140    // Looks like we need to pick an error to emit.
141    // Is there any feature which we could have enabled to make this work?
142    match abi {
143        ExternAbi::System { .. } => {
144            feature_err(&tcx.sess, sym::extern_system_varargs, span, UNSTABLE_EXPLAIN)
145        }
146        abi if abi.supports_varargs() => {
147            feature_err(&tcx.sess, sym::extended_varargs_abi_support, span, UNSTABLE_EXPLAIN)
148        }
149        _ => tcx.dcx().create_err(errors::VariadicFunctionCompatibleConvention {
150            span,
151            conventions: if tcx.sess.opts.unstable_features.is_nightly_build() {
152                CONVENTIONS_UNSTABLE
153            } else {
154                CONVENTIONS_STABLE
155            },
156        }),
157    }
158    .emit();
159}
160
161pub fn provide(providers: &mut Providers) {
162    collect::provide(providers);
163    coherence::provide(providers);
164    check::provide(providers);
165    check_unused::provide(providers);
166    variance::provide(providers);
167    outlives::provide(providers);
168    hir_wf_check::provide(providers);
169    *providers = Providers {
170        inherit_sig_for_delegation_item: delegation::inherit_sig_for_delegation_item,
171        enforce_impl_non_lifetime_params_are_constrained:
172            impl_wf_check::enforce_impl_non_lifetime_params_are_constrained,
173        ..*providers
174    };
175}
176
177pub fn check_crate(tcx: TyCtxt<'_>) {
178    let _prof_timer = tcx.sess.timer("type_check_crate");
179
180    tcx.sess.time("coherence_checking", || {
181        // When discarding query call results, use an explicit type to indicate
182        // what we are intending to discard, to help future type-based refactoring.
183        type R = Result<(), ErrorGuaranteed>;
184
185        tcx.par_hir_for_each_module(|module| {
186            let _: R = tcx.ensure_ok().check_mod_type_wf(module);
187        });
188
189        for &trait_def_id in tcx.all_local_trait_impls(()).keys() {
190            let _: R = tcx.ensure_ok().coherent_trait(trait_def_id);
191        }
192        // these queries are executed for side-effects (error reporting):
193        let _: R = tcx.ensure_ok().crate_inherent_impls_validity_check(());
194        let _: R = tcx.ensure_ok().crate_inherent_impls_overlap_check(());
195    });
196
197    // Make sure we evaluate all static and (non-associated) const items, even if unused.
198    // If any of these fail to evaluate, we do not want this crate to pass compilation.
199    tcx.par_hir_body_owners(|item_def_id| {
200        let def_kind = tcx.def_kind(item_def_id);
201        match def_kind {
202            DefKind::Static { .. } => {
203                tcx.ensure_ok().eval_static_initializer(item_def_id);
204                check::maybe_check_static_with_link_section(tcx, item_def_id);
205            }
206            DefKind::Const if tcx.generics_of(item_def_id).is_empty() => {
207                let instance = ty::Instance::new_raw(item_def_id.into(), ty::GenericArgs::empty());
208                let cid = GlobalId { instance, promoted: None };
209                let typing_env = ty::TypingEnv::fully_monomorphized();
210                tcx.ensure_ok().eval_to_const_value_raw(typing_env.as_query_input(cid));
211            }
212            _ => (),
213        }
214        // Skip `AnonConst`s because we feed their `type_of`.
215        if !matches!(def_kind, DefKind::AnonConst) {
216            tcx.ensure_ok().typeck(item_def_id);
217        }
218    });
219
220    if tcx.features().rustc_attrs() {
221        tcx.sess.time("dumping_rustc_attr_data", || {
222            outlives::dump::inferred_outlives(tcx);
223            variance::dump::variances(tcx);
224            collect::dump::opaque_hidden_types(tcx);
225            collect::dump::predicates_and_item_bounds(tcx);
226            collect::dump::def_parents(tcx);
227            collect::dump::vtables(tcx);
228        });
229    }
230
231    tcx.ensure_ok().check_unused_traits(());
232}
233
234/// Lower a [`hir::Ty`] to a [`Ty`].
235///
236/// <div class="warning">
237///
238/// This function is **quasi-deprecated**. It can cause ICEs if called inside of a body
239/// (of a function or constant) and especially if it contains inferred types (`_`).
240///
241/// It's used in rustdoc and Clippy.
242///
243/// </div>
244pub fn lower_ty<'tcx>(tcx: TyCtxt<'tcx>, hir_ty: &hir::Ty<'tcx>) -> Ty<'tcx> {
245    // In case there are any projections, etc., find the "environment"
246    // def-ID that will be used to determine the traits/predicates in
247    // scope. This is derived from the enclosing item-like thing.
248    let env_def_id = tcx.hir_get_parent_item(hir_ty.hir_id);
249    collect::ItemCtxt::new(tcx, env_def_id.def_id)
250        .lowerer()
251        .lower_ty_maybe_return_type_notation(hir_ty)
252}
253
254/// This is for rustdoc.
255// FIXME(const_generics): having special methods for rustdoc in `rustc_hir_analysis` is cursed
256pub fn lower_const_arg_for_rustdoc<'tcx>(
257    tcx: TyCtxt<'tcx>,
258    hir_ct: &hir::ConstArg<'tcx>,
259    feed: FeedConstTy<'_, 'tcx>,
260) -> Const<'tcx> {
261    let env_def_id = tcx.hir_get_parent_item(hir_ct.hir_id);
262    collect::ItemCtxt::new(tcx, env_def_id.def_id).lowerer().lower_const_arg(hir_ct, feed)
263}