summaryrefslogtreecommitdiffstats
path: root/compiler/rustc_hir_analysis/src/check
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-30 03:59:35 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-30 03:59:35 +0000
commitd1b2d29528b7794b41e66fc2136e395a02f8529b (patch)
treea4a17504b260206dec3cf55b2dca82929a348ac2 /compiler/rustc_hir_analysis/src/check
parentReleasing progress-linux version 1.72.1+dfsg1-1~progress7.99u1. (diff)
downloadrustc-d1b2d29528b7794b41e66fc2136e395a02f8529b.tar.xz
rustc-d1b2d29528b7794b41e66fc2136e395a02f8529b.zip
Merging upstream version 1.73.0+dfsg1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'compiler/rustc_hir_analysis/src/check')
-rw-r--r--compiler/rustc_hir_analysis/src/check/check.rs215
-rw-r--r--compiler/rustc_hir_analysis/src/check/compare_impl_item.rs396
-rw-r--r--compiler/rustc_hir_analysis/src/check/dropck.rs26
-rw-r--r--compiler/rustc_hir_analysis/src/check/entry.rs277
-rw-r--r--compiler/rustc_hir_analysis/src/check/intrinsic.rs34
-rw-r--r--compiler/rustc_hir_analysis/src/check/intrinsicck.rs18
-rw-r--r--compiler/rustc_hir_analysis/src/check/mod.rs25
-rw-r--r--compiler/rustc_hir_analysis/src/check/wfcheck.rs257
8 files changed, 813 insertions, 435 deletions
diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs
index 120545c8e..2c7788498 100644
--- a/compiler/rustc_hir_analysis/src/check/check.rs
+++ b/compiler/rustc_hir_analysis/src/check/check.rs
@@ -8,7 +8,7 @@ use rustc_attr as attr;
use rustc_errors::{Applicability, ErrorGuaranteed, MultiSpan};
use rustc_hir as hir;
use rustc_hir::def::{CtorKind, DefKind, Res};
-use rustc_hir::def_id::{DefId, LocalDefId};
+use rustc_hir::def_id::{DefId, LocalDefId, LocalModDefId};
use rustc_hir::intravisit::Visitor;
use rustc_hir::{ItemKind, Node, PathSegment};
use rustc_infer::infer::opaque_types::ConstrainOpaqueTypeRegionVisitor;
@@ -19,11 +19,13 @@ use rustc_lint_defs::builtin::REPR_TRANSPARENT_EXTERNAL_PRIVATE_FIELDS;
use rustc_middle::hir::nested_filter;
use rustc_middle::middle::stability::EvalResult;
use rustc_middle::traits::DefiningAnchor;
+use rustc_middle::ty::fold::BottomUpFolder;
use rustc_middle::ty::layout::{LayoutError, MAX_SIMD_LANES};
-use rustc_middle::ty::subst::GenericArgKind;
use rustc_middle::ty::util::{Discr, IntTypeExt};
+use rustc_middle::ty::GenericArgKind;
use rustc_middle::ty::{
- self, AdtDef, ParamEnv, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitableExt,
+ self, AdtDef, ParamEnv, RegionKind, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable,
+ TypeVisitableExt,
};
use rustc_session::lint::builtin::{UNINHABITED_STATIC, UNSUPPORTED_CALLING_CONVENTIONS};
use rustc_span::symbol::sym;
@@ -34,6 +36,7 @@ use rustc_trait_selection::traits::error_reporting::on_unimplemented::OnUnimplem
use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt as _;
use rustc_trait_selection::traits::outlives_bounds::InferCtxtExt as _;
use rustc_trait_selection::traits::{self, ObligationCtxt, TraitEngine, TraitEngineExt as _};
+use rustc_type_ir::fold::TypeFoldable;
use std::ops::ControlFlow;
@@ -96,8 +99,8 @@ fn check_union(tcx: TyCtxt<'_>, def_id: LocalDefId) {
/// Check that the fields of the `union` do not need dropping.
fn check_union_fields(tcx: TyCtxt<'_>, span: Span, item_def_id: LocalDefId) -> bool {
- let item_type = tcx.type_of(item_def_id).subst_identity();
- if let ty::Adt(def, substs) = item_type.kind() {
+ let item_type = tcx.type_of(item_def_id).instantiate_identity();
+ if let ty::Adt(def, args) = item_type.kind() {
assert!(def.is_union());
fn allowed_union_field<'tcx>(
@@ -128,7 +131,7 @@ fn check_union_fields(tcx: TyCtxt<'_>, span: Span, item_def_id: LocalDefId) -> b
let param_env = tcx.param_env(item_def_id);
for field in &def.non_enum_variant().fields {
- let field_ty = tcx.normalize_erasing_regions(param_env, field.ty(tcx, substs));
+ let field_ty = tcx.normalize_erasing_regions(param_env, field.ty(tcx, args));
if !allowed_union_field(field_ty, tcx, param_env) {
let (field_span, ty_span) = match tcx.hir().get_if_local(field.did) {
@@ -163,7 +166,7 @@ fn check_static_inhabited(tcx: TyCtxt<'_>, def_id: LocalDefId) {
// would be enough to check this for `extern` statics, as statics with an initializer will
// have UB during initialization if they are uninhabited, but there also seems to be no good
// reason to allow any statics to be uninhabited.
- let ty = tcx.type_of(def_id).subst_identity();
+ let ty = tcx.type_of(def_id).instantiate_identity();
let span = tcx.def_span(def_id);
let layout = match tcx.layout_of(ParamEnv::reveal_all().and(ty)) {
Ok(l) => l,
@@ -212,16 +215,16 @@ fn check_opaque(tcx: TyCtxt<'_>, id: hir::ItemId) {
return;
}
- let substs = InternalSubsts::identity_for_item(tcx, item.owner_id);
+ let args = GenericArgs::identity_for_item(tcx, item.owner_id);
let span = tcx.def_span(item.owner_id.def_id);
if !tcx.features().impl_trait_projections {
check_opaque_for_inheriting_lifetimes(tcx, item.owner_id.def_id, span);
}
- if tcx.type_of(item.owner_id.def_id).subst_identity().references_error() {
+ if tcx.type_of(item.owner_id.def_id).instantiate_identity().references_error() {
return;
}
- if check_opaque_for_cycles(tcx, item.owner_id.def_id, substs, span, &origin).is_err() {
+ if check_opaque_for_cycles(tcx, item.owner_id.def_id, args, span, &origin).is_err() {
return;
}
@@ -302,16 +305,11 @@ pub(super) fn check_opaque_for_inheriting_lifetimes(
if let ItemKind::OpaqueTy(&hir::OpaqueTy {
origin: hir::OpaqueTyOrigin::AsyncFn(..) | hir::OpaqueTyOrigin::FnReturn(..),
- in_trait,
..
}) = item.kind
{
- let substs = InternalSubsts::identity_for_item(tcx, def_id);
- let opaque_identity_ty = if in_trait && !tcx.lower_impl_trait_in_trait_to_assoc_ty() {
- Ty::new_projection(tcx, def_id.to_def_id(), substs)
- } else {
- Ty::new_opaque(tcx, def_id.to_def_id(), substs)
- };
+ let args = GenericArgs::identity_for_item(tcx, def_id);
+ let opaque_identity_ty = Ty::new_opaque(tcx, def_id.to_def_id(), args);
let mut visitor = ProhibitOpaqueVisitor {
opaque_identity_ty,
parent_count: tcx.generics_of(def_id).parent_count as u32,
@@ -321,7 +319,7 @@ pub(super) fn check_opaque_for_inheriting_lifetimes(
};
let prohibit_opaque = tcx
.explicit_item_bounds(def_id)
- .subst_identity_iter_copied()
+ .instantiate_identity_iter_copied()
.try_for_each(|(predicate, _)| predicate.visit_with(&mut visitor));
if let Some(ty) = prohibit_opaque.break_value() {
@@ -347,7 +345,7 @@ pub(super) fn check_opaque_for_inheriting_lifetimes(
err.span_suggestion(
span,
"consider spelling out the type instead",
- name.unwrap_or_else(|| format!("{:?}", ty)),
+ name.unwrap_or_else(|| format!("{ty:?}")),
Applicability::MaybeIncorrect,
);
}
@@ -360,11 +358,11 @@ pub(super) fn check_opaque_for_inheriting_lifetimes(
pub(super) fn check_opaque_for_cycles<'tcx>(
tcx: TyCtxt<'tcx>,
def_id: LocalDefId,
- substs: SubstsRef<'tcx>,
+ args: GenericArgsRef<'tcx>,
span: Span,
origin: &hir::OpaqueTyOrigin,
) -> Result<(), ErrorGuaranteed> {
- if tcx.try_expand_impl_trait_type(def_id.to_def_id(), substs).is_err() {
+ if tcx.try_expand_impl_trait_type(def_id.to_def_id(), args).is_err() {
let reported = match origin {
hir::OpaqueTyOrigin::AsyncFn(..) => async_opaque_type_cycle_error(tcx, span),
_ => opaque_type_cycle_error(tcx, def_id, span),
@@ -409,16 +407,26 @@ fn check_opaque_meets_bounds<'tcx>(
.build();
let ocx = ObligationCtxt::new(&infcx);
- let substs = InternalSubsts::identity_for_item(tcx, def_id.to_def_id());
- let opaque_ty = Ty::new_opaque(tcx, def_id.to_def_id(), substs);
+ let args = match *origin {
+ hir::OpaqueTyOrigin::FnReturn(parent) | hir::OpaqueTyOrigin::AsyncFn(parent) => {
+ GenericArgs::identity_for_item(tcx, parent).extend_to(
+ tcx,
+ def_id.to_def_id(),
+ |param, _| tcx.map_rpit_lifetime_to_fn_lifetime(param.def_id.expect_local()).into(),
+ )
+ }
+ hir::OpaqueTyOrigin::TyAlias { .. } => GenericArgs::identity_for_item(tcx, def_id),
+ };
+
+ let opaque_ty = Ty::new_opaque(tcx, def_id.to_def_id(), args);
- // `ReErased` regions appear in the "parent_substs" of closures/generators.
+ // `ReErased` regions appear in the "parent_args" of closures/generators.
// We're ignoring them here and replacing them with fresh region variables.
- // See tests in ui/type-alias-impl-trait/closure_{parent_substs,wf_outlives}.rs.
+ // See tests in ui/type-alias-impl-trait/closure_{parent_args,wf_outlives}.rs.
//
// FIXME: Consider wrapping the hidden type in an existential `Binder` and instantiating it
// here rather than using ReErased.
- let hidden_ty = tcx.type_of(def_id.to_def_id()).subst(tcx, substs);
+ let hidden_ty = tcx.type_of(def_id.to_def_id()).instantiate(tcx, args);
let hidden_ty = tcx.fold_regions(hidden_ty, |re, _dbi| match re.kind() {
ty::ReErased => infcx.next_region_var(RegionVariableOrigin::MiscVariable(span)),
_ => re,
@@ -442,7 +450,7 @@ fn check_opaque_meets_bounds<'tcx>(
// hidden type is well formed even without those bounds.
let predicate =
ty::Binder::dummy(ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(hidden_ty.into())));
- ocx.register_obligation(Obligation::new(tcx, misc_cause, param_env, predicate));
+ ocx.register_obligation(Obligation::new(tcx, misc_cause.clone(), param_env, predicate));
// Check that all obligations are satisfied by the implementation's
// version.
@@ -453,7 +461,15 @@ fn check_opaque_meets_bounds<'tcx>(
}
match origin {
// Checked when type checking the function containing them.
- hir::OpaqueTyOrigin::FnReturn(..) | hir::OpaqueTyOrigin::AsyncFn(..) => {}
+ hir::OpaqueTyOrigin::FnReturn(..) | hir::OpaqueTyOrigin::AsyncFn(..) => {
+ // HACK: this should also fall through to the hidden type check below, but the original
+ // implementation had a bug where equivalent lifetimes are not identical. This caused us
+ // to reject existing stable code that is otherwise completely fine. The real fix is to
+ // compare the hidden types via our type equivalence/relation infra instead of doing an
+ // identity check.
+ let _ = infcx.take_opaque_types();
+ return Ok(());
+ }
// Nested opaque types occur only in associated types:
// ` type Opaque<T> = impl Trait<&'static T, AssocTy = impl Nested>; `
// They can only be referenced as `<Opaque<T> as Trait<&'static T>>::AssocTy`.
@@ -469,15 +485,63 @@ fn check_opaque_meets_bounds<'tcx>(
ocx.resolve_regions_and_report_errors(defining_use_anchor, &outlives_env)?;
}
}
- // Clean up after ourselves
- let _ = infcx.take_opaque_types();
+ // Check that any hidden types found during wf checking match the hidden types that `type_of` sees.
+ for (mut key, mut ty) in infcx.take_opaque_types() {
+ ty.hidden_type.ty = infcx.resolve_vars_if_possible(ty.hidden_type.ty);
+ key = infcx.resolve_vars_if_possible(key);
+ sanity_check_found_hidden_type(tcx, key, ty.hidden_type)?;
+ }
Ok(())
}
+fn sanity_check_found_hidden_type<'tcx>(
+ tcx: TyCtxt<'tcx>,
+ key: ty::OpaqueTypeKey<'tcx>,
+ mut ty: ty::OpaqueHiddenType<'tcx>,
+) -> Result<(), ErrorGuaranteed> {
+ if ty.ty.is_ty_var() {
+ // Nothing was actually constrained.
+ return Ok(());
+ }
+ if let ty::Alias(ty::Opaque, alias) = ty.ty.kind() {
+ if alias.def_id == key.def_id.to_def_id() && alias.args == key.args {
+ // Nothing was actually constrained, this is an opaque usage that was
+ // only discovered to be opaque after inference vars resolved.
+ return Ok(());
+ }
+ }
+ let strip_vars = |ty: Ty<'tcx>| {
+ ty.fold_with(&mut BottomUpFolder {
+ tcx,
+ ty_op: |t| t,
+ ct_op: |c| c,
+ lt_op: |l| match l.kind() {
+ RegionKind::ReVar(_) => tcx.lifetimes.re_erased,
+ _ => l,
+ },
+ })
+ };
+ // Closures frequently end up containing erased lifetimes in their final representation.
+ // These correspond to lifetime variables that never got resolved, so we patch this up here.
+ ty.ty = strip_vars(ty.ty);
+ // Get the hidden type.
+ let hidden_ty = tcx.type_of(key.def_id).instantiate(tcx, key.args);
+ let hidden_ty = strip_vars(hidden_ty);
+
+ // If the hidden types differ, emit a type mismatch diagnostic.
+ if hidden_ty == ty.ty {
+ Ok(())
+ } else {
+ let span = tcx.def_span(key.def_id);
+ let other = ty::OpaqueHiddenType { ty: hidden_ty, span };
+ Err(ty.report_mismatch(&other, key.def_id, tcx).emit())
+ }
+}
+
fn is_enum_of_nonnullable_ptr<'tcx>(
tcx: TyCtxt<'tcx>,
adt_def: AdtDef<'tcx>,
- substs: SubstsRef<'tcx>,
+ args: GenericArgsRef<'tcx>,
) -> bool {
if adt_def.repr().inhibit_enum_layout_opt() {
return false;
@@ -489,14 +553,14 @@ fn is_enum_of_nonnullable_ptr<'tcx>(
let (([], [field]) | ([field], [])) = (&var_one.fields.raw[..], &var_two.fields.raw[..]) else {
return false;
};
- matches!(field.ty(tcx, substs).kind(), ty::FnPtr(..) | ty::Ref(..))
+ matches!(field.ty(tcx, args).kind(), ty::FnPtr(..) | ty::Ref(..))
}
fn check_static_linkage(tcx: TyCtxt<'_>, def_id: LocalDefId) {
if tcx.codegen_fn_attrs(def_id).import_linkage.is_some() {
- if match tcx.type_of(def_id).subst_identity().kind() {
+ if match tcx.type_of(def_id).instantiate_identity().kind() {
ty::RawPtr(_) => false,
- ty::Adt(adt_def, substs) => !is_enum_of_nonnullable_ptr(tcx, *adt_def, *substs),
+ ty::Adt(adt_def, args) => !is_enum_of_nonnullable_ptr(tcx, *adt_def, *args),
_ => true,
} {
tcx.sess.emit_err(LinkageType { span: tcx.def_span(def_id) });
@@ -530,7 +594,7 @@ fn check_item_type(tcx: TyCtxt<'_>, id: hir::ItemId) {
check_impl_items_against_trait(
tcx,
id.owner_id.def_id,
- impl_trait_ref.subst_identity(),
+ impl_trait_ref.instantiate_identity(),
);
check_on_unimplemented(tcx, id);
}
@@ -546,13 +610,13 @@ fn check_item_type(tcx: TyCtxt<'_>, id: hir::ItemId) {
fn_maybe_err(tcx, assoc_item.ident(tcx).span, abi);
}
ty::AssocKind::Type if assoc_item.defaultness(tcx).has_value() => {
- let trait_substs =
- InternalSubsts::identity_for_item(tcx, id.owner_id);
+ let trait_args =
+ GenericArgs::identity_for_item(tcx, id.owner_id);
let _: Result<_, rustc_errors::ErrorGuaranteed> = check_type_bounds(
tcx,
assoc_item,
assoc_item,
- ty::TraitRef::new(tcx, id.owner_id.to_def_id(), trait_substs),
+ ty::TraitRef::new(tcx, id.owner_id.to_def_id(), trait_args),
);
}
_ => {}
@@ -576,19 +640,8 @@ fn check_item_type(tcx: TyCtxt<'_>, id: hir::ItemId) {
check_opaque(tcx, id);
}
}
- DefKind::ImplTraitPlaceholder => {
- let parent = tcx.impl_trait_in_trait_parent_fn(id.owner_id.to_def_id());
- // Only check the validity of this opaque type if the function has a default body
- if let hir::Node::TraitItem(hir::TraitItem {
- kind: hir::TraitItemKind::Fn(_, hir::TraitFn::Provided(_)),
- ..
- }) = tcx.hir().get_by_def_id(parent.expect_local())
- {
- check_opaque(tcx, id);
- }
- }
- DefKind::TyAlias => {
- let pty_ty = tcx.type_of(id.owner_id).subst_identity();
+ DefKind::TyAlias { .. } => {
+ let pty_ty = tcx.type_of(id.owner_id).instantiate_identity();
let generics = tcx.generics_of(id.owner_id);
check_type_params_are_used(tcx, &generics, pty_ty);
}
@@ -642,7 +695,7 @@ fn check_item_type(tcx: TyCtxt<'_>, id: hir::ItemId) {
"replace the {} parameters with concrete {}{}",
kinds,
kinds_pl,
- egs.map(|egs| format!(" like `{}`", egs)).unwrap_or_default(),
+ egs.map(|egs| format!(" like `{egs}`")).unwrap_or_default(),
),
)
.emit();
@@ -727,7 +780,7 @@ pub(super) fn check_specialization_validity<'tcx>(
} else {
tcx.sess.delay_span_bug(
DUMMY_SP,
- format!("parent item: {:?} not marked as default", parent_impl),
+ format!("parent item: {parent_impl:?} not marked as default"),
);
}
}
@@ -902,8 +955,8 @@ fn check_impl_items_against_trait<'tcx>(
}
pub fn check_simd(tcx: TyCtxt<'_>, sp: Span, def_id: LocalDefId) {
- let t = tcx.type_of(def_id).subst_identity();
- if let ty::Adt(def, substs) = t.kind()
+ let t = tcx.type_of(def_id).instantiate_identity();
+ if let ty::Adt(def, args) = t.kind()
&& def.is_struct()
{
let fields = &def.non_enum_variant().fields;
@@ -911,8 +964,8 @@ pub fn check_simd(tcx: TyCtxt<'_>, sp: Span, def_id: LocalDefId) {
struct_span_err!(tcx.sess, sp, E0075, "SIMD vector cannot be empty").emit();
return;
}
- let e = fields[FieldIdx::from_u32(0)].ty(tcx, substs);
- if !fields.iter().all(|f| f.ty(tcx, substs) == e) {
+ let e = fields[FieldIdx::from_u32(0)].ty(tcx, args);
+ if !fields.iter().all(|f| f.ty(tcx, args) == e) {
struct_span_err!(tcx.sess, sp, E0076, "SIMD vector should be homogeneous")
.span_label(sp, "SIMD elements must have the same type")
.emit();
@@ -1019,7 +1072,7 @@ pub(super) fn check_packed(tcx: TyCtxt<'_>, sp: Span, def: ty::AdtDef<'_>) {
if first {
format!(
"`{}` contains a field of type `{}`",
- tcx.type_of(def.did()).subst_identity(),
+ tcx.type_of(def.did()).instantiate_identity(),
ident
)
} else {
@@ -1041,7 +1094,7 @@ pub(super) fn check_packed_inner(
def_id: DefId,
stack: &mut Vec<DefId>,
) -> Option<Vec<(DefId, Span)>> {
- if let ty::Adt(def, substs) = tcx.type_of(def_id).subst_identity().kind() {
+ if let ty::Adt(def, args) = tcx.type_of(def_id).instantiate_identity().kind() {
if def.is_struct() || def.is_union() {
if def.repr().align.is_some() {
return Some(vec![(def.did(), DUMMY_SP)]);
@@ -1049,7 +1102,7 @@ pub(super) fn check_packed_inner(
stack.push(def_id);
for field in &def.non_enum_variant().fields {
- if let ty::Adt(def, _) = field.ty(tcx, substs).kind()
+ if let ty::Adt(def, _) = field.ty(tcx, args).kind()
&& !stack.contains(&def.did())
&& let Some(mut defs) = check_packed_inner(tcx, def.did(), stack)
{
@@ -1088,21 +1141,21 @@ pub(super) fn check_transparent<'tcx>(tcx: TyCtxt<'tcx>, adt: ty::AdtDef<'tcx>)
// For each field, figure out if it's known to be a ZST and align(1), with "known"
// respecting #[non_exhaustive] attributes.
let field_infos = adt.all_fields().map(|field| {
- let ty = field.ty(tcx, InternalSubsts::identity_for_item(tcx, field.did));
+ let ty = field.ty(tcx, GenericArgs::identity_for_item(tcx, field.did));
let param_env = tcx.param_env(field.did);
let layout = tcx.layout_of(param_env.and(ty));
// We are currently checking the type this field came from, so it must be local
let span = tcx.hir().span_if_local(field.did).unwrap();
let zst = layout.is_ok_and(|layout| layout.is_zst());
- let align1 = layout.is_ok_and(|layout| layout.align.abi.bytes() == 1);
+ let align = layout.ok().map(|layout| layout.align.abi.bytes());
if !zst {
- return (span, zst, align1, None);
+ return (span, zst, align, None);
}
fn check_non_exhaustive<'tcx>(
tcx: TyCtxt<'tcx>,
t: Ty<'tcx>,
- ) -> ControlFlow<(&'static str, DefId, SubstsRef<'tcx>, bool)> {
+ ) -> ControlFlow<(&'static str, DefId, GenericArgsRef<'tcx>, bool)> {
match t.kind() {
ty::Tuple(list) => list.iter().try_for_each(|t| check_non_exhaustive(tcx, t)),
ty::Array(ty, _) => check_non_exhaustive(tcx, *ty),
@@ -1131,12 +1184,12 @@ pub(super) fn check_transparent<'tcx>(tcx: TyCtxt<'tcx>, adt: ty::AdtDef<'tcx>)
}
}
- (span, zst, align1, check_non_exhaustive(tcx, ty).break_value())
+ (span, zst, align, check_non_exhaustive(tcx, ty).break_value())
});
let non_zst_fields = field_infos
.clone()
- .filter_map(|(span, zst, _align1, _non_exhaustive)| if !zst { Some(span) } else { None });
+ .filter_map(|(span, zst, _align, _non_exhaustive)| if !zst { Some(span) } else { None });
let non_zst_count = non_zst_fields.clone().count();
if non_zst_count >= 2 {
bad_non_zero_sized_fields(tcx, adt, non_zst_count, non_zst_fields, tcx.def_span(adt.did()));
@@ -1144,19 +1197,28 @@ pub(super) fn check_transparent<'tcx>(tcx: TyCtxt<'tcx>, adt: ty::AdtDef<'tcx>)
let incompatible_zst_fields =
field_infos.clone().filter(|(_, _, _, opt)| opt.is_some()).count();
let incompat = incompatible_zst_fields + non_zst_count >= 2 && non_zst_count < 2;
- for (span, zst, align1, non_exhaustive) in field_infos {
- if zst && !align1 {
- struct_span_err!(
+ for (span, zst, align, non_exhaustive) in field_infos {
+ if zst && align != Some(1) {
+ let mut err = struct_span_err!(
tcx.sess,
span,
E0691,
"zero-sized field in transparent {} has alignment larger than 1",
adt.descr(),
- )
- .span_label(span, "has alignment larger than 1")
- .emit();
+ );
+
+ if let Some(align_bytes) = align {
+ err.span_label(
+ span,
+ format!("has alignment of {align_bytes}, which is larger than 1"),
+ );
+ } else {
+ err.span_label(span, "may have alignment larger than 1");
+ }
+
+ err.emit();
}
- if incompat && let Some((descr, def_id, substs, non_exhaustive)) = non_exhaustive {
+ if incompat && let Some((descr, def_id, args, non_exhaustive)) = non_exhaustive {
tcx.struct_span_lint_hir(
REPR_TRANSPARENT_EXTERNAL_PRIVATE_FIELDS,
tcx.hir().local_def_id_to_hir_id(adt.did().expect_local()),
@@ -1168,7 +1230,7 @@ pub(super) fn check_transparent<'tcx>(tcx: TyCtxt<'tcx>, adt: ty::AdtDef<'tcx>)
} else {
"contains private fields"
};
- let field_ty = tcx.def_path_str_with_substs(def_id, substs);
+ let field_ty = tcx.def_path_str_with_args(def_id, args);
lint
.note(format!("this {descr} contains `{field_ty}`, which {note}, \
and makes it not a breaking change to become non-zero-sized in the future."))
@@ -1389,11 +1451,14 @@ pub(super) fn check_type_params_are_used<'tcx>(
}
}
-pub(super) fn check_mod_item_types(tcx: TyCtxt<'_>, module_def_id: LocalDefId) {
+pub(super) fn check_mod_item_types(tcx: TyCtxt<'_>, module_def_id: LocalModDefId) {
let module = tcx.hir_module_items(module_def_id);
for id in module.items() {
check_item_type(tcx, id);
}
+ if module_def_id == LocalModDefId::CRATE_DEF_ID {
+ super::entry::check_for_entry_fn(tcx);
+ }
}
fn async_opaque_type_cycle_error(tcx: TyCtxt<'_>, span: Span) -> ErrorGuaranteed {
diff --git a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs
index 22e576e34..bd0ab6463 100644
--- a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs
+++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs
@@ -1,7 +1,7 @@
use super::potentially_plural_count;
use crate::errors::LifetimesOrBoundsMismatchOnTrait;
use hir::def_id::{DefId, LocalDefId};
-use rustc_data_structures::fx::{FxHashMap, FxIndexSet};
+use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexSet};
use rustc_errors::{
pluralize, struct_span_err, Applicability, DiagnosticId, ErrorGuaranteed, MultiSpan,
};
@@ -16,7 +16,7 @@ use rustc_infer::traits::util;
use rustc_middle::ty::error::{ExpectedFound, TypeError};
use rustc_middle::ty::util::ExplicitSelf;
use rustc_middle::ty::{
- self, InternalSubsts, Ty, TypeFoldable, TypeFolder, TypeSuperFoldable, TypeVisitableExt,
+ self, GenericArgs, Ty, TypeFoldable, TypeFolder, TypeSuperFoldable, TypeVisitableExt,
};
use rustc_middle::ty::{GenericParamDefKind, ToPredicate, TyCtxt};
use rustc_span::{Span, DUMMY_SP};
@@ -76,7 +76,7 @@ fn check_method_is_structurally_compatible<'tcx>(
Ok(())
}
-/// This function is best explained by example. Consider a trait with it's implementation:
+/// This function is best explained by example. Consider a trait with its implementation:
///
/// ```rust
/// trait Trait<'t, T> {
@@ -96,15 +96,15 @@ fn check_method_is_structurally_compatible<'tcx>(
/// For this we have to show that, assuming the bounds of the impl hold, the
/// bounds of `trait_m` imply the bounds of `impl_m`.
///
-/// We start out with `trait_to_impl_substs`, that maps the trait
+/// We start out with `trait_to_impl_args`, that maps the trait
/// type parameters to impl type parameters. This is taken from the
/// impl trait reference:
///
/// ```rust,ignore (pseudo-Rust)
-/// trait_to_impl_substs = {'t => 'j, T => &'i U, Self => Foo}
+/// trait_to_impl_args = {'t => 'j, T => &'i U, Self => Foo}
/// ```
///
-/// We create a mapping `dummy_substs` that maps from the impl type
+/// We create a mapping `dummy_args` that maps from the impl type
/// parameters to fresh types and regions. For type parameters,
/// this is the identity transform, but we could as well use any
/// placeholder types. For regions, we convert from bound to free
@@ -112,32 +112,32 @@ fn check_method_is_structurally_compatible<'tcx>(
/// declared on the impl or used in type parameter bounds).
///
/// ```rust,ignore (pseudo-Rust)
-/// impl_to_placeholder_substs = {'i => 'i0, U => U0, N => N0 }
+/// impl_to_placeholder_args = {'i => 'i0, U => U0, N => N0 }
/// ```
///
-/// Now we can apply `placeholder_substs` to the type of the impl method
+/// Now we can apply `placeholder_args` to the type of the impl method
/// to yield a new function type in terms of our fresh, placeholder
/// types:
///
/// ```rust,ignore (pseudo-Rust)
-/// <'b> fn(t: &'i0 U0, m: &'b) -> Foo
+/// <'b> fn(t: &'i0 U0, m: &'b N0) -> Foo
/// ```
///
/// We now want to extract and substitute the type of the *trait*
/// method and compare it. To do so, we must create a compound
-/// substitution by combining `trait_to_impl_substs` and
-/// `impl_to_placeholder_substs`, and also adding a mapping for the method
+/// substitution by combining `trait_to_impl_args` and
+/// `impl_to_placeholder_args`, and also adding a mapping for the method
/// type parameters. We extend the mapping to also include
/// the method parameters.
///
/// ```rust,ignore (pseudo-Rust)
-/// trait_to_placeholder_substs = { T => &'i0 U0, Self => Foo, M => N0 }
+/// trait_to_placeholder_args = { T => &'i0 U0, Self => Foo, M => N0 }
/// ```
///
/// Applying this to the trait method type yields:
///
/// ```rust,ignore (pseudo-Rust)
-/// <'a> fn(t: &'i0 U0, m: &'a) -> Foo
+/// <'a> fn(t: &'i0 U0, m: &'a N0) -> Foo
/// ```
///
/// This type is also the same but the name of the bound region (`'a`
@@ -148,8 +148,8 @@ fn check_method_is_structurally_compatible<'tcx>(
/// satisfied by the implementation's method.
///
/// We do this by creating a parameter environment which contains a
-/// substitution corresponding to `impl_to_placeholder_substs`. We then build
-/// `trait_to_placeholder_substs` and use it to convert the predicates contained
+/// substitution corresponding to `impl_to_placeholder_args`. We then build
+/// `trait_to_placeholder_args` and use it to convert the predicates contained
/// in the `trait_m` generics to the placeholder form.
///
/// Finally we register each of these predicates as an obligation and check that
@@ -162,7 +162,7 @@ fn compare_method_predicate_entailment<'tcx>(
impl_trait_ref: ty::TraitRef<'tcx>,
check_implied_wf: CheckImpliedWfMode,
) -> Result<(), ErrorGuaranteed> {
- let trait_to_impl_substs = impl_trait_ref.substs;
+ let trait_to_impl_args = impl_trait_ref.args;
// This node-id should be used for the `body_id` field on each
// `ObligationCause` (and the `FnCtxt`).
@@ -182,12 +182,12 @@ fn compare_method_predicate_entailment<'tcx>(
);
// Create mapping from impl to placeholder.
- let impl_to_placeholder_substs = InternalSubsts::identity_for_item(tcx, impl_m.def_id);
+ let impl_to_placeholder_args = GenericArgs::identity_for_item(tcx, impl_m.def_id);
// Create mapping from trait to placeholder.
- let trait_to_placeholder_substs =
- impl_to_placeholder_substs.rebase_onto(tcx, impl_m.container_id(tcx), trait_to_impl_substs);
- debug!("compare_impl_method: trait_to_placeholder_substs={:?}", trait_to_placeholder_substs);
+ let trait_to_placeholder_args =
+ impl_to_placeholder_args.rebase_onto(tcx, impl_m.container_id(tcx), trait_to_impl_args);
+ debug!("compare_impl_method: trait_to_placeholder_args={:?}", trait_to_placeholder_args);
let impl_m_predicates = tcx.predicates_of(impl_m.def_id);
let trait_m_predicates = tcx.predicates_of(trait_m.def_id);
@@ -211,7 +211,7 @@ fn compare_method_predicate_entailment<'tcx>(
// if all constraints hold.
hybrid_preds.predicates.extend(
trait_m_predicates
- .instantiate_own(tcx, trait_to_placeholder_substs)
+ .instantiate_own(tcx, trait_to_placeholder_args)
.map(|(predicate, _)| predicate),
);
@@ -219,11 +219,7 @@ fn compare_method_predicate_entailment<'tcx>(
// The key step here is to update the caller_bounds's predicates to be
// the new hybrid bounds we computed.
let normalize_cause = traits::ObligationCause::misc(impl_m_span, impl_m_def_id);
- let param_env = ty::ParamEnv::new(
- tcx.mk_clauses(&hybrid_preds.predicates),
- Reveal::UserFacing,
- hir::Constness::NotConst,
- );
+ let param_env = ty::ParamEnv::new(tcx.mk_clauses(&hybrid_preds.predicates), Reveal::UserFacing);
let param_env = traits::normalize_param_env_or_error(tcx, param_env, normalize_cause);
let infcx = &tcx.infer_ctxt().build();
@@ -231,7 +227,7 @@ fn compare_method_predicate_entailment<'tcx>(
debug!("compare_impl_method: caller_bounds={:?}", param_env.caller_bounds());
- let impl_m_own_bounds = impl_m_predicates.instantiate_own(tcx, impl_to_placeholder_substs);
+ let impl_m_own_bounds = impl_m_predicates.instantiate_own(tcx, impl_to_placeholder_args);
for (predicate, span) in impl_m_own_bounds {
let normalize_cause = traits::ObligationCause::misc(span, impl_m_def_id);
let predicate = ocx.normalize(&normalize_cause, param_env, predicate);
@@ -262,22 +258,19 @@ fn compare_method_predicate_entailment<'tcx>(
// type.
// Compute placeholder form of impl and trait method tys.
- let tcx = infcx.tcx;
-
let mut wf_tys = FxIndexSet::default();
let unnormalized_impl_sig = infcx.instantiate_binder_with_fresh_vars(
impl_m_span,
infer::HigherRankedType,
- tcx.fn_sig(impl_m.def_id).subst_identity(),
+ tcx.fn_sig(impl_m.def_id).instantiate_identity(),
);
- let unnormalized_impl_fty = Ty::new_fn_ptr(tcx, ty::Binder::dummy(unnormalized_impl_sig));
let norm_cause = ObligationCause::misc(impl_m_span, impl_m_def_id);
let impl_sig = ocx.normalize(&norm_cause, param_env, unnormalized_impl_sig);
debug!("compare_impl_method: impl_fty={:?}", impl_sig);
- let trait_sig = tcx.fn_sig(trait_m.def_id).subst(tcx, trait_to_placeholder_substs);
+ let trait_sig = tcx.fn_sig(trait_m.def_id).instantiate(tcx, trait_to_placeholder_args);
let trait_sig = tcx.liberate_late_bound_regions(impl_m.def_id, trait_sig);
// Next, add all inputs and output as well-formed tys. Importantly,
@@ -315,16 +308,60 @@ fn compare_method_predicate_entailment<'tcx>(
}
if check_implied_wf == CheckImpliedWfMode::Check && !(impl_sig, trait_sig).references_error() {
- // We need to check that the impl's args are well-formed given
- // the hybrid param-env (impl + trait method where-clauses).
- ocx.register_obligation(traits::Obligation::new(
- infcx.tcx,
- ObligationCause::dummy(),
- param_env,
- ty::Binder::dummy(ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(
- unnormalized_impl_fty.into(),
- ))),
- ));
+ // Select obligations to make progress on inference before processing
+ // the wf obligation below.
+ // FIXME(-Ztrait-solver=next): Not needed when the hack below is removed.
+ let errors = ocx.select_where_possible();
+ if !errors.is_empty() {
+ let reported = infcx.err_ctxt().report_fulfillment_errors(&errors);
+ return Err(reported);
+ }
+
+ // See #108544. Annoying, we can end up in cases where, because of winnowing,
+ // we pick param env candidates over a more general impl, leading to more
+ // stricter lifetime requirements than we would otherwise need. This can
+ // trigger the lint. Instead, let's only consider type outlives and
+ // region outlives obligations.
+ //
+ // FIXME(-Ztrait-solver=next): Try removing this hack again once
+ // the new solver is stable.
+ let mut wf_args: smallvec::SmallVec<[_; 4]> =
+ unnormalized_impl_sig.inputs_and_output.iter().map(|ty| ty.into()).collect();
+ // Annoyingly, asking for the WF predicates of an array (with an unevaluated const (only?))
+ // will give back the well-formed predicate of the same array.
+ let mut wf_args_seen: FxHashSet<_> = wf_args.iter().copied().collect();
+ while let Some(arg) = wf_args.pop() {
+ let Some(obligations) = rustc_trait_selection::traits::wf::obligations(
+ infcx,
+ param_env,
+ impl_m_def_id,
+ 0,
+ arg,
+ impl_m_span,
+ ) else {
+ continue;
+ };
+ for obligation in obligations {
+ debug!(?obligation);
+ match obligation.predicate.kind().skip_binder() {
+ // We need to register Projection oblgiations too, because we may end up with
+ // an implied `X::Item: 'a`, which gets desugared into `X::Item = ?0`, `?0: 'a`.
+ // If we only register the region outlives obligation, this leads to an unconstrained var.
+ // See `implied_bounds_entailment_alias_var` test.
+ ty::PredicateKind::Clause(
+ ty::ClauseKind::RegionOutlives(..)
+ | ty::ClauseKind::TypeOutlives(..)
+ | ty::ClauseKind::Projection(..),
+ ) => ocx.register_obligation(obligation),
+ ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(arg)) => {
+ if wf_args_seen.insert(arg) {
+ wf_args.push(arg)
+ }
+ }
+ _ => {}
+ }
+ }
+ }
}
// Check that all obligations are satisfied by the implementation's
@@ -357,7 +394,7 @@ fn compare_method_predicate_entailment<'tcx>(
// lifetime parameters.
let outlives_env = OutlivesEnvironment::with_bounds(
param_env,
- infcx.implied_bounds_tys(param_env, impl_m_def_id, wf_tys.clone()),
+ infcx.implied_bounds_tys(param_env, impl_m_def_id, wf_tys),
);
let errors = infcx.resolve_regions(&outlives_env);
if !errors.is_empty() {
@@ -615,14 +652,14 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>(
let impl_m = tcx.opt_associated_item(impl_m_def_id.to_def_id()).unwrap();
let trait_m = tcx.opt_associated_item(impl_m.trait_item_def_id.unwrap()).unwrap();
let impl_trait_ref =
- tcx.impl_trait_ref(impl_m.impl_container(tcx).unwrap()).unwrap().subst_identity();
+ tcx.impl_trait_ref(impl_m.impl_container(tcx).unwrap()).unwrap().instantiate_identity();
let param_env = tcx.param_env(impl_m_def_id);
// First, check a few of the same things as `compare_impl_method`,
// just so we don't ICE during substitution later.
check_method_is_structurally_compatible(tcx, impl_m, trait_m, impl_trait_ref, true)?;
- let trait_to_impl_substs = impl_trait_ref.substs;
+ let trait_to_impl_args = impl_trait_ref.args;
let impl_m_hir_id = tcx.hir().local_def_id_to_hir_id(impl_m_def_id);
let return_span = tcx.hir().fn_decl_by_hir_id(impl_m_hir_id).unwrap().output.span();
@@ -637,11 +674,11 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>(
);
// Create mapping from impl to placeholder.
- let impl_to_placeholder_substs = InternalSubsts::identity_for_item(tcx, impl_m.def_id);
+ let impl_to_placeholder_args = GenericArgs::identity_for_item(tcx, impl_m.def_id);
// Create mapping from trait to placeholder.
- let trait_to_placeholder_substs =
- impl_to_placeholder_substs.rebase_onto(tcx, impl_m.container_id(tcx), trait_to_impl_substs);
+ let trait_to_placeholder_args =
+ impl_to_placeholder_args.rebase_onto(tcx, impl_m.container_id(tcx), trait_to_impl_args);
let infcx = &tcx.infer_ctxt().build();
let ocx = ObligationCtxt::new(infcx);
@@ -651,7 +688,10 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>(
let impl_sig = ocx.normalize(
&norm_cause,
param_env,
- tcx.liberate_late_bound_regions(impl_m.def_id, tcx.fn_sig(impl_m.def_id).subst_identity()),
+ tcx.liberate_late_bound_regions(
+ impl_m.def_id,
+ tcx.fn_sig(impl_m.def_id).instantiate_identity(),
+ ),
);
impl_sig.error_reported()?;
let impl_return_ty = impl_sig.output();
@@ -665,7 +705,7 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>(
.instantiate_binder_with_fresh_vars(
return_span,
infer::HigherRankedType,
- tcx.fn_sig(trait_m.def_id).subst(tcx, trait_to_placeholder_substs),
+ tcx.fn_sig(trait_m.def_id).instantiate(tcx, trait_to_placeholder_args),
)
.fold_with(&mut collector);
@@ -757,48 +797,48 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>(
);
ocx.resolve_regions_and_report_errors(impl_m_def_id, &outlives_env)?;
- let mut collected_tys = FxHashMap::default();
- for (def_id, (ty, substs)) in collected_types {
- match infcx.fully_resolve((ty, substs)) {
- Ok((ty, substs)) => {
+ let mut remapped_types = FxHashMap::default();
+ for (def_id, (ty, args)) in collected_types {
+ match infcx.fully_resolve((ty, args)) {
+ Ok((ty, args)) => {
// `ty` contains free regions that we created earlier while liberating the
// trait fn signature. However, projection normalization expects `ty` to
// contains `def_id`'s early-bound regions.
- let id_substs = InternalSubsts::identity_for_item(tcx, def_id);
- debug!(?id_substs, ?substs);
- let map: FxHashMap<_, _> = std::iter::zip(substs, id_substs)
+ let id_args = GenericArgs::identity_for_item(tcx, def_id);
+ debug!(?id_args, ?args);
+ let map: FxHashMap<_, _> = std::iter::zip(args, id_args)
.skip(tcx.generics_of(trait_m.def_id).count())
.filter_map(|(a, b)| Some((a.as_region()?, b.as_region()?)))
.collect();
debug!(?map);
// NOTE(compiler-errors): RPITITs, like all other RPITs, have early-bound
- // region substs that are synthesized during AST lowering. These are substs
- // that are appended to the parent substs (trait and trait method). However,
+ // region args that are synthesized during AST lowering. These are args
+ // that are appended to the parent args (trait and trait method). However,
// we're trying to infer the unsubstituted type value of the RPITIT inside
- // the *impl*, so we can later use the impl's method substs to normalize
+ // the *impl*, so we can later use the impl's method args to normalize
// an RPITIT to a concrete type (`confirm_impl_trait_in_trait_candidate`).
//
// Due to the design of RPITITs, during AST lowering, we have no idea that
// an impl method corresponds to a trait method with RPITITs in it. Therefore,
- // we don't have a list of early-bound region substs for the RPITIT in the impl.
+ // we don't have a list of early-bound region args for the RPITIT in the impl.
// Since early region parameters are index-based, we can't just rebase these
- // (trait method) early-bound region substs onto the impl, and there's no
- // guarantee that the indices from the trait substs and impl substs line up.
- // So to fix this, we subtract the number of trait substs and add the number of
- // impl substs to *renumber* these early-bound regions to their corresponding
+ // (trait method) early-bound region args onto the impl, and there's no
+ // guarantee that the indices from the trait args and impl args line up.
+ // So to fix this, we subtract the number of trait args and add the number of
+ // impl args to *renumber* these early-bound regions to their corresponding
// indices in the impl's substitutions list.
//
- // Also, we only need to account for a difference in trait and impl substs,
+ // Also, we only need to account for a difference in trait and impl args,
// since we previously enforce that the trait method and impl method have the
// same generics.
- let num_trait_substs = trait_to_impl_substs.len();
- let num_impl_substs = tcx.generics_of(impl_m.container_id(tcx)).params.len();
+ let num_trait_args = trait_to_impl_args.len();
+ let num_impl_args = tcx.generics_of(impl_m.container_id(tcx)).params.len();
let ty = match ty.try_fold_with(&mut RemapHiddenTyRegions {
tcx,
map,
- num_trait_substs,
- num_impl_substs,
+ num_trait_args,
+ num_impl_args,
def_id,
impl_def_id: impl_m.container_id(tcx),
ty,
@@ -807,24 +847,42 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>(
Ok(ty) => ty,
Err(guar) => Ty::new_error(tcx, guar),
};
- collected_tys.insert(def_id, ty::EarlyBinder::bind(ty));
+ remapped_types.insert(def_id, ty::EarlyBinder::bind(ty));
}
Err(err) => {
let reported = tcx.sess.delay_span_bug(
return_span,
format!("could not fully resolve: {ty} => {err:?}"),
);
- collected_tys.insert(def_id, ty::EarlyBinder::bind(Ty::new_error(tcx, reported)));
+ remapped_types.insert(def_id, ty::EarlyBinder::bind(Ty::new_error(tcx, reported)));
}
}
}
- Ok(&*tcx.arena.alloc(collected_tys))
+ // We may not collect all RPITITs that we see in the HIR for a trait signature
+ // because an RPITIT was located within a missing item. Like if we have a sig
+ // returning `-> Missing<impl Sized>`, that gets converted to `-> [type error]`,
+ // and when walking through the signature we end up never collecting the def id
+ // of the `impl Sized`. Insert that here, so we don't ICE later.
+ for assoc_item in tcx.associated_types_for_impl_traits_in_associated_fn(trait_m.def_id) {
+ if !remapped_types.contains_key(assoc_item) {
+ remapped_types.insert(
+ *assoc_item,
+ ty::EarlyBinder::bind(Ty::new_error_with_message(
+ tcx,
+ return_span,
+ "missing synthetic item for RPITIT",
+ )),
+ );
+ }
+ }
+
+ Ok(&*tcx.arena.alloc(remapped_types))
}
struct ImplTraitInTraitCollector<'a, 'tcx> {
ocx: &'a ObligationCtxt<'a, 'tcx>,
- types: FxHashMap<DefId, (Ty<'tcx>, ty::SubstsRef<'tcx>)>,
+ types: FxHashMap<DefId, (Ty<'tcx>, ty::GenericArgsRef<'tcx>)>,
span: Span,
param_env: ty::ParamEnv<'tcx>,
body_id: LocalDefId,
@@ -853,8 +911,8 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for ImplTraitInTraitCollector<'_, 'tcx> {
if let Some((ty, _)) = self.types.get(&proj.def_id) {
return *ty;
}
- //FIXME(RPITIT): Deny nested RPITIT in substs too
- if proj.substs.has_escaping_bound_vars() {
+ //FIXME(RPITIT): Deny nested RPITIT in args too
+ if proj.args.has_escaping_bound_vars() {
bug!("FIXME(RPITIT): error here");
}
// Replace with infer var
@@ -862,9 +920,9 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for ImplTraitInTraitCollector<'_, 'tcx> {
span: self.span,
kind: TypeVariableOriginKind::MiscVariable,
});
- self.types.insert(proj.def_id, (infer_ty, proj.substs));
+ self.types.insert(proj.def_id, (infer_ty, proj.args));
// Recurse into bounds
- for (pred, pred_span) in self.interner().explicit_item_bounds(proj.def_id).subst_iter_copied(self.interner(), proj.substs) {
+ for (pred, pred_span) in self.interner().explicit_item_bounds(proj.def_id).iter_instantiated_copied(self.interner(), proj.args) {
let pred = pred.fold_with(self);
let pred = self.ocx.normalize(
&ObligationCause::misc(self.span, self.body_id),
@@ -893,8 +951,8 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for ImplTraitInTraitCollector<'_, 'tcx> {
struct RemapHiddenTyRegions<'tcx> {
tcx: TyCtxt<'tcx>,
map: FxHashMap<ty::Region<'tcx>, ty::Region<'tcx>>,
- num_trait_substs: usize,
- num_impl_substs: usize,
+ num_trait_args: usize,
+ num_impl_args: usize,
def_id: DefId,
impl_def_id: DefId,
ty: Ty<'tcx>,
@@ -909,16 +967,16 @@ impl<'tcx> ty::FallibleTypeFolder<TyCtxt<'tcx>> for RemapHiddenTyRegions<'tcx> {
}
fn try_fold_ty(&mut self, t: Ty<'tcx>) -> Result<Ty<'tcx>, Self::Error> {
- if let ty::Alias(ty::Opaque, ty::AliasTy { substs, def_id, .. }) = *t.kind() {
- let mut mapped_substs = Vec::with_capacity(substs.len());
- for (arg, v) in std::iter::zip(substs, self.tcx.variances_of(def_id)) {
- mapped_substs.push(match (arg.unpack(), v) {
- // Skip uncaptured opaque substs
+ if let ty::Alias(ty::Opaque, ty::AliasTy { args, def_id, .. }) = *t.kind() {
+ let mut mapped_args = Vec::with_capacity(args.len());
+ for (arg, v) in std::iter::zip(args, self.tcx.variances_of(def_id)) {
+ mapped_args.push(match (arg.unpack(), v) {
+ // Skip uncaptured opaque args
(ty::GenericArgKind::Lifetime(_), ty::Bivariant) => arg,
_ => arg.try_fold_with(self)?,
});
}
- Ok(Ty::new_opaque(self.tcx, def_id, self.tcx.mk_substs(&mapped_substs)))
+ Ok(Ty::new_opaque(self.tcx, def_id, self.tcx.mk_args(&mapped_args)))
} else {
t.try_super_fold_with(self)
}
@@ -975,7 +1033,7 @@ impl<'tcx> ty::FallibleTypeFolder<TyCtxt<'tcx>> for RemapHiddenTyRegions<'tcx> {
ty::EarlyBoundRegion {
def_id: e.def_id,
name: e.name,
- index: (e.index as usize - self.num_trait_substs + self.num_impl_substs) as u32,
+ index: (e.index as usize - self.num_trait_args + self.num_impl_args) as u32,
},
))
}
@@ -1214,7 +1272,7 @@ fn compare_self_type<'tcx>(
ty::ImplContainer => impl_trait_ref.self_ty(),
ty::TraitContainer => tcx.types.self_param,
};
- let self_arg_ty = tcx.fn_sig(method.def_id).subst_identity().input(0);
+ let self_arg_ty = tcx.fn_sig(method.def_id).instantiate_identity().input(0);
let param_env = ty::ParamEnv::reveal_all();
let infcx = tcx.infer_ctxt().build();
@@ -1319,7 +1377,7 @@ fn compare_number_of_generics<'tcx>(
// has mismatched type or const generic arguments, then the method that it's
// inheriting the generics from will also have mismatched arguments, and
// we'll report an error for that instead. Delay a bug for safety, though.
- if trait_.opt_rpitit_info.is_some() {
+ if trait_.is_impl_trait_in_trait() {
return Err(tcx.sess.delay_span_bug(
rustc_span::DUMMY_SP,
"errors comparing numbers of generics of trait/impl functions were not emitted",
@@ -1669,19 +1727,19 @@ fn compare_synthetic_generics<'tcx>(
/// ```rust,ignore (pseudo-Rust)
/// trait Foo {
/// fn foo<const N: u8>();
-/// type bar<const N: u8>;
+/// type Bar<const N: u8>;
/// fn baz<const N: u32>();
-/// type blah<T>;
+/// type Blah<T>;
/// }
///
/// impl Foo for () {
/// fn foo<const N: u64>() {}
/// //~^ error
-/// type bar<const N: u64> {}
+/// type Bar<const N: u64> = ();
/// //~^ error
/// fn baz<T>() {}
/// //~^ error
-/// type blah<const N: i64> = u32;
+/// type Blah<const N: i64> = u32;
/// //~^ error
/// }
/// ```
@@ -1738,10 +1796,10 @@ fn compare_generic_param_kinds<'tcx>(
format!(
"{} const parameter of type `{}`",
prefix,
- tcx.type_of(param.def_id).subst_identity()
+ tcx.type_of(param.def_id).instantiate_identity()
)
}
- Type { .. } => format!("{} type parameter", prefix),
+ Type { .. } => format!("{prefix} type parameter"),
Lifetime { .. } => unreachable!(),
};
@@ -1769,37 +1827,83 @@ pub(super) fn compare_impl_const_raw(
let impl_const_item = tcx.associated_item(impl_const_item_def);
let trait_const_item = tcx.associated_item(trait_const_item_def);
let impl_trait_ref =
- tcx.impl_trait_ref(impl_const_item.container_id(tcx)).unwrap().subst_identity();
- debug!("compare_const_impl(impl_trait_ref={:?})", impl_trait_ref);
+ tcx.impl_trait_ref(impl_const_item.container_id(tcx)).unwrap().instantiate_identity();
- let impl_c_span = tcx.def_span(impl_const_item_def.to_def_id());
+ debug!("compare_impl_const(impl_trait_ref={:?})", impl_trait_ref);
- let infcx = tcx.infer_ctxt().build();
- let param_env = tcx.param_env(impl_const_item_def.to_def_id());
- let ocx = ObligationCtxt::new(&infcx);
+ compare_number_of_generics(tcx, impl_const_item, trait_const_item, false)?;
+ compare_generic_param_kinds(tcx, impl_const_item, trait_const_item, false)?;
+ compare_const_predicate_entailment(tcx, impl_const_item, trait_const_item, impl_trait_ref)
+}
+
+/// The equivalent of [compare_method_predicate_entailment], but for associated constants
+/// instead of associated functions.
+// FIXME(generic_const_items): If possible extract the common parts of `compare_{type,const}_predicate_entailment`.
+fn compare_const_predicate_entailment<'tcx>(
+ tcx: TyCtxt<'tcx>,
+ impl_ct: ty::AssocItem,
+ trait_ct: ty::AssocItem,
+ impl_trait_ref: ty::TraitRef<'tcx>,
+) -> Result<(), ErrorGuaranteed> {
+ let impl_ct_def_id = impl_ct.def_id.expect_local();
+ let impl_ct_span = tcx.def_span(impl_ct_def_id);
// The below is for the most part highly similar to the procedure
// for methods above. It is simpler in many respects, especially
// because we shouldn't really have to deal with lifetimes or
// predicates. In fact some of this should probably be put into
// shared functions because of DRY violations...
- let trait_to_impl_substs = impl_trait_ref.substs;
+ let impl_args = GenericArgs::identity_for_item(tcx, impl_ct.def_id);
+ let trait_to_impl_args =
+ impl_args.rebase_onto(tcx, impl_ct.container_id(tcx), impl_trait_ref.args);
// Create a parameter environment that represents the implementation's
// method.
// Compute placeholder form of impl and trait const tys.
- let impl_ty = tcx.type_of(impl_const_item_def.to_def_id()).subst_identity();
- let trait_ty = tcx.type_of(trait_const_item_def).subst(tcx, trait_to_impl_substs);
- let mut cause = ObligationCause::new(
- impl_c_span,
- impl_const_item_def,
- ObligationCauseCode::CompareImplItemObligation {
- impl_item_def_id: impl_const_item_def,
- trait_item_def_id: trait_const_item_def,
- kind: impl_const_item.kind,
- },
+ let impl_ty = tcx.type_of(impl_ct_def_id).instantiate_identity();
+
+ let trait_ty = tcx.type_of(trait_ct.def_id).instantiate(tcx, trait_to_impl_args);
+ let code = ObligationCauseCode::CompareImplItemObligation {
+ impl_item_def_id: impl_ct_def_id,
+ trait_item_def_id: trait_ct.def_id,
+ kind: impl_ct.kind,
+ };
+ let mut cause = ObligationCause::new(impl_ct_span, impl_ct_def_id, code.clone());
+
+ let impl_ct_predicates = tcx.predicates_of(impl_ct.def_id);
+ let trait_ct_predicates = tcx.predicates_of(trait_ct.def_id);
+
+ check_region_bounds_on_impl_item(tcx, impl_ct, trait_ct, false)?;
+
+ // The predicates declared by the impl definition, the trait and the
+ // associated const in the trait are assumed.
+ let impl_predicates = tcx.predicates_of(impl_ct_predicates.parent.unwrap());
+ let mut hybrid_preds = impl_predicates.instantiate_identity(tcx);
+ hybrid_preds.predicates.extend(
+ trait_ct_predicates
+ .instantiate_own(tcx, trait_to_impl_args)
+ .map(|(predicate, _)| predicate),
+ );
+
+ let param_env = ty::ParamEnv::new(tcx.mk_clauses(&hybrid_preds.predicates), Reveal::UserFacing);
+ let param_env = traits::normalize_param_env_or_error(
+ tcx,
+ param_env,
+ ObligationCause::misc(impl_ct_span, impl_ct_def_id),
);
+ let infcx = tcx.infer_ctxt().build();
+ let ocx = ObligationCtxt::new(&infcx);
+
+ let impl_ct_own_bounds = impl_ct_predicates.instantiate_own(tcx, impl_args);
+ for (predicate, span) in impl_ct_own_bounds {
+ let cause = ObligationCause::misc(span, impl_ct_def_id);
+ let predicate = ocx.normalize(&cause, param_env, predicate);
+
+ let cause = ObligationCause::new(span, impl_ct_def_id, code.clone());
+ ocx.register_obligation(traits::Obligation::new(tcx, cause, param_env, predicate));
+ }
+
// There is no "body" here, so just pass dummy id.
let impl_ty = ocx.normalize(&cause, param_env, impl_ty);
@@ -1818,7 +1922,7 @@ pub(super) fn compare_impl_const_raw(
);
// Locate the Span containing just the type of the offending impl
- let (ty, _) = tcx.hir().expect_impl_item(impl_const_item_def).expect_const();
+ let (ty, _) = tcx.hir().expect_impl_item(impl_ct_def_id).expect_const();
cause.span = ty.span;
let mut diag = struct_span_err!(
@@ -1826,12 +1930,12 @@ pub(super) fn compare_impl_const_raw(
cause.span,
E0326,
"implemented const `{}` has an incompatible type for trait",
- trait_const_item.name
+ trait_ct.name
);
- let trait_c_span = trait_const_item_def.as_local().map(|trait_c_def_id| {
+ let trait_c_span = trait_ct.def_id.as_local().map(|trait_ct_def_id| {
// Add a label to the Span containing just the type of the const
- let (ty, _) = tcx.hir().expect_trait_item(trait_c_def_id).expect_const();
+ let (ty, _) = tcx.hir().expect_trait_item(trait_ct_def_id).expect_const();
ty.span
});
@@ -1858,7 +1962,7 @@ pub(super) fn compare_impl_const_raw(
}
let outlives_env = OutlivesEnvironment::new(param_env);
- ocx.resolve_regions_and_report_errors(impl_const_item_def, &outlives_env)
+ ocx.resolve_regions_and_report_errors(impl_ct_def_id, &outlives_env)
}
pub(super) fn compare_impl_ty<'tcx>(
@@ -1885,26 +1989,26 @@ fn compare_type_predicate_entailment<'tcx>(
trait_ty: ty::AssocItem,
impl_trait_ref: ty::TraitRef<'tcx>,
) -> Result<(), ErrorGuaranteed> {
- let impl_substs = InternalSubsts::identity_for_item(tcx, impl_ty.def_id);
- let trait_to_impl_substs =
- impl_substs.rebase_onto(tcx, impl_ty.container_id(tcx), impl_trait_ref.substs);
+ let impl_args = GenericArgs::identity_for_item(tcx, impl_ty.def_id);
+ let trait_to_impl_args =
+ impl_args.rebase_onto(tcx, impl_ty.container_id(tcx), impl_trait_ref.args);
let impl_ty_predicates = tcx.predicates_of(impl_ty.def_id);
let trait_ty_predicates = tcx.predicates_of(trait_ty.def_id);
check_region_bounds_on_impl_item(tcx, impl_ty, trait_ty, false)?;
- let impl_ty_own_bounds = impl_ty_predicates.instantiate_own(tcx, impl_substs);
+ let impl_ty_own_bounds = impl_ty_predicates.instantiate_own(tcx, impl_args);
if impl_ty_own_bounds.len() == 0 {
// Nothing to check.
return Ok(());
}
- // This `HirId` should be used for the `body_id` field on each
+ // This `DefId` should be used for the `body_id` field on each
// `ObligationCause` (and the `FnCtxt`). This is what
// `regionck_item` expects.
let impl_ty_def_id = impl_ty.def_id.expect_local();
- debug!("compare_type_predicate_entailment: trait_to_impl_substs={:?}", trait_to_impl_substs);
+ debug!("compare_type_predicate_entailment: trait_to_impl_args={:?}", trait_to_impl_args);
// The predicates declared by the impl definition, the trait and the
// associated type in the trait are assumed.
@@ -1912,19 +2016,15 @@ fn compare_type_predicate_entailment<'tcx>(
let mut hybrid_preds = impl_predicates.instantiate_identity(tcx);
hybrid_preds.predicates.extend(
trait_ty_predicates
- .instantiate_own(tcx, trait_to_impl_substs)
+ .instantiate_own(tcx, trait_to_impl_args)
.map(|(predicate, _)| predicate),
);
debug!("compare_type_predicate_entailment: bounds={:?}", hybrid_preds);
let impl_ty_span = tcx.def_span(impl_ty_def_id);
- let normalize_cause = traits::ObligationCause::misc(impl_ty_span, impl_ty_def_id);
- let param_env = ty::ParamEnv::new(
- tcx.mk_clauses(&hybrid_preds.predicates),
- Reveal::UserFacing,
- hir::Constness::NotConst,
- );
+ let normalize_cause = ObligationCause::misc(impl_ty_span, impl_ty_def_id);
+ let param_env = ty::ParamEnv::new(tcx.mk_clauses(&hybrid_preds.predicates), Reveal::UserFacing);
let param_env = traits::normalize_param_env_or_error(tcx, param_env, normalize_cause);
let infcx = tcx.infer_ctxt().build();
let ocx = ObligationCtxt::new(&infcx);
@@ -1968,7 +2068,7 @@ fn compare_type_predicate_entailment<'tcx>(
///
/// trait X { type Y: Copy } impl X for T { type Y = S; }
///
-/// We are able to normalize `<T as X>::U` to `S`, and so when we check the
+/// We are able to normalize `<T as X>::Y` to `S`, and so when we check the
/// impl is well-formed we have to prove `S: Copy`.
///
/// For default associated types the normalization is not possible (the value
@@ -1990,9 +2090,9 @@ pub(super) fn check_type_bounds<'tcx>(
// }
//
// - `impl_trait_ref` would be `<(A, B) as Foo<u32>>`
- // - `normalize_impl_ty_substs` would be `[A, B, ^0.0]` (`^0.0` here is the bound var with db 0 and index 0)
+ // - `normalize_impl_ty_args` would be `[A, B, ^0.0]` (`^0.0` here is the bound var with db 0 and index 0)
// - `normalize_impl_ty` would be `Wrapper<A, B, ^0.0>`
- // - `rebased_substs` would be `[(A, B), u32, ^0.0]`, combining the substs from
+ // - `rebased_args` would be `[(A, B), u32, ^0.0]`, combining the args from
// the *trait* with the generic associated type parameters (as bound vars).
//
// A note regarding the use of bound vars here:
@@ -2022,9 +2122,11 @@ pub(super) fn check_type_bounds<'tcx>(
// the trait (notably, that X: Eq and T: Family).
let mut bound_vars: smallvec::SmallVec<[ty::BoundVariableKind; 8]> =
smallvec::SmallVec::with_capacity(tcx.generics_of(impl_ty.def_id).params.len());
- // Extend the impl's identity substs with late-bound GAT vars
- let normalize_impl_ty_substs = ty::InternalSubsts::identity_for_item(tcx, container_id)
- .extend_to(tcx, impl_ty.def_id, |param, _| match param.kind {
+ // Extend the impl's identity args with late-bound GAT vars
+ let normalize_impl_ty_args = ty::GenericArgs::identity_for_item(tcx, container_id).extend_to(
+ tcx,
+ impl_ty.def_id,
+ |param, _| match param.kind {
GenericParamDefKind::Type { .. } => {
let kind = ty::BoundTyKind::Param(param.def_id, param.name);
let bound_var = ty::BoundVariableKind::Ty(kind);
@@ -2060,7 +2162,8 @@ pub(super) fn check_type_bounds<'tcx>(
)
.into()
}
- });
+ },
+ );
// When checking something like
//
// trait X { type Y: PartialEq<<Self as X>::Y> }
@@ -2070,15 +2173,14 @@ pub(super) fn check_type_bounds<'tcx>(
// we want <T as X>::Y to normalize to S. This is valid because we are
// checking the default value specifically here. Add this equality to the
// ParamEnv for normalization specifically.
- let normalize_impl_ty = tcx.type_of(impl_ty.def_id).subst(tcx, normalize_impl_ty_substs);
- let rebased_substs =
- normalize_impl_ty_substs.rebase_onto(tcx, container_id, impl_trait_ref.substs);
+ let normalize_impl_ty = tcx.type_of(impl_ty.def_id).instantiate(tcx, normalize_impl_ty_args);
+ let rebased_args = normalize_impl_ty_args.rebase_onto(tcx, container_id, impl_trait_ref.args);
let bound_vars = tcx.mk_bound_variable_kinds(&bound_vars);
let normalize_param_env = {
let mut predicates = param_env.caller_bounds().iter().collect::<Vec<_>>();
match normalize_impl_ty.kind() {
ty::Alias(ty::Projection, proj)
- if proj.def_id == trait_ty.def_id && proj.substs == rebased_substs =>
+ if proj.def_id == trait_ty.def_id && proj.args == rebased_args =>
{
// Don't include this predicate if the projected type is
// exactly the same as the projection. This can occur in
@@ -2089,7 +2191,7 @@ pub(super) fn check_type_bounds<'tcx>(
_ => predicates.push(
ty::Binder::bind_with_vars(
ty::ProjectionPredicate {
- projection_ty: tcx.mk_alias_ty(trait_ty.def_id, rebased_substs),
+ projection_ty: tcx.mk_alias_ty(trait_ty.def_id, rebased_args),
term: normalize_impl_ty.into(),
},
bound_vars,
@@ -2097,13 +2199,13 @@ pub(super) fn check_type_bounds<'tcx>(
.to_predicate(tcx),
),
};
- ty::ParamEnv::new(tcx.mk_clauses(&predicates), Reveal::UserFacing, param_env.constness())
+ ty::ParamEnv::new(tcx.mk_clauses(&predicates), Reveal::UserFacing)
};
debug!(?normalize_param_env);
let impl_ty_def_id = impl_ty.def_id.expect_local();
- let impl_ty_substs = InternalSubsts::identity_for_item(tcx, impl_ty.def_id);
- let rebased_substs = impl_ty_substs.rebase_onto(tcx, container_id, impl_trait_ref.substs);
+ let impl_ty_args = GenericArgs::identity_for_item(tcx, impl_ty.def_id);
+ let rebased_args = impl_ty_args.rebase_onto(tcx, container_id, impl_trait_ref.args);
let infcx = tcx.infer_ctxt().build();
let ocx = ObligationCtxt::new(&infcx);
@@ -2111,7 +2213,7 @@ pub(super) fn check_type_bounds<'tcx>(
// A synthetic impl Trait for RPITIT desugaring has no HIR, which we currently use to get the
// span for an impl's associated type. Instead, for these, use the def_span for the synthesized
// associated type.
- let impl_ty_span = if impl_ty.opt_rpitit_info.is_some() {
+ let impl_ty_span = if impl_ty.is_impl_trait_in_trait() {
tcx.def_span(impl_ty_def_id)
} else {
match tcx.hir().get_by_def_id(impl_ty_def_id) {
@@ -2144,7 +2246,7 @@ pub(super) fn check_type_bounds<'tcx>(
let obligations: Vec<_> = tcx
.explicit_item_bounds(trait_ty.def_id)
- .subst_iter_copied(tcx, rebased_substs)
+ .iter_instantiated_copied(tcx, rebased_args)
.map(|(concrete_ty_bound, span)| {
debug!("check_type_bounds: concrete_ty_bound = {:?}", concrete_ty_bound);
traits::Obligation::new(tcx, mk_cause(span), param_env, concrete_ty_bound)
diff --git a/compiler/rustc_hir_analysis/src/check/dropck.rs b/compiler/rustc_hir_analysis/src/check/dropck.rs
index 13d1abe2a..dda3f7425 100644
--- a/compiler/rustc_hir_analysis/src/check/dropck.rs
+++ b/compiler/rustc_hir_analysis/src/check/dropck.rs
@@ -5,8 +5,8 @@ use rustc_data_structures::fx::FxHashSet;
use rustc_errors::{struct_span_err, ErrorGuaranteed};
use rustc_infer::infer::outlives::env::OutlivesEnvironment;
use rustc_infer::infer::{RegionResolutionError, TyCtxtInferExt};
-use rustc_middle::ty::subst::SubstsRef;
use rustc_middle::ty::util::CheckRegions;
+use rustc_middle::ty::GenericArgsRef;
use rustc_middle::ty::{self, TyCtxt};
use rustc_trait_selection::traits::{self, ObligationCtxt};
@@ -44,21 +44,21 @@ pub fn check_drop_impl(tcx: TyCtxt<'_>, drop_impl_did: DefId) -> Result<(), Erro
}));
}
}
- let dtor_self_type = tcx.type_of(drop_impl_did).subst_identity();
+ let dtor_self_type = tcx.type_of(drop_impl_did).instantiate_identity();
match dtor_self_type.kind() {
- ty::Adt(adt_def, adt_to_impl_substs) => {
+ ty::Adt(adt_def, adt_to_impl_args) => {
ensure_drop_params_and_item_params_correspond(
tcx,
drop_impl_did.expect_local(),
adt_def.did(),
- adt_to_impl_substs,
+ adt_to_impl_args,
)?;
ensure_drop_predicates_are_implied_by_item_defn(
tcx,
drop_impl_did.expect_local(),
adt_def.did().expect_local(),
- adt_to_impl_substs,
+ adt_to_impl_args,
)
}
_ => {
@@ -79,10 +79,11 @@ fn ensure_drop_params_and_item_params_correspond<'tcx>(
tcx: TyCtxt<'tcx>,
drop_impl_did: LocalDefId,
self_type_did: DefId,
- adt_to_impl_substs: SubstsRef<'tcx>,
+ adt_to_impl_args: GenericArgsRef<'tcx>,
) -> Result<(), ErrorGuaranteed> {
- let Err(arg) = tcx.uses_unique_generic_params(adt_to_impl_substs, CheckRegions::OnlyEarlyBound) else {
- return Ok(())
+ let Err(arg) = tcx.uses_unique_generic_params(adt_to_impl_args, CheckRegions::OnlyEarlyBound)
+ else {
+ return Ok(());
};
let drop_impl_span = tcx.def_span(drop_impl_did);
@@ -114,12 +115,12 @@ fn ensure_drop_predicates_are_implied_by_item_defn<'tcx>(
tcx: TyCtxt<'tcx>,
drop_impl_def_id: LocalDefId,
adt_def_id: LocalDefId,
- adt_to_impl_substs: SubstsRef<'tcx>,
+ adt_to_impl_args: GenericArgsRef<'tcx>,
) -> Result<(), ErrorGuaranteed> {
let infcx = tcx.infer_ctxt().build();
let ocx = ObligationCtxt::new(&infcx);
- // Take the param-env of the adt and substitute the substs that show up in
+ // Take the param-env of the adt and substitute the args that show up in
// the implementation's self type. This gives us the assumptions that the
// self ty of the implementation is allowed to know just from it being a
// well-formed adt, since that's all we're allowed to assume while proving
@@ -128,9 +129,8 @@ fn ensure_drop_predicates_are_implied_by_item_defn<'tcx>(
// We don't need to normalize this param-env or anything, since we're only
// substituting it with free params, so no additional param-env normalization
// can occur on top of what has been done in the param_env query itself.
- let param_env = ty::EarlyBinder::bind(tcx.param_env(adt_def_id))
- .subst(tcx, adt_to_impl_substs)
- .with_constness(tcx.constness(drop_impl_def_id));
+ let param_env =
+ ty::EarlyBinder::bind(tcx.param_env(adt_def_id)).instantiate(tcx, adt_to_impl_args);
for (pred, span) in tcx.predicates_of(drop_impl_def_id).instantiate_identity(tcx) {
let normalize_cause = traits::ObligationCause::misc(span, adt_def_id);
diff --git a/compiler/rustc_hir_analysis/src/check/entry.rs b/compiler/rustc_hir_analysis/src/check/entry.rs
new file mode 100644
index 000000000..fcaefe026
--- /dev/null
+++ b/compiler/rustc_hir_analysis/src/check/entry.rs
@@ -0,0 +1,277 @@
+use rustc_hir as hir;
+use rustc_hir::Node;
+use rustc_infer::infer::TyCtxtInferExt;
+use rustc_middle::ty::{self, Ty, TyCtxt};
+use rustc_session::config::EntryFnType;
+use rustc_span::def_id::{DefId, LocalDefId, CRATE_DEF_ID};
+use rustc_span::{symbol::sym, Span};
+use rustc_target::spec::abi::Abi;
+use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt as _;
+use rustc_trait_selection::traits::{self, ObligationCause, ObligationCauseCode};
+
+use std::ops::Not;
+
+use crate::errors;
+use crate::require_same_types;
+
+pub(crate) fn check_for_entry_fn(tcx: TyCtxt<'_>) {
+ match tcx.entry_fn(()) {
+ Some((def_id, EntryFnType::Main { .. })) => check_main_fn_ty(tcx, def_id),
+ Some((def_id, EntryFnType::Start)) => check_start_fn_ty(tcx, def_id),
+ _ => {}
+ }
+}
+
+fn check_main_fn_ty(tcx: TyCtxt<'_>, main_def_id: DefId) {
+ let main_fnsig = tcx.fn_sig(main_def_id).instantiate_identity();
+ let main_span = tcx.def_span(main_def_id);
+
+ fn main_fn_diagnostics_def_id(tcx: TyCtxt<'_>, def_id: DefId, sp: Span) -> LocalDefId {
+ if let Some(local_def_id) = def_id.as_local() {
+ let hir_type = tcx.type_of(local_def_id).instantiate_identity();
+ if !matches!(hir_type.kind(), ty::FnDef(..)) {
+ span_bug!(sp, "main has a non-function type: found `{}`", hir_type);
+ }
+ local_def_id
+ } else {
+ CRATE_DEF_ID
+ }
+ }
+
+ fn main_fn_generics_params_span(tcx: TyCtxt<'_>, def_id: DefId) -> Option<Span> {
+ if !def_id.is_local() {
+ return None;
+ }
+ let hir_id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local());
+ match tcx.hir().find(hir_id) {
+ Some(Node::Item(hir::Item { kind: hir::ItemKind::Fn(_, generics, _), .. })) => {
+ generics.params.is_empty().not().then_some(generics.span)
+ }
+ _ => {
+ span_bug!(tcx.def_span(def_id), "main has a non-function type");
+ }
+ }
+ }
+
+ fn main_fn_where_clauses_span(tcx: TyCtxt<'_>, def_id: DefId) -> Option<Span> {
+ if !def_id.is_local() {
+ return None;
+ }
+ let hir_id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local());
+ match tcx.hir().find(hir_id) {
+ Some(Node::Item(hir::Item { kind: hir::ItemKind::Fn(_, generics, _), .. })) => {
+ Some(generics.where_clause_span)
+ }
+ _ => {
+ span_bug!(tcx.def_span(def_id), "main has a non-function type");
+ }
+ }
+ }
+
+ fn main_fn_asyncness_span(tcx: TyCtxt<'_>, def_id: DefId) -> Option<Span> {
+ if !def_id.is_local() {
+ return None;
+ }
+ Some(tcx.def_span(def_id))
+ }
+
+ fn main_fn_return_type_span(tcx: TyCtxt<'_>, def_id: DefId) -> Option<Span> {
+ if !def_id.is_local() {
+ return None;
+ }
+ let hir_id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local());
+ match tcx.hir().find(hir_id) {
+ Some(Node::Item(hir::Item { kind: hir::ItemKind::Fn(fn_sig, _, _), .. })) => {
+ Some(fn_sig.decl.output.span())
+ }
+ _ => {
+ span_bug!(tcx.def_span(def_id), "main has a non-function type");
+ }
+ }
+ }
+
+ let mut error = false;
+ let main_diagnostics_def_id = main_fn_diagnostics_def_id(tcx, main_def_id, main_span);
+ let main_fn_generics = tcx.generics_of(main_def_id);
+ let main_fn_predicates = tcx.predicates_of(main_def_id);
+ if main_fn_generics.count() != 0 || !main_fnsig.bound_vars().is_empty() {
+ let generics_param_span = main_fn_generics_params_span(tcx, main_def_id);
+ tcx.sess.emit_err(errors::MainFunctionGenericParameters {
+ span: generics_param_span.unwrap_or(main_span),
+ label_span: generics_param_span,
+ });
+ error = true;
+ } else if !main_fn_predicates.predicates.is_empty() {
+ // generics may bring in implicit predicates, so we skip this check if generics is present.
+ let generics_where_clauses_span = main_fn_where_clauses_span(tcx, main_def_id);
+ tcx.sess.emit_err(errors::WhereClauseOnMain {
+ span: generics_where_clauses_span.unwrap_or(main_span),
+ generics_span: generics_where_clauses_span,
+ });
+ error = true;
+ }
+
+ let main_asyncness = tcx.asyncness(main_def_id);
+ if let hir::IsAsync::Async = main_asyncness {
+ let asyncness_span = main_fn_asyncness_span(tcx, main_def_id);
+ tcx.sess.emit_err(errors::MainFunctionAsync { span: main_span, asyncness: asyncness_span });
+ error = true;
+ }
+
+ for attr in tcx.get_attrs(main_def_id, sym::track_caller) {
+ tcx.sess.emit_err(errors::TrackCallerOnMain { span: attr.span, annotated: main_span });
+ error = true;
+ }
+
+ if !tcx.codegen_fn_attrs(main_def_id).target_features.is_empty()
+ // Calling functions with `#[target_feature]` is not unsafe on WASM, see #84988
+ && !tcx.sess.target.is_like_wasm
+ && !tcx.sess.opts.actually_rustdoc
+ {
+ tcx.sess.emit_err(errors::TargetFeatureOnMain { main: main_span });
+ error = true;
+ }
+
+ if error {
+ return;
+ }
+
+ // Main should have no WC, so empty param env is OK here.
+ let param_env = ty::ParamEnv::empty();
+ let expected_return_type;
+ if let Some(term_did) = tcx.lang_items().termination() {
+ let return_ty = main_fnsig.output();
+ let return_ty_span = main_fn_return_type_span(tcx, main_def_id).unwrap_or(main_span);
+ if !return_ty.bound_vars().is_empty() {
+ tcx.sess.emit_err(errors::MainFunctionReturnTypeGeneric { span: return_ty_span });
+ error = true;
+ }
+ let return_ty = return_ty.skip_binder();
+ let infcx = tcx.infer_ctxt().build();
+ let cause = traits::ObligationCause::new(
+ return_ty_span,
+ main_diagnostics_def_id,
+ ObligationCauseCode::MainFunctionType,
+ );
+ let ocx = traits::ObligationCtxt::new(&infcx);
+ let norm_return_ty = ocx.normalize(&cause, param_env, return_ty);
+ ocx.register_bound(cause, param_env, norm_return_ty, term_did);
+ let errors = ocx.select_all_or_error();
+ if !errors.is_empty() {
+ infcx.err_ctxt().report_fulfillment_errors(&errors);
+ error = true;
+ }
+ // now we can take the return type of the given main function
+ expected_return_type = main_fnsig.output();
+ } else {
+ // standard () main return type
+ expected_return_type = ty::Binder::dummy(Ty::new_unit(tcx));
+ }
+
+ if error {
+ return;
+ }
+
+ let se_ty = Ty::new_fn_ptr(
+ tcx,
+ expected_return_type.map_bound(|expected_return_type| {
+ tcx.mk_fn_sig([], expected_return_type, false, hir::Unsafety::Normal, Abi::Rust)
+ }),
+ );
+
+ require_same_types(
+ tcx,
+ &ObligationCause::new(
+ main_span,
+ main_diagnostics_def_id,
+ ObligationCauseCode::MainFunctionType,
+ ),
+ param_env,
+ se_ty,
+ Ty::new_fn_ptr(tcx, main_fnsig),
+ );
+}
+
+fn check_start_fn_ty(tcx: TyCtxt<'_>, start_def_id: DefId) {
+ let start_def_id = start_def_id.expect_local();
+ let start_id = tcx.hir().local_def_id_to_hir_id(start_def_id);
+ let start_span = tcx.def_span(start_def_id);
+ let start_t = tcx.type_of(start_def_id).instantiate_identity();
+ match start_t.kind() {
+ ty::FnDef(..) => {
+ if let Some(Node::Item(it)) = tcx.hir().find(start_id) {
+ if let hir::ItemKind::Fn(sig, generics, _) = &it.kind {
+ let mut error = false;
+ if !generics.params.is_empty() {
+ tcx.sess.emit_err(errors::StartFunctionParameters { span: generics.span });
+ error = true;
+ }
+ if generics.has_where_clause_predicates {
+ tcx.sess.emit_err(errors::StartFunctionWhere {
+ span: generics.where_clause_span,
+ });
+ error = true;
+ }
+ if let hir::IsAsync::Async = sig.header.asyncness {
+ let span = tcx.def_span(it.owner_id);
+ tcx.sess.emit_err(errors::StartAsync { span: span });
+ error = true;
+ }
+
+ let attrs = tcx.hir().attrs(start_id);
+ for attr in attrs {
+ if attr.has_name(sym::track_caller) {
+ tcx.sess.emit_err(errors::StartTrackCaller {
+ span: attr.span,
+ start: start_span,
+ });
+ error = true;
+ }
+ if attr.has_name(sym::target_feature)
+ // Calling functions with `#[target_feature]` is
+ // not unsafe on WASM, see #84988
+ && !tcx.sess.target.is_like_wasm
+ && !tcx.sess.opts.actually_rustdoc
+ {
+ tcx.sess.emit_err(errors::StartTargetFeature {
+ span: attr.span,
+ start: start_span,
+ });
+ error = true;
+ }
+ }
+
+ if error {
+ return;
+ }
+ }
+ }
+
+ let se_ty = Ty::new_fn_ptr(
+ tcx,
+ ty::Binder::dummy(tcx.mk_fn_sig(
+ [tcx.types.isize, Ty::new_imm_ptr(tcx, Ty::new_imm_ptr(tcx, tcx.types.u8))],
+ tcx.types.isize,
+ false,
+ hir::Unsafety::Normal,
+ Abi::Rust,
+ )),
+ );
+
+ require_same_types(
+ tcx,
+ &ObligationCause::new(
+ start_span,
+ start_def_id,
+ ObligationCauseCode::StartFunctionType,
+ ),
+ ty::ParamEnv::empty(), // start should not have any where bounds.
+ se_ty,
+ Ty::new_fn_ptr(tcx, tcx.fn_sig(start_def_id).instantiate_identity()),
+ );
+ }
+ _ => {
+ span_bug!(start_span, "start has a non-function type: found `{}`", start_t);
+ }
+ }
+}
diff --git a/compiler/rustc_hir_analysis/src/check/intrinsic.rs b/compiler/rustc_hir_analysis/src/check/intrinsic.rs
index 1248f991c..f89e2e5c2 100644
--- a/compiler/rustc_hir_analysis/src/check/intrinsic.rs
+++ b/compiler/rustc_hir_analysis/src/check/intrinsic.rs
@@ -60,7 +60,7 @@ fn equate_intrinsic_type<'tcx>(
tcx,
&cause,
ty::ParamEnv::empty(), // FIXME: do all intrinsics have an empty param env?
- Ty::new_fn_ptr(tcx, tcx.fn_sig(it.owner_id).subst_identity()),
+ Ty::new_fn_ptr(tcx, tcx.fn_sig(it.owner_id).instantiate_identity()),
fty,
);
}
@@ -134,7 +134,7 @@ pub fn intrinsic_operation_unsafety(tcx: TyCtxt<'_>, intrinsic_id: DefId) -> hir
/// Remember to add all intrinsics here, in `compiler/rustc_codegen_llvm/src/intrinsic.rs`,
/// and in `library/core/src/intrinsics.rs`.
pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) {
- let param = |n| Ty::new_param(tcx, n, Symbol::intern(&format!("P{}", n)));
+ let param = |n| Ty::new_param(tcx, n, Symbol::intern(&format!("P{n}")));
let intrinsic_id = it.owner_id.to_def_id();
let intrinsic_name = tcx.item_name(intrinsic_id);
let name_str = intrinsic_name.as_str();
@@ -155,7 +155,7 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) {
ty::INNERMOST,
ty::BoundRegion { var: ty::BoundVar::from_u32(1), kind: ty::BrEnv },
);
- let va_list_ty = tcx.type_of(did).subst(tcx, &[region.into()]);
+ let va_list_ty = tcx.type_of(did).instantiate(tcx, &[region.into()]);
(Ty::new_ref(tcx, env_region, ty::TypeAndMut { ty: va_list_ty, mutbl }), va_list_ty)
})
};
@@ -238,7 +238,7 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) {
ty: Ty::new_adt(
tcx,
tcx.adt_def(option_def_id),
- tcx.mk_substs_from_iter([ty::GenericArg::from(p0)].into_iter()),
+ tcx.mk_args_from_iter([ty::GenericArg::from(p0)].into_iter()),
),
mutbl: hir::Mutability::Not,
},
@@ -273,6 +273,10 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) {
],
Ty::new_unit(tcx),
),
+ sym::compare_bytes => {
+ let byte_ptr = Ty::new_imm_ptr(tcx, tcx.types.u8);
+ (0, vec![byte_ptr, byte_ptr, tcx.types.usize], tcx.types.i32)
+ }
sym::write_bytes | sym::volatile_set_memory => (
1,
vec![
@@ -412,7 +416,7 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) {
ty::Region::new_late_bound(tcx, ty::INNERMOST, br),
param(0),
)],
- Ty::new_projection(tcx, discriminant_def_id, tcx.mk_substs(&[param(0).into()])),
+ Ty::new_projection(tcx, discriminant_def_id, tcx.mk_args(&[param(0).into()])),
)
}
@@ -494,7 +498,7 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) {
/// Type-check `extern "platform-intrinsic" { ... }` functions.
pub fn check_platform_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) {
let param = |n| {
- let name = Symbol::intern(&format!("P{}", n));
+ let name = Symbol::intern(&format!("P{n}"));
Ty::new_param(tcx, n, name)
};
@@ -521,6 +525,10 @@ pub fn check_platform_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>)
| sym::simd_saturating_sub => (1, vec![param(0), param(0)], param(0)),
sym::simd_arith_offset => (2, vec![param(0), param(1)], param(0)),
sym::simd_neg
+ | sym::simd_bswap
+ | sym::simd_bitreverse
+ | sym::simd_ctlz
+ | sym::simd_cttz
| sym::simd_fsqrt
| sym::simd_fsin
| sym::simd_fcos
@@ -563,20 +571,6 @@ pub fn check_platform_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>)
| sym::simd_reduce_min_nanless
| sym::simd_reduce_max_nanless => (2, vec![param(0)], param(1)),
sym::simd_shuffle => (3, vec![param(0), param(0), param(1)], param(2)),
- name if name.as_str().starts_with("simd_shuffle") => {
- match name.as_str()["simd_shuffle".len()..].parse() {
- Ok(n) => {
- let params = vec![param(0), param(0), Ty::new_array(tcx, tcx.types.u32, n)];
- (2, params, param(1))
- }
- Err(_) => {
- let msg =
- format!("unrecognized platform-specific intrinsic function: `{name}`");
- tcx.sess.struct_span_err(it.span, msg).emit();
- return;
- }
- }
- }
_ => {
let msg = format!("unrecognized platform-specific intrinsic function: `{name}`");
tcx.sess.struct_span_err(it.span, msg).emit();
diff --git a/compiler/rustc_hir_analysis/src/check/intrinsicck.rs b/compiler/rustc_hir_analysis/src/check/intrinsicck.rs
index 0bb1467ef..945953edd 100644
--- a/compiler/rustc_hir_analysis/src/check/intrinsicck.rs
+++ b/compiler/rustc_hir_analysis/src/check/intrinsicck.rs
@@ -68,7 +68,7 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> {
let asm_ty = match *ty.kind() {
// `!` is allowed for input but not for output (issue #87802)
ty::Never if is_input => return None,
- ty::Error(_) => return None,
+ _ if ty.references_error() => return None,
ty::Int(IntTy::I8) | ty::Uint(UintTy::U8) => Some(InlineAsmType::I8),
ty::Int(IntTy::I16) | ty::Uint(UintTy::U16) => Some(InlineAsmType::I16),
ty::Int(IntTy::I32) | ty::Uint(UintTy::U32) => Some(InlineAsmType::I32),
@@ -81,9 +81,9 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> {
ty::RawPtr(ty::TypeAndMut { ty, mutbl: _ }) if self.is_thin_ptr_ty(ty) => {
Some(asm_ty_isize)
}
- ty::Adt(adt, substs) if adt.repr().simd() => {
+ ty::Adt(adt, args) if adt.repr().simd() => {
let fields = &adt.non_enum_variant().fields;
- let elem_ty = fields[FieldIdx::from_u32(0)].ty(self.tcx, substs);
+ let elem_ty = fields[FieldIdx::from_u32(0)].ty(self.tcx, args);
let (size, ty) = match elem_ty.kind() {
ty::Array(ty, len) => {
@@ -186,18 +186,14 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> {
let Some((_, feature)) = supported_tys.iter().find(|&&(t, _)| t == asm_ty) else {
let msg = format!("type `{ty}` cannot be used with this register class");
let mut err = self.tcx.sess.struct_span_err(expr.span, msg);
- let supported_tys: Vec<_> =
- supported_tys.iter().map(|(t, _)| t.to_string()).collect();
+ let supported_tys: Vec<_> = supported_tys.iter().map(|(t, _)| t.to_string()).collect();
err.note(format!(
"register class `{}` supports these types: {}",
reg_class.name(),
supported_tys.join(", "),
));
if let Some(suggest) = reg_class.suggest_class(asm_arch, asm_ty) {
- err.help(format!(
- "consider using the `{}` register class instead",
- suggest.name()
- ));
+ err.help(format!("consider using the `{}` register class instead", suggest.name()));
}
err.emit();
return Some(asm_ty);
@@ -215,7 +211,7 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> {
// register class is usable at all.
if let Some(feature) = feature {
if !target_features.contains(feature) {
- let msg = format!("`{}` target feature is not enabled", feature);
+ let msg = format!("`{feature}` target feature is not enabled");
let mut err = self.tcx.sess.struct_span_err(expr.span, msg);
err.note(format!(
"this is required to use type `{}` with register class `{}`",
@@ -427,7 +423,7 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> {
// Check that sym actually points to a function. Later passes
// depend on this.
hir::InlineAsmOperand::SymFn { anon_const } => {
- let ty = self.tcx.type_of(anon_const.def_id).subst_identity();
+ let ty = self.tcx.type_of(anon_const.def_id).instantiate_identity();
match ty.kind() {
ty::Never | ty::Error(_) => {}
ty::FnDef(..) => {}
diff --git a/compiler/rustc_hir_analysis/src/check/mod.rs b/compiler/rustc_hir_analysis/src/check/mod.rs
index ce2da7cb1..4cf358732 100644
--- a/compiler/rustc_hir_analysis/src/check/mod.rs
+++ b/compiler/rustc_hir_analysis/src/check/mod.rs
@@ -38,7 +38,7 @@ can be broken down into several distinct phases:
While type checking a function, the intermediate types for the
expressions, blocks, and so forth contained within the function are
-stored in `fcx.node_types` and `fcx.node_substs`. These types
+stored in `fcx.node_types` and `fcx.node_args`. These types
may contain unresolved type variables. After type checking is
complete, the functions in the writeback module are used to take the
types from this table, resolve them, and then write them into their
@@ -65,6 +65,7 @@ a type parameter).
mod check;
mod compare_impl_item;
pub mod dropck;
+mod entry;
pub mod intrinsic;
pub mod intrinsicck;
mod region;
@@ -80,7 +81,7 @@ use rustc_hir::intravisit::Visitor;
use rustc_index::bit_set::BitSet;
use rustc_middle::query::Providers;
use rustc_middle::ty::{self, Ty, TyCtxt};
-use rustc_middle::ty::{InternalSubsts, SubstsRef};
+use rustc_middle::ty::{GenericArgs, GenericArgsRef};
use rustc_session::parse::feature_err;
use rustc_span::source_map::DUMMY_SP;
use rustc_span::symbol::{kw, Ident};
@@ -188,7 +189,7 @@ fn missing_items_err(
full_impl_span: Span,
) {
let missing_items =
- missing_items.iter().filter(|trait_item| trait_item.opt_rpitit_info.is_none());
+ missing_items.iter().filter(|trait_item| !trait_item.is_impl_trait_in_trait());
let missing_items_msg = missing_items
.clone()
@@ -211,9 +212,9 @@ fn missing_items_err(
let snippet = suggestion_signature(
tcx,
trait_item,
- tcx.impl_trait_ref(impl_def_id).unwrap().subst_identity(),
+ tcx.impl_trait_ref(impl_def_id).unwrap().instantiate_identity(),
);
- let code = format!("{}{}\n{}", padding, snippet, padding);
+ let code = format!("{padding}{snippet}\n{padding}");
if let Some(span) = tcx.hir().span_if_local(trait_item.def_id) {
missing_trait_item_label
.push(errors::MissingTraitItemLabel { span, item: trait_item.name });
@@ -408,7 +409,7 @@ fn fn_sig_suggestion<'tcx>(
let asyncness = if tcx.asyncness(assoc.def_id).is_async() {
output = if let ty::Alias(_, alias_ty) = *output.kind() {
tcx.explicit_item_bounds(alias_ty.def_id)
- .subst_iter_copied(tcx, alias_ty.substs)
+ .iter_instantiated_copied(tcx, alias_ty.args)
.find_map(|(bound, _)| bound.as_projection_clause()?.no_bound_vars()?.term.ty())
.unwrap_or_else(|| {
span_bug!(
@@ -461,10 +462,10 @@ fn suggestion_signature<'tcx>(
assoc: ty::AssocItem,
impl_trait_ref: ty::TraitRef<'tcx>,
) -> String {
- let substs = ty::InternalSubsts::identity_for_item(tcx, assoc.def_id).rebase_onto(
+ let args = ty::GenericArgs::identity_for_item(tcx, assoc.def_id).rebase_onto(
tcx,
assoc.container_id(tcx),
- impl_trait_ref.with_self_ty(tcx, tcx.types.self_param).substs,
+ impl_trait_ref.with_self_ty(tcx, tcx.types.self_param).args,
);
match assoc.kind {
@@ -472,21 +473,21 @@ fn suggestion_signature<'tcx>(
tcx,
tcx.liberate_late_bound_regions(
assoc.def_id,
- tcx.fn_sig(assoc.def_id).subst(tcx, substs),
+ tcx.fn_sig(assoc.def_id).instantiate(tcx, args),
),
assoc.ident(tcx),
- tcx.predicates_of(assoc.def_id).instantiate_own(tcx, substs),
+ tcx.predicates_of(assoc.def_id).instantiate_own(tcx, args),
assoc,
),
ty::AssocKind::Type => {
let (generics, where_clauses) = bounds_from_generic_predicates(
tcx,
- tcx.predicates_of(assoc.def_id).instantiate_own(tcx, substs),
+ tcx.predicates_of(assoc.def_id).instantiate_own(tcx, args),
);
format!("type {}{generics} = /* Type */{where_clauses};", assoc.name)
}
ty::AssocKind::Const => {
- let ty = tcx.type_of(assoc.def_id).subst_identity();
+ let ty = tcx.type_of(assoc.def_id).instantiate_identity();
let val = ty_kind_suggestion(ty).unwrap_or("todo!()");
format!("const {}: {} = {};", assoc.name, ty, val)
}
diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs
index d4748b7ef..f5beefc47 100644
--- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs
+++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs
@@ -5,7 +5,7 @@ use rustc_ast as ast;
use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexSet};
use rustc_errors::{pluralize, struct_span_err, Applicability, DiagnosticBuilder, ErrorGuaranteed};
use rustc_hir as hir;
-use rustc_hir::def_id::{DefId, LocalDefId};
+use rustc_hir::def_id::{DefId, LocalDefId, LocalModDefId};
use rustc_hir::lang_items::LangItem;
use rustc_hir::ItemKind;
use rustc_infer::infer::outlives::env::{OutlivesEnvironment, RegionBoundPairs};
@@ -18,7 +18,7 @@ use rustc_middle::ty::{
self, AdtKind, GenericParamDefKind, ToPredicate, Ty, TyCtxt, TypeFoldable, TypeSuperVisitable,
TypeVisitable, TypeVisitableExt, TypeVisitor,
};
-use rustc_middle::ty::{GenericArgKind, InternalSubsts};
+use rustc_middle::ty::{GenericArgKind, GenericArgs};
use rustc_session::parse::feature_err;
use rustc_span::symbol::{sym, Ident, Symbol};
use rustc_span::{Span, DUMMY_SP};
@@ -75,12 +75,10 @@ impl<'tcx> WfCheckingCtxt<'_, 'tcx> {
self.body_def_id,
ObligationCauseCode::WellFormed(loc),
);
- // for a type to be WF, we do not need to check if const trait predicates satisfy.
- let param_env = self.param_env.without_const();
self.ocx.register_obligation(traits::Obligation::new(
self.tcx(),
cause,
- param_env,
+ self.param_env,
ty::Binder::dummy(ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(arg))),
));
}
@@ -196,7 +194,7 @@ fn check_item<'tcx>(tcx: TyCtxt<'tcx>, item: &'tcx hir::Item<'tcx>) {
// We match on both `ty::ImplPolarity` and `ast::ImplPolarity` just to get the `!` span.
match (tcx.impl_polarity(def_id), impl_.polarity) {
(ty::ImplPolarity::Positive, _) => {
- check_impl(tcx, item, impl_.self_ty, &impl_.of_trait, impl_.constness);
+ check_impl(tcx, item, impl_.self_ty, &impl_.of_trait);
}
(ty::ImplPolarity::Negative, ast::ImplPolarity::Negative(span)) => {
// FIXME(#27579): what amount of WF checking do we need for neg impls?
@@ -247,10 +245,14 @@ fn check_item<'tcx>(tcx: TyCtxt<'tcx>, item: &'tcx hir::Item<'tcx>) {
}
// `ForeignItem`s are handled separately.
hir::ItemKind::ForeignMod { .. } => {}
- hir::ItemKind::TyAlias(hir_ty, ..) => {
- if tcx.type_of(item.owner_id.def_id).skip_binder().has_opaque_types() {
- // Bounds are respected for `type X = impl Trait` and `type X = (impl Trait, Y);`
+ hir::ItemKind::TyAlias(hir_ty, ast_generics) => {
+ if tcx.features().lazy_type_alias
+ || tcx.type_of(item.owner_id).skip_binder().has_opaque_types()
+ {
+ // Bounds of lazy type aliases and of eager ones that contain opaque types are respected.
+ // E.g: `type X = impl Trait;`, `type X = (impl Trait, Y);`.
check_item_type(tcx, def_id, hir_ty.span, UnsizedHandling::Allow);
+ check_variances_for_type_defn(tcx, item, ast_generics);
}
}
_ => {}
@@ -286,11 +288,22 @@ fn check_trait_item(tcx: TyCtxt<'_>, trait_item: &hir::TraitItem<'_>) {
};
check_object_unsafe_self_trait_by_name(tcx, trait_item);
check_associated_item(tcx, def_id, span, method_sig);
+
+ if matches!(trait_item.kind, hir::TraitItemKind::Fn(..)) {
+ for &assoc_ty_def_id in tcx.associated_types_for_impl_traits_in_associated_fn(def_id) {
+ check_associated_item(
+ tcx,
+ assoc_ty_def_id.expect_local(),
+ tcx.def_span(assoc_ty_def_id),
+ None,
+ );
+ }
+ }
}
/// Require that the user writes where clauses on GATs for the implicit
/// outlives bounds involving trait parameters in trait functions and
-/// lifetimes passed as GAT substs. See `self-outlives-lint` test.
+/// lifetimes passed as GAT args. See `self-outlives-lint` test.
///
/// We use the following trait as an example throughout this function:
/// ```rust,ignore (this code fails due to this lint)
@@ -314,7 +327,7 @@ fn check_gat_where_clauses(tcx: TyCtxt<'_>, associated_items: &[hir::TraitItemRe
for gat_item in associated_items {
let gat_def_id = gat_item.id.owner_id;
let gat_item = tcx.associated_item(gat_def_id);
- // If this item is not an assoc ty, or has no substs, then it's not a GAT
+ // If this item is not an assoc ty, or has no args, then it's not a GAT
if gat_item.kind != ty::AssocKind::Type {
continue;
}
@@ -345,7 +358,7 @@ fn check_gat_where_clauses(tcx: TyCtxt<'_>, associated_items: &[hir::TraitItemRe
// `Self::Iter<'a>` is a GAT we want to gather any potential missing bounds from.
let sig: ty::FnSig<'_> = tcx.liberate_late_bound_regions(
item_def_id.to_def_id(),
- tcx.fn_sig(item_def_id).subst_identity(),
+ tcx.fn_sig(item_def_id).instantiate_identity(),
);
gather_gat_bounds(
tcx,
@@ -374,7 +387,7 @@ fn check_gat_where_clauses(tcx: TyCtxt<'_>, associated_items: &[hir::TraitItemRe
param_env,
item_def_id,
tcx.explicit_item_bounds(item_def_id)
- .subst_identity_iter_copied()
+ .instantiate_identity_iter_copied()
.collect::<Vec<_>>(),
&FxIndexSet::default(),
gat_def_id.def_id,
@@ -472,8 +485,7 @@ fn check_gat_where_clauses(tcx: TyCtxt<'_>, associated_items: &[hir::TraitItemRe
let bound =
if unsatisfied_bounds.len() > 1 { "these bounds are" } else { "this bound is" };
err.note(format!(
- "{} currently required to ensure that impls have maximum flexibility",
- bound
+ "{bound} currently required to ensure that impls have maximum flexibility"
));
err.note(
"we are soliciting feedback, see issue #87479 \
@@ -505,7 +517,7 @@ fn augment_param_env<'tcx>(
);
// FIXME(compiler-errors): Perhaps there is a case where we need to normalize this
// i.e. traits::normalize_param_env_or_error
- ty::ParamEnv::new(bounds, param_env.reveal(), param_env.constness())
+ ty::ParamEnv::new(bounds, param_env.reveal())
}
/// We use the following trait as an example throughout this function.
@@ -544,8 +556,8 @@ fn gather_gat_bounds<'tcx, T: TypeFoldable<TyCtxt<'tcx>>>(
for (region_a, region_a_idx) in &regions {
// Ignore `'static` lifetimes for the purpose of this lint: it's
// because we know it outlives everything and so doesn't give meaningful
- // clues
- if let ty::ReStatic = **region_a {
+ // clues. Also ignore `ReError`, to avoid knock-down errors.
+ if let ty::ReStatic | ty::ReError(_) = **region_a {
continue;
}
// For each region argument (e.g., `'a` in our example), check for a
@@ -588,8 +600,9 @@ fn gather_gat_bounds<'tcx, T: TypeFoldable<TyCtxt<'tcx>>>(
// on the GAT itself.
for (region_b, region_b_idx) in &regions {
// Again, skip `'static` because it outlives everything. Also, we trivially
- // know that a region outlives itself.
- if ty::ReStatic == **region_b || region_a == region_b {
+ // know that a region outlives itself. Also ignore `ReError`, to avoid
+ // knock-down errors.
+ if matches!(**region_b, ty::ReStatic | ty::ReError(_)) || region_a == region_b {
continue;
}
if region_known_to_outlive(
@@ -737,7 +750,7 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for GATSubstCollector<'tcx> {
fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
match t.kind() {
ty::Alias(ty::Projection, p) if p.def_id == self.gat => {
- for (idx, subst) in p.substs.iter().enumerate() {
+ for (idx, subst) in p.args.iter().enumerate() {
match subst.unpack() {
GenericArgKind::Lifetime(lt) if !lt.is_late_bound() => {
self.regions.insert((lt, idx));
@@ -836,7 +849,7 @@ fn check_param_wf(tcx: TyCtxt<'_>, param: &hir::GenericParam<'_>) {
// Const parameters are well formed if their type is structural match.
hir::GenericParamKind::Const { ty: hir_ty, default: _ } => {
- let ty = tcx.type_of(param.def_id).subst_identity();
+ let ty = tcx.type_of(param.def_id).instantiate_identity();
if tcx.features().adt_const_params {
enter_wf_checking_ctxt(tcx, hir_ty.span, param.def_id, |wfcx| {
@@ -910,17 +923,17 @@ fn check_associated_item(
let self_ty = match item.container {
ty::TraitContainer => tcx.types.self_param,
- ty::ImplContainer => tcx.type_of(item.container_id(tcx)).subst_identity(),
+ ty::ImplContainer => tcx.type_of(item.container_id(tcx)).instantiate_identity(),
};
match item.kind {
ty::AssocKind::Const => {
- let ty = tcx.type_of(item.def_id).subst_identity();
+ let ty = tcx.type_of(item.def_id).instantiate_identity();
let ty = wfcx.normalize(span, Some(WellFormedLoc::Ty(item_id)), ty);
wfcx.register_wf_obligation(span, loc, ty.into());
}
ty::AssocKind::Fn => {
- let sig = tcx.fn_sig(item.def_id).subst_identity();
+ let sig = tcx.fn_sig(item.def_id).instantiate_identity();
let hir_sig = sig_if_method.expect("bad signature for method");
check_fn_or_method(
wfcx,
@@ -936,7 +949,7 @@ fn check_associated_item(
check_associated_type_bounds(wfcx, item, span)
}
if item.defaultness(tcx).has_value() {
- let ty = tcx.type_of(item.def_id).subst_identity();
+ let ty = tcx.type_of(item.def_id).instantiate_identity();
let ty = wfcx.normalize(span, Some(WellFormedLoc::Ty(item_id)), ty);
wfcx.register_wf_obligation(span, loc, ty.into());
}
@@ -969,7 +982,11 @@ fn check_type_defn<'tcx>(tcx: TyCtxt<'tcx>, item: &hir::Item<'tcx>, all_sized: b
let field_id = field.did.expect_local();
let hir::FieldDef { ty: hir_ty, .. } =
tcx.hir().get_by_def_id(field_id).expect_field();
- let ty = wfcx.normalize(hir_ty.span, None, tcx.type_of(field.did).subst_identity());
+ let ty = wfcx.normalize(
+ hir_ty.span,
+ None,
+ tcx.type_of(field.did).instantiate_identity(),
+ );
wfcx.register_wf_obligation(
hir_ty.span,
Some(WellFormedLoc::Ty(field_id)),
@@ -981,11 +998,11 @@ fn check_type_defn<'tcx>(tcx: TyCtxt<'tcx>, item: &hir::Item<'tcx>, all_sized: b
// intermediate types must be sized.
let needs_drop_copy = || {
packed && {
- let ty = tcx.type_of(variant.tail().did).subst_identity();
+ let ty = tcx.type_of(variant.tail().did).instantiate_identity();
let ty = tcx.erase_regions(ty);
if ty.has_infer() {
tcx.sess
- .delay_span_bug(item.span, format!("inference variables in {:?}", ty));
+ .delay_span_bug(item.span, format!("inference variables in {ty:?}"));
// Just treat unresolved type expression as if it needs drop.
true
} else {
@@ -1003,7 +1020,11 @@ fn check_type_defn<'tcx>(tcx: TyCtxt<'tcx>, item: &hir::Item<'tcx>, all_sized: b
let field_id = field.did.expect_local();
let hir::FieldDef { ty: hir_ty, .. } =
tcx.hir().get_by_def_id(field_id).expect_field();
- let ty = wfcx.normalize(hir_ty.span, None, tcx.type_of(field.did).subst_identity());
+ let ty = wfcx.normalize(
+ hir_ty.span,
+ None,
+ tcx.type_of(field.did).instantiate_identity(),
+ );
wfcx.register_bound(
traits::ObligationCause::new(
hir_ty.span,
@@ -1083,16 +1104,17 @@ fn check_associated_type_bounds(wfcx: &WfCheckingCtxt<'_, '_>, item: ty::AssocIt
let bounds = wfcx.tcx().explicit_item_bounds(item.def_id);
debug!("check_associated_type_bounds: bounds={:?}", bounds);
- let wf_obligations = bounds.subst_identity_iter_copied().flat_map(|(bound, bound_span)| {
- let normalized_bound = wfcx.normalize(span, None, bound);
- traits::wf::predicate_obligations(
- wfcx.infcx,
- wfcx.param_env,
- wfcx.body_def_id,
- normalized_bound.as_predicate(),
- bound_span,
- )
- });
+ let wf_obligations =
+ bounds.instantiate_identity_iter_copied().flat_map(|(bound, bound_span)| {
+ let normalized_bound = wfcx.normalize(span, None, bound);
+ traits::wf::predicate_obligations(
+ wfcx.infcx,
+ wfcx.param_env,
+ wfcx.body_def_id,
+ normalized_bound.as_predicate(),
+ bound_span,
+ )
+ });
wfcx.register_obligations(wf_obligations);
}
@@ -1105,7 +1127,7 @@ fn check_item_fn(
decl: &hir::FnDecl<'_>,
) {
enter_wf_checking_ctxt(tcx, span, def_id, |wfcx| {
- let sig = tcx.fn_sig(def_id).subst_identity();
+ let sig = tcx.fn_sig(def_id).instantiate_identity();
check_fn_or_method(wfcx, ident.span, sig, decl, def_id);
})
}
@@ -1125,7 +1147,7 @@ fn check_item_type(
debug!("check_item_type: {:?}", item_id);
enter_wf_checking_ctxt(tcx, ty_span, item_id, |wfcx| {
- let ty = tcx.type_of(item_id).subst_identity();
+ let ty = tcx.type_of(item_id).instantiate_identity();
let item_ty = wfcx.normalize(ty_span, Some(WellFormedLoc::Ty(item_id)), ty);
let forbid_unsized = match unsized_handling {
@@ -1170,7 +1192,6 @@ fn check_impl<'tcx>(
item: &'tcx hir::Item<'tcx>,
ast_self_ty: &hir::Ty<'_>,
ast_trait_ref: &Option<hir::TraitRef<'_>>,
- constness: hir::Constness,
) {
enter_wf_checking_ctxt(tcx, item.span, item.owner_id.def_id, |wfcx| {
match ast_trait_ref {
@@ -1178,20 +1199,14 @@ fn check_impl<'tcx>(
// `#[rustc_reservation_impl]` impls are not real impls and
// therefore don't need to be WF (the trait's `Self: Trait` predicate
// won't hold).
- let trait_ref = tcx.impl_trait_ref(item.owner_id).unwrap().subst_identity();
+ let trait_ref = tcx.impl_trait_ref(item.owner_id).unwrap().instantiate_identity();
let trait_ref = wfcx.normalize(
ast_trait_ref.path.span,
Some(WellFormedLoc::Ty(item.hir_id().expect_owner().def_id)),
trait_ref,
);
- let trait_pred = ty::TraitPredicate {
- trait_ref,
- constness: match constness {
- hir::Constness::Const => ty::BoundConstness::ConstIfConst,
- hir::Constness::NotConst => ty::BoundConstness::NotConst,
- },
- polarity: ty::ImplPolarity::Positive,
- };
+ let trait_pred =
+ ty::TraitPredicate { trait_ref, polarity: ty::ImplPolarity::Positive };
let mut obligations = traits::wf::trait_obligations(
wfcx.infcx,
wfcx.param_env,
@@ -1211,7 +1226,7 @@ fn check_impl<'tcx>(
wfcx.register_obligations(obligations);
}
None => {
- let self_ty = tcx.type_of(item.owner_id).subst_identity();
+ let self_ty = tcx.type_of(item.owner_id).instantiate_identity();
let self_ty = wfcx.normalize(
item.span,
Some(WellFormedLoc::Ty(item.hir_id().expect_owner().def_id)),
@@ -1256,7 +1271,7 @@ fn check_where_clauses<'tcx>(wfcx: &WfCheckingCtxt<'_, 'tcx>, span: Span, def_id
match param.kind {
GenericParamDefKind::Type { .. } => {
if is_our_default(param) {
- let ty = tcx.type_of(param.def_id).subst_identity();
+ let ty = tcx.type_of(param.def_id).instantiate_identity();
// Ignore dependent defaults -- that is, where the default of one type
// parameter includes another (e.g., `<T, U = T>`). In those cases, we can't
// be sure if it will error or not as user might always specify the other.
@@ -1272,10 +1287,10 @@ fn check_where_clauses<'tcx>(wfcx: &WfCheckingCtxt<'_, 'tcx>, span: Span, def_id
GenericParamDefKind::Const { .. } => {
if is_our_default(param) {
// FIXME(const_generics_defaults): This
- // is incorrect when dealing with unused substs, for example
+ // is incorrect when dealing with unused args, for example
// for `struct Foo<const N: usize, const M: usize = { 1 - 2 }>`
// we should eagerly error.
- let default_ct = tcx.const_param_default(param.def_id).subst_identity();
+ let default_ct = tcx.const_param_default(param.def_id).instantiate_identity();
if !default_ct.has_param() {
wfcx.register_wf_obligation(
tcx.def_span(param.def_id),
@@ -1298,7 +1313,7 @@ fn check_where_clauses<'tcx>(wfcx: &WfCheckingCtxt<'_, 'tcx>, span: Span, def_id
// For more examples see tests `defaults-well-formedness.rs` and `type-check-defaults.rs`.
//
// First we build the defaulted substitution.
- let substs = InternalSubsts::for_item(tcx, def_id.to_def_id(), |param, _| {
+ let args = GenericArgs::for_item(tcx, def_id.to_def_id(), |param, _| {
match param.kind {
GenericParamDefKind::Lifetime => {
// All regions are identity.
@@ -1308,7 +1323,7 @@ fn check_where_clauses<'tcx>(wfcx: &WfCheckingCtxt<'_, 'tcx>, span: Span, def_id
GenericParamDefKind::Type { .. } => {
// If the param has a default, ...
if is_our_default(param) {
- let default_ty = tcx.type_of(param.def_id).subst_identity();
+ let default_ty = tcx.type_of(param.def_id).instantiate_identity();
// ... and it's not a dependent default, ...
if !default_ty.has_param() {
// ... then substitute it with the default.
@@ -1321,7 +1336,7 @@ fn check_where_clauses<'tcx>(wfcx: &WfCheckingCtxt<'_, 'tcx>, span: Span, def_id
GenericParamDefKind::Const { .. } => {
// If the param has a default, ...
if is_our_default(param) {
- let default_ct = tcx.const_param_default(param.def_id).subst_identity();
+ let default_ct = tcx.const_param_default(param.def_id).instantiate_identity();
// ... and it's not a dependent default, ...
if !default_ct.has_param() {
// ... then substitute it with the default.
@@ -1366,7 +1381,7 @@ fn check_where_clauses<'tcx>(wfcx: &WfCheckingCtxt<'_, 'tcx>, span: Span, def_id
}
let mut param_count = CountParams::default();
let has_region = pred.visit_with(&mut param_count).is_break();
- let substituted_pred = ty::EarlyBinder::bind(pred).subst(tcx, substs);
+ let substituted_pred = ty::EarlyBinder::bind(pred).instantiate(tcx, args);
// Don't check non-defaulted params, dependent defaults (including lifetimes)
// or preds with multiple params.
if substituted_pred.has_non_region_param() || param_count.params.len() > 1 || has_region
@@ -1407,7 +1422,7 @@ fn check_where_clauses<'tcx>(wfcx: &WfCheckingCtxt<'_, 'tcx>, span: Span, def_id
let wf_obligations = predicates.into_iter().flat_map(|(p, sp)| {
traits::wf::predicate_obligations(
infcx,
- wfcx.param_env.without_const(),
+ wfcx.param_env,
wfcx.body_def_id,
p.as_predicate(),
sp,
@@ -1460,13 +1475,6 @@ fn check_fn_or_method<'tcx>(
check_where_clauses(wfcx, span, def_id);
- check_return_position_impl_trait_in_trait_bounds(
- wfcx,
- def_id,
- sig.output(),
- hir_decl.output.span(),
- );
-
if sig.abi == Abi::RustCall {
let span = tcx.def_span(def_id);
let has_implicit_self = hir_decl.implicit_self != hir::ImplicitSelfKind::None;
@@ -1501,87 +1509,6 @@ fn check_fn_or_method<'tcx>(
}
}
-/// Basically `check_associated_type_bounds`, but separated for now and should be
-/// deduplicated when RPITITs get lowered into real associated items.
-#[tracing::instrument(level = "trace", skip(wfcx))]
-fn check_return_position_impl_trait_in_trait_bounds<'tcx>(
- wfcx: &WfCheckingCtxt<'_, 'tcx>,
- fn_def_id: LocalDefId,
- fn_output: Ty<'tcx>,
- span: Span,
-) {
- let tcx = wfcx.tcx();
- let Some(assoc_item) = tcx.opt_associated_item(fn_def_id.to_def_id()) else {
- return;
- };
- if assoc_item.container != ty::AssocItemContainer::TraitContainer {
- return;
- }
- fn_output.visit_with(&mut ImplTraitInTraitFinder {
- wfcx,
- fn_def_id,
- depth: ty::INNERMOST,
- seen: FxHashSet::default(),
- });
-}
-
-// FIXME(-Zlower-impl-trait-in-trait-to-assoc-ty): Even with the new lowering
-// strategy, we can't just call `check_associated_item` on the new RPITITs,
-// because tests like `tests/ui/async-await/in-trait/implied-bounds.rs` will fail.
-// That's because we need to check that the bounds of the RPITIT hold using
-// the special substs that we create during opaque type lowering, otherwise we're
-// getting a bunch of early bound and free regions mixed up... Haven't looked too
-// deep into this, though.
-struct ImplTraitInTraitFinder<'a, 'tcx> {
- wfcx: &'a WfCheckingCtxt<'a, 'tcx>,
- fn_def_id: LocalDefId,
- depth: ty::DebruijnIndex,
- seen: FxHashSet<DefId>,
-}
-impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for ImplTraitInTraitFinder<'_, 'tcx> {
- type BreakTy = !;
-
- fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow<!> {
- let tcx = self.wfcx.tcx();
- if let ty::Alias(ty::Opaque, unshifted_opaque_ty) = *ty.kind()
- && self.seen.insert(unshifted_opaque_ty.def_id)
- && let Some(opaque_def_id) = unshifted_opaque_ty.def_id.as_local()
- && let origin = tcx.opaque_type_origin(opaque_def_id)
- && let hir::OpaqueTyOrigin::FnReturn(source) | hir::OpaqueTyOrigin::AsyncFn(source) = origin
- && source == self.fn_def_id
- {
- let opaque_ty = tcx.fold_regions(unshifted_opaque_ty, |re, _depth| {
- match re.kind() {
- ty::ReEarlyBound(_) | ty::ReFree(_) | ty::ReError(_) | ty::ReStatic => re,
- r => bug!("unexpected region: {r:?}"),
- }
- });
- for (bound, bound_span) in tcx
- .explicit_item_bounds(opaque_ty.def_id)
- .subst_iter_copied(tcx, opaque_ty.substs)
- {
- let bound = self.wfcx.normalize(bound_span, None, bound);
- self.wfcx.register_obligations(traits::wf::predicate_obligations(
- self.wfcx.infcx,
- self.wfcx.param_env,
- self.wfcx.body_def_id,
- bound.as_predicate(),
- bound_span,
- ));
- // Set the debruijn index back to innermost here, since we already eagerly
- // shifted the substs that we use to generate these bounds. This is unfortunately
- // subtly different behavior than the `ImplTraitInTraitFinder` we use in `param_env`,
- // but that function doesn't actually need to normalize the bound it's visiting
- // (whereas we have to do so here)...
- let old_depth = std::mem::replace(&mut self.depth, ty::INNERMOST);
- bound.visit_with(self);
- self.depth = old_depth;
- }
- }
- ty.super_visit_with(self)
- }
-}
-
const HELP_FOR_SELF_TYPE: &str = "consider changing to `self`, `&self`, `&mut self`, `self: Box<Self>`, \
`self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one \
of the previous types except `Self`)";
@@ -1601,7 +1528,7 @@ fn check_method_receiver<'tcx>(
let span = fn_sig.decl.inputs[0].span;
- let sig = tcx.fn_sig(method.def_id).subst_identity();
+ let sig = tcx.fn_sig(method.def_id).instantiate_identity();
let sig = tcx.liberate_late_bound_regions(method.def_id, sig);
let sig = wfcx.normalize(span, None, sig);
@@ -1773,11 +1700,28 @@ fn check_variances_for_type_defn<'tcx>(
item: &hir::Item<'tcx>,
hir_generics: &hir::Generics<'_>,
) {
- let identity_substs = ty::InternalSubsts::identity_for_item(tcx, item.owner_id);
- for field in tcx.adt_def(item.owner_id).all_fields() {
- if field.ty(tcx, identity_substs).references_error() {
- return;
+ let identity_args = ty::GenericArgs::identity_for_item(tcx, item.owner_id);
+
+ match item.kind {
+ ItemKind::Enum(..) | ItemKind::Struct(..) | ItemKind::Union(..) => {
+ for field in tcx.adt_def(item.owner_id).all_fields() {
+ if field.ty(tcx, identity_args).references_error() {
+ return;
+ }
+ }
+ }
+ ItemKind::TyAlias(..) => {
+ let ty = tcx.type_of(item.owner_id).instantiate_identity();
+
+ if tcx.features().lazy_type_alias || ty.has_opaque_types() {
+ if ty.references_error() {
+ return;
+ }
+ } else {
+ bug!();
+ }
}
+ _ => bug!(),
}
let ty_predicates = tcx.predicates_of(item.owner_id);
@@ -1854,8 +1798,7 @@ fn report_bivariance(
if matches!(param.kind, hir::GenericParamKind::Type { .. }) && !has_explicit_bounds {
err.help(format!(
- "if you intended `{0}` to be a const parameter, use `const {0}: usize` instead",
- param_name
+ "if you intended `{param_name}` to be a const parameter, use `const {param_name}: usize` instead"
));
}
err.emit()
@@ -1911,7 +1854,7 @@ impl<'tcx> WfCheckingCtxt<'_, 'tcx> {
}
}
-fn check_mod_type_wf(tcx: TyCtxt<'_>, module: LocalDefId) {
+fn check_mod_type_wf(tcx: TyCtxt<'_>, module: LocalModDefId) {
let items = tcx.hir_module_items(module);
items.par_items(|item| tcx.ensure().check_well_formed(item.owner_id));
items.par_impl_items(|item| tcx.ensure().check_well_formed(item.owner_id));