#![allow(rustc::potential_query_instability)]
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
#![feature(box_patterns)]
#![feature(control_flow_enum)]
#![feature(if_let_guard)]
#![feature(is_sorted)]
#![feature(iter_intersperse)]
#![feature(let_chains)]
#![feature(min_specialization)]
#![feature(never_type)]
#![feature(lazy_cell)]
#![feature(slice_partition_dedup)]
#![feature(try_blocks)]
#![feature(type_alias_impl_trait)]
#![recursion_limit = "256"]
#[macro_use]
extern crate tracing;
#[macro_use]
extern crate rustc_middle;
pub mod check;
pub mod astconv;
pub mod autoderef;
mod bounds;
mod check_unused;
mod coherence;
pub mod collect;
mod constrained_generic_params;
mod errors;
pub mod hir_wf_check;
mod impl_wf_check;
mod outlives;
pub mod structured_errors;
mod variance;
use rustc_errors::ErrorGuaranteed;
use rustc_errors::{DiagnosticMessage, SubdiagnosticMessage};
use rustc_fluent_macro::fluent_messages;
use rustc_hir as hir;
use rustc_infer::infer::TyCtxtInferExt;
use rustc_middle::middle;
use rustc_middle::query::Providers;
use rustc_middle::ty::{self, Ty, TyCtxt};
use rustc_middle::util;
use rustc_session::parse::feature_err;
use rustc_span::{symbol::sym, Span, DUMMY_SP};
use rustc_target::spec::abi::Abi;
use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt as _;
use rustc_trait_selection::traits::{self, ObligationCause, ObligationCtxt};
use astconv::{AstConv, OnlySelfBounds};
use bounds::Bounds;
use rustc_hir::def::DefKind;
fluent_messages! { "../messages.ftl" }
fn require_c_abi_if_c_variadic(tcx: TyCtxt<'_>, decl: &hir::FnDecl<'_>, abi: Abi, span: Span) {
const CONVENTIONS_UNSTABLE: &str = "`C`, `cdecl`, `win64`, `sysv64` or `efiapi`";
const CONVENTIONS_STABLE: &str = "`C` or `cdecl`";
const UNSTABLE_EXPLAIN: &str =
"using calling conventions other than `C` or `cdecl` for varargs functions is unstable";
if !decl.c_variadic || matches!(abi, Abi::C { .. } | Abi::Cdecl { .. }) {
return;
}
let extended_abi_support = tcx.features().extended_varargs_abi_support;
let conventions = match (extended_abi_support, abi.supports_varargs()) {
(true, true) => return,
(false, true) => {
feature_err(
&tcx.sess.parse_sess,
sym::extended_varargs_abi_support,
span,
UNSTABLE_EXPLAIN,
)
.emit();
CONVENTIONS_STABLE
}
(false, false) => CONVENTIONS_STABLE,
(true, false) => CONVENTIONS_UNSTABLE,
};
tcx.sess.emit_err(errors::VariadicFunctionCompatibleConvention { span, conventions });
}
fn require_same_types<'tcx>(
tcx: TyCtxt<'tcx>,
cause: &ObligationCause<'tcx>,
param_env: ty::ParamEnv<'tcx>,
expected: Ty<'tcx>,
actual: Ty<'tcx>,
) {
let infcx = &tcx.infer_ctxt().build();
let ocx = ObligationCtxt::new(infcx);
match ocx.eq(cause, param_env, expected, actual) {
Ok(()) => {
let errors = ocx.select_all_or_error();
if !errors.is_empty() {
infcx.err_ctxt().report_fulfillment_errors(&errors);
}
}
Err(err) => {
infcx.err_ctxt().report_mismatched_types(cause, expected, actual, err).emit();
}
}
}
pub fn provide(providers: &mut Providers) {
collect::provide(providers);
coherence::provide(providers);
check::provide(providers);
check_unused::provide(providers);
variance::provide(providers);
outlives::provide(providers);
impl_wf_check::provide(providers);
hir_wf_check::provide(providers);
}
pub fn check_crate(tcx: TyCtxt<'_>) -> Result<(), ErrorGuaranteed> {
let _prof_timer = tcx.sess.timer("type_check_crate");
tcx.sess.track_errors(|| {
tcx.sess.time("type_collecting", || {
tcx.hir().for_each_module(|module| tcx.ensure().collect_mod_item_types(module))
});
})?;
if tcx.features().rustc_attrs {
tcx.sess.track_errors(|| {
tcx.sess.time("outlives_testing", || outlives::test::test_inferred_outlives(tcx));
})?;
}
tcx.sess.track_errors(|| {
tcx.sess.time("impl_wf_inference", || {
tcx.hir().for_each_module(|module| tcx.ensure().check_mod_impl_wf(module))
});
})?;
tcx.sess.track_errors(|| {
tcx.sess.time("coherence_checking", || {
for &trait_def_id in tcx.all_local_trait_impls(()).keys() {
tcx.ensure().coherent_trait(trait_def_id);
}
tcx.ensure().crate_inherent_impls(());
tcx.ensure().crate_inherent_impls_overlap_check(());
});
})?;
if tcx.features().rustc_attrs {
tcx.sess.track_errors(|| {
tcx.sess.time("variance_testing", || variance::test::test_variance(tcx));
})?;
}
tcx.sess.track_errors(|| {
tcx.sess.time("wf_checking", || {
tcx.hir().par_for_each_module(|module| tcx.ensure().check_mod_type_wf(module))
});
})?;
tcx.sess.time("item_types_checking", || {
tcx.hir().for_each_module(|module| tcx.ensure().check_mod_item_types(module))
});
tcx.hir().par_body_owners(|item_def_id| {
let def_kind = tcx.def_kind(item_def_id);
if !matches!(def_kind, DefKind::AnonConst) {
tcx.ensure().typeck(item_def_id);
}
});
tcx.ensure().check_unused_traits(());
if let Some(reported) = tcx.sess.has_errors() { Err(reported) } else { Ok(()) }
}
pub fn hir_ty_to_ty<'tcx>(tcx: TyCtxt<'tcx>, hir_ty: &hir::Ty<'_>) -> Ty<'tcx> {
let env_def_id = tcx.hir().get_parent_item(hir_ty.hir_id);
let item_cx = self::collect::ItemCtxt::new(tcx, env_def_id.def_id);
item_cx.astconv().ast_ty_to_ty(hir_ty)
}
pub fn hir_trait_to_predicates<'tcx>(
tcx: TyCtxt<'tcx>,
hir_trait: &hir::TraitRef<'_>,
self_ty: Ty<'tcx>,
) -> Bounds<'tcx> {
let env_def_id = tcx.hir().get_parent_item(hir_trait.hir_ref_id);
let item_cx = self::collect::ItemCtxt::new(tcx, env_def_id.def_id);
let mut bounds = Bounds::default();
let _ = &item_cx.astconv().instantiate_poly_trait_ref(
hir_trait,
DUMMY_SP,
ty::BoundConstness::NotConst,
ty::ImplPolarity::Positive,
self_ty,
&mut bounds,
true,
OnlySelfBounds(false),
);
bounds
}