summaryrefslogtreecommitdiffstats
path: root/compiler/rustc_ty_utils
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-30 03:57:31 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-30 03:57:31 +0000
commitdc0db358abe19481e475e10c32149b53370f1a1c (patch)
treeab8ce99c4b255ce46f99ef402c27916055b899ee /compiler/rustc_ty_utils
parentReleasing progress-linux version 1.71.1+dfsg1-2~progress7.99u1. (diff)
downloadrustc-dc0db358abe19481e475e10c32149b53370f1a1c.tar.xz
rustc-dc0db358abe19481e475e10c32149b53370f1a1c.zip
Merging upstream version 1.72.1+dfsg1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'compiler/rustc_ty_utils')
-rw-r--r--compiler/rustc_ty_utils/Cargo.toml1
-rw-r--r--compiler/rustc_ty_utils/src/abi.rs36
-rw-r--r--compiler/rustc_ty_utils/src/assoc.rs29
-rw-r--r--compiler/rustc_ty_utils/src/consts.rs45
-rw-r--r--compiler/rustc_ty_utils/src/errors.rs2
-rw-r--r--compiler/rustc_ty_utils/src/implied_bounds.rs76
-rw-r--r--compiler/rustc_ty_utils/src/instance.rs147
-rw-r--r--compiler/rustc_ty_utils/src/layout.rs208
-rw-r--r--compiler/rustc_ty_utils/src/needs_drop.rs2
-rw-r--r--compiler/rustc_ty_utils/src/opaque_types.rs298
-rw-r--r--compiler/rustc_ty_utils/src/ty.rs165
11 files changed, 557 insertions, 452 deletions
diff --git a/compiler/rustc_ty_utils/Cargo.toml b/compiler/rustc_ty_utils/Cargo.toml
index 51885c9b4..50dac3a37 100644
--- a/compiler/rustc_ty_utils/Cargo.toml
+++ b/compiler/rustc_ty_utils/Cargo.toml
@@ -5,6 +5,7 @@ edition = "2021"
[dependencies]
tracing = "0.1"
+itertools = "0.10.1"
rustc_middle = { path = "../rustc_middle" }
rustc_data_structures = { path = "../rustc_data_structures" }
rustc_errors = { path = "../rustc_errors" }
diff --git a/compiler/rustc_ty_utils/src/abi.rs b/compiler/rustc_ty_utils/src/abi.rs
index 15c191046..55484f5c7 100644
--- a/compiler/rustc_ty_utils/src/abi.rs
+++ b/compiler/rustc_ty_utils/src/abi.rs
@@ -64,7 +64,7 @@ fn fn_sig_for_fn_abi<'tcx>(
// Modify `fn(self, ...)` to `fn(self: *mut Self, ...)`.
sig = sig.map_bound(|mut sig| {
let mut inputs_and_output = sig.inputs_and_output.to_vec();
- inputs_and_output[0] = tcx.mk_mut_ptr(inputs_and_output[0]);
+ inputs_and_output[0] = Ty::new_mut_ptr(tcx, inputs_and_output[0]);
sig.inputs_and_output = tcx.mk_type_list(&inputs_and_output);
sig
});
@@ -81,7 +81,7 @@ fn fn_sig_for_fn_abi<'tcx>(
var: ty::BoundVar::from_usize(bound_vars.len() - 1),
kind: ty::BoundRegionKind::BrEnv,
};
- let env_region = tcx.mk_re_late_bound(ty::INNERMOST, br);
+ let env_region = ty::Region::new_late_bound(tcx, ty::INNERMOST, br);
let env_ty = tcx.closure_env_ty(def_id, substs, env_region).unwrap();
let sig = sig.skip_binder();
@@ -106,12 +106,13 @@ fn fn_sig_for_fn_abi<'tcx>(
var: ty::BoundVar::from_usize(bound_vars.len() - 1),
kind: ty::BoundRegionKind::BrEnv,
};
- let env_ty = tcx.mk_mut_ref(tcx.mk_re_late_bound(ty::INNERMOST, br), ty);
+ let env_ty =
+ Ty::new_mut_ref(tcx, ty::Region::new_late_bound(tcx, ty::INNERMOST, br), ty);
let pin_did = tcx.require_lang_item(LangItem::Pin, None);
let pin_adt_ref = tcx.adt_def(pin_did);
let pin_substs = tcx.mk_substs(&[env_ty.into()]);
- let env_ty = tcx.mk_adt(pin_adt_ref, pin_substs);
+ let env_ty = Ty::new_adt(tcx, pin_adt_ref, pin_substs);
let sig = sig.skip_binder();
// The `FnSig` and the `ret_ty` here is for a generators main
@@ -123,7 +124,7 @@ fn fn_sig_for_fn_abi<'tcx>(
let poll_did = tcx.require_lang_item(LangItem::Poll, None);
let poll_adt_ref = tcx.adt_def(poll_did);
let poll_substs = tcx.mk_substs(&[sig.return_ty.into()]);
- let ret_ty = tcx.mk_adt(poll_adt_ref, poll_substs);
+ let ret_ty = Ty::new_adt(tcx, poll_adt_ref, poll_substs);
// We have to replace the `ResumeTy` that is used for type and borrow checking
// with `&mut Context<'_>` which is used in codegen.
@@ -137,7 +138,7 @@ fn fn_sig_for_fn_abi<'tcx>(
panic!("expected `ResumeTy`, found `{:?}`", sig.resume_ty);
};
}
- let context_mut_ref = tcx.mk_task_context();
+ let context_mut_ref = Ty::new_task_context(tcx);
(context_mut_ref, ret_ty)
} else {
@@ -145,7 +146,7 @@ fn fn_sig_for_fn_abi<'tcx>(
let state_did = tcx.require_lang_item(LangItem::GeneratorState, None);
let state_adt_ref = tcx.adt_def(state_did);
let state_substs = tcx.mk_substs(&[sig.yield_ty.into(), sig.return_ty.into()]);
- let ret_ty = tcx.mk_adt(state_adt_ref, state_substs);
+ let ret_ty = Ty::new_adt(tcx, state_adt_ref, state_substs);
(sig.resume_ty, ret_ty)
};
@@ -202,7 +203,7 @@ fn conv_from_spec_abi(tcx: TyCtxt<'_>, abi: SpecAbi) -> Conv {
fn fn_abi_of_fn_ptr<'tcx>(
tcx: TyCtxt<'tcx>,
query: ty::ParamEnvAnd<'tcx, (ty::PolyFnSig<'tcx>, &'tcx ty::List<Ty<'tcx>>)>,
-) -> Result<&'tcx FnAbi<'tcx, Ty<'tcx>>, FnAbiError<'tcx>> {
+) -> Result<&'tcx FnAbi<'tcx, Ty<'tcx>>, &'tcx FnAbiError<'tcx>> {
let (param_env, (sig, extra_args)) = query.into_parts();
let cx = LayoutCx { tcx, param_env };
@@ -212,7 +213,7 @@ fn fn_abi_of_fn_ptr<'tcx>(
fn fn_abi_of_instance<'tcx>(
tcx: TyCtxt<'tcx>,
query: ty::ParamEnvAnd<'tcx, (ty::Instance<'tcx>, &'tcx ty::List<Ty<'tcx>>)>,
-) -> Result<&'tcx FnAbi<'tcx, Ty<'tcx>>, FnAbiError<'tcx>> {
+) -> Result<&'tcx FnAbi<'tcx, Ty<'tcx>>, &'tcx FnAbiError<'tcx>> {
let (param_env, (instance, extra_args)) = query.into_parts();
let sig = fn_sig_for_fn_abi(tcx, instance, param_env);
@@ -331,7 +332,7 @@ fn fn_abi_new_uncached<'tcx>(
fn_def_id: Option<DefId>,
// FIXME(eddyb) replace this with something typed, like an `enum`.
force_thin_self_ptr: bool,
-) -> Result<&'tcx FnAbi<'tcx, Ty<'tcx>>, FnAbiError<'tcx>> {
+) -> Result<&'tcx FnAbi<'tcx, Ty<'tcx>>, &'tcx FnAbiError<'tcx>> {
let sig = cx.tcx.normalize_erasing_late_bound_regions(cx.param_env, sig);
let conv = conv_from_spec_abi(cx.tcx(), sig.abi);
@@ -376,7 +377,7 @@ fn fn_abi_new_uncached<'tcx>(
let is_drop_in_place =
fn_def_id.is_some() && fn_def_id == cx.tcx.lang_items().drop_in_place_fn();
- let arg_of = |ty: Ty<'tcx>, arg_idx: Option<usize>| -> Result<_, FnAbiError<'tcx>> {
+ let arg_of = |ty: Ty<'tcx>, arg_idx: Option<usize>| -> Result<_, &'tcx FnAbiError<'tcx>> {
let span = tracing::debug_span!("arg_of");
let _entered = span.enter();
let is_return = arg_idx.is_none();
@@ -386,7 +387,8 @@ fn fn_abi_new_uncached<'tcx>(
_ => bug!("argument to drop_in_place is not a raw ptr: {:?}", ty),
});
- let layout = cx.layout_of(ty)?;
+ let layout =
+ cx.layout_of(ty).map_err(|err| &*cx.tcx.arena.alloc(FnAbiError::Layout(*err)))?;
let layout = if force_thin_self_ptr && arg_idx == Some(0) {
// Don't pass the vtable, it's not an argument of the virtual fn.
// Instead, pass just the data pointer, but give it the type `*const/mut dyn Trait`
@@ -454,7 +456,7 @@ fn fn_abi_adjust_for_abi<'tcx>(
fn_abi: &mut FnAbi<'tcx, Ty<'tcx>>,
abi: SpecAbi,
fn_def_id: Option<DefId>,
-) -> Result<(), FnAbiError<'tcx>> {
+) -> Result<(), &'tcx FnAbiError<'tcx>> {
if abi == SpecAbi::Unadjusted {
return Ok(());
}
@@ -548,7 +550,9 @@ fn fn_abi_adjust_for_abi<'tcx>(
fixup(arg, Some(arg_idx));
}
} else {
- fn_abi.adjust_for_foreign_abi(cx, abi)?;
+ fn_abi
+ .adjust_for_foreign_abi(cx, abi)
+ .map_err(|err| &*cx.tcx.arena.alloc(FnAbiError::AdjustForForeignAbi(err)))?;
}
Ok(())
@@ -563,7 +567,7 @@ fn make_thin_self_ptr<'tcx>(
let fat_pointer_ty = if layout.is_unsized() {
// unsized `self` is passed as a pointer to `self`
// FIXME (mikeyhew) change this to use &own if it is ever added to the language
- tcx.mk_mut_ptr(layout.ty)
+ Ty::new_mut_ptr(tcx, layout.ty)
} else {
match layout.abi {
Abi::ScalarPair(..) | Abi::Scalar(..) => (),
@@ -597,7 +601,7 @@ fn make_thin_self_ptr<'tcx>(
// we now have a type like `*mut RcBox<dyn Trait>`
// change its layout to that of `*mut ()`, a thin pointer, but keep the same type
// this is understood as a special case elsewhere in the compiler
- let unit_ptr_ty = tcx.mk_mut_ptr(tcx.mk_unit());
+ let unit_ptr_ty = Ty::new_mut_ptr(tcx, Ty::new_unit(tcx));
TyAndLayout {
ty: fat_pointer_ty,
diff --git a/compiler/rustc_ty_utils/src/assoc.rs b/compiler/rustc_ty_utils/src/assoc.rs
index ed574f22e..897e7aad4 100644
--- a/compiler/rustc_ty_utils/src/assoc.rs
+++ b/compiler/rustc_ty_utils/src/assoc.rs
@@ -5,7 +5,7 @@ use rustc_hir::def_id::{DefId, DefIdMap, LocalDefId};
use rustc_hir::definitions::DefPathData;
use rustc_hir::intravisit::{self, Visitor};
use rustc_middle::query::Providers;
-use rustc_middle::ty::{self, ImplTraitInTraitData, InternalSubsts, TyCtxt};
+use rustc_middle::ty::{self, ImplTraitInTraitData, InternalSubsts, Ty, TyCtxt};
use rustc_span::symbol::kw;
pub fn provide(providers: &mut Providers) {
@@ -259,7 +259,7 @@ fn associated_type_for_impl_trait_in_trait(
opaque_ty_def_id: LocalDefId,
) -> LocalDefId {
let (hir::OpaqueTyOrigin::FnReturn(fn_def_id) | hir::OpaqueTyOrigin::AsyncFn(fn_def_id)) =
- tcx.hir().expect_item(opaque_ty_def_id).expect_opaque_ty().origin
+ tcx.opaque_type_origin(opaque_ty_def_id)
else {
bug!("expected opaque for {opaque_ty_def_id:?}");
};
@@ -297,11 +297,12 @@ fn associated_type_for_impl_trait_in_trait(
// Copy visility of the containing function.
trait_assoc_ty.visibility(tcx.visibility(fn_def_id));
- // Copy impl_defaultness of the containing function.
- trait_assoc_ty.impl_defaultness(tcx.impl_defaultness(fn_def_id));
+ // Copy defaultness of the containing function.
+ trait_assoc_ty.defaultness(tcx.defaultness(fn_def_id));
// Copy type_of of the opaque.
- trait_assoc_ty.type_of(ty::EarlyBinder(tcx.mk_opaque(
+ trait_assoc_ty.type_of(ty::EarlyBinder::bind(Ty::new_opaque(
+ tcx,
opaque_ty_def_id.to_def_id(),
InternalSubsts::identity_for_item(tcx, opaque_ty_def_id),
)));
@@ -337,15 +338,10 @@ fn associated_type_for_impl_trait_in_trait(
param_def_id_to_index,
has_self: opaque_ty_generics.has_self,
has_late_bound_regions: opaque_ty_generics.has_late_bound_regions,
+ host_effect_index: parent_generics.host_effect_index,
}
});
- // There are no predicates for the synthesized associated type.
- trait_assoc_ty.explicit_predicates_of(ty::GenericPredicates {
- parent: Some(trait_def_id.to_def_id()),
- predicates: &[],
- });
-
// There are no inferred outlives for the synthesized associated type.
trait_assoc_ty.inferred_outlives_of(&[]);
@@ -393,8 +389,8 @@ fn associated_type_for_impl_trait_in_impl(
// Copy visility of the containing function.
impl_assoc_ty.visibility(tcx.visibility(impl_fn_def_id));
- // Copy impl_defaultness of the containing function.
- impl_assoc_ty.impl_defaultness(tcx.impl_defaultness(impl_fn_def_id));
+ // Copy defaultness of the containing function.
+ impl_assoc_ty.defaultness(tcx.defaultness(impl_fn_def_id));
// Copy generics_of the trait's associated item but the impl as the parent.
// FIXME(-Zlower-impl-trait-in-trait-to-assoc-ty) resolves to the trait instead of the impl
@@ -421,15 +417,10 @@ fn associated_type_for_impl_trait_in_impl(
param_def_id_to_index,
has_self: false,
has_late_bound_regions: trait_assoc_generics.has_late_bound_regions,
+ host_effect_index: parent_generics.host_effect_index,
}
});
- // There are no predicates for the synthesized associated type.
- impl_assoc_ty.explicit_predicates_of(ty::GenericPredicates {
- parent: Some(impl_local_def_id.to_def_id()),
- predicates: &[],
- });
-
// There are no inferred outlives for the synthesized associated type.
impl_assoc_ty.inferred_outlives_of(&[]);
diff --git a/compiler/rustc_ty_utils/src/consts.rs b/compiler/rustc_ty_utils/src/consts.rs
index 1219bb400..426c98012 100644
--- a/compiler/rustc_ty_utils/src/consts.rs
+++ b/compiler/rustc_ty_utils/src/consts.rs
@@ -33,8 +33,10 @@ pub(crate) fn destructure_const<'tcx>(
let (fields, variant) = match const_.ty().kind() {
ty::Array(inner_ty, _) | ty::Slice(inner_ty) => {
// construct the consts for the elements of the array/slice
- let field_consts =
- branches.iter().map(|b| tcx.mk_const(*b, *inner_ty)).collect::<Vec<_>>();
+ let field_consts = branches
+ .iter()
+ .map(|b| ty::Const::new_value(tcx, *b, *inner_ty))
+ .collect::<Vec<_>>();
debug!(?field_consts);
(field_consts, None)
@@ -52,7 +54,7 @@ pub(crate) fn destructure_const<'tcx>(
for (field, field_valtree) in iter::zip(fields, branches) {
let field_ty = field.ty(tcx, substs);
- let field_const = tcx.mk_const(*field_valtree, field_ty);
+ let field_const = ty::Const::new_value(tcx, *field_valtree, field_ty);
field_consts.push(field_const);
}
debug!(?field_consts);
@@ -61,7 +63,7 @@ pub(crate) fn destructure_const<'tcx>(
}
ty::Tuple(elem_tys) => {
let fields = iter::zip(*elem_tys, branches)
- .map(|(elem_ty, elem_valtree)| tcx.mk_const(*elem_valtree, elem_ty))
+ .map(|(elem_ty, elem_valtree)| ty::Const::new_value(tcx, *elem_valtree, elem_ty))
.collect::<Vec<_>>();
(fields, None)
@@ -78,8 +80,9 @@ pub(crate) fn destructure_const<'tcx>(
fn check_binop(op: mir::BinOp) -> bool {
use mir::BinOp::*;
match op {
- Add | Sub | Mul | Div | Rem | BitXor | BitAnd | BitOr | Shl | Shr | Eq | Lt | Le | Ne
- | Ge | Gt => true,
+ Add | AddUnchecked | Sub | SubUnchecked | Mul | MulUnchecked | Div | Rem | BitXor
+ | BitAnd | BitOr | Shl | ShlUnchecked | Shr | ShrUnchecked | Eq | Lt | Le | Ne | Ge
+ | Gt => true,
Offset => false,
}
}
@@ -116,7 +119,7 @@ fn recurse_build<'tcx>(
let sp = node.span;
match tcx.at(sp).lit_to_const(LitToConstInput { lit: &lit.node, ty: node.ty, neg }) {
Ok(c) => c,
- Err(LitToConstError::Reported(guar)) => tcx.const_error(node.ty, guar),
+ Err(LitToConstError::Reported(guar)) => ty::Const::new_error(tcx, guar, node.ty),
Err(LitToConstError::TypeError) => {
bug!("encountered type error in lit_to_const")
}
@@ -124,17 +127,17 @@ fn recurse_build<'tcx>(
}
&ExprKind::NonHirLiteral { lit, user_ty: _ } => {
let val = ty::ValTree::from_scalar_int(lit);
- tcx.mk_const(val, node.ty)
+ ty::Const::new_value(tcx, val, node.ty)
}
&ExprKind::ZstLiteral { user_ty: _ } => {
let val = ty::ValTree::zst();
- tcx.mk_const(val, node.ty)
+ ty::Const::new_value(tcx, val, node.ty)
}
&ExprKind::NamedConst { def_id, substs, user_ty: _ } => {
let uneval = ty::UnevaluatedConst::new(def_id, substs);
- tcx.mk_const(uneval, node.ty)
+ ty::Const::new_unevaluated(tcx, uneval, node.ty)
}
- ExprKind::ConstParam { param, .. } => tcx.mk_const(*param, node.ty),
+ ExprKind::ConstParam { param, .. } => ty::Const::new_param(tcx, *param, node.ty),
ExprKind::Call { fun, args, .. } => {
let fun = recurse_build(tcx, body, *fun, root_span)?;
@@ -144,16 +147,16 @@ fn recurse_build<'tcx>(
new_args.push(recurse_build(tcx, body, id, root_span)?);
}
let new_args = tcx.mk_const_list(&new_args);
- tcx.mk_const(Expr::FunctionCall(fun, new_args), node.ty)
+ ty::Const::new_expr(tcx, Expr::FunctionCall(fun, new_args), node.ty)
}
&ExprKind::Binary { op, lhs, rhs } if check_binop(op) => {
let lhs = recurse_build(tcx, body, lhs, root_span)?;
let rhs = recurse_build(tcx, body, rhs, root_span)?;
- tcx.mk_const(Expr::Binop(op, lhs, rhs), node.ty)
+ ty::Const::new_expr(tcx, Expr::Binop(op, lhs, rhs), node.ty)
}
&ExprKind::Unary { op, arg } if check_unop(op) => {
let arg = recurse_build(tcx, body, arg, root_span)?;
- tcx.mk_const(Expr::UnOp(op, arg), node.ty)
+ ty::Const::new_expr(tcx, Expr::UnOp(op, arg), node.ty)
}
// This is necessary so that the following compiles:
//
@@ -174,11 +177,11 @@ fn recurse_build<'tcx>(
// This is important so that `N as usize as usize` doesnt unify with `N as usize`. (untested)
&ExprKind::Use { source } => {
let arg = recurse_build(tcx, body, source, root_span)?;
- tcx.mk_const(Expr::Cast(CastKind::Use, arg, node.ty), node.ty)
+ ty::Const::new_expr(tcx, Expr::Cast(CastKind::Use, arg, node.ty), node.ty)
}
&ExprKind::Cast { source } => {
let arg = recurse_build(tcx, body, source, root_span)?;
- tcx.mk_const(Expr::Cast(CastKind::As, arg, node.ty), node.ty)
+ ty::Const::new_expr(tcx, Expr::Cast(CastKind::As, arg, node.ty), node.ty)
}
ExprKind::Borrow { arg, .. } => {
let arg_node = &body.exprs[*arg];
@@ -218,7 +221,7 @@ fn recurse_build<'tcx>(
maybe_supported_error(GenericConstantTooComplexSub::AdtNotSupported(node.span))?
}
// dont know if this is correct
- ExprKind::Pointer { .. } => {
+ ExprKind::PointerCoercion { .. } => {
error(GenericConstantTooComplexSub::PointerNotSupported(node.span))?
}
ExprKind::Yield { .. } => {
@@ -240,7 +243,8 @@ fn recurse_build<'tcx>(
ExprKind::Assign { .. } | ExprKind::AssignOp { .. } => {
error(GenericConstantTooComplexSub::AssignNotSupported(node.span))?
}
- ExprKind::Closure { .. } | ExprKind::Return { .. } => {
+ // FIXME(explicit_tail_calls): maybe get `become` a new error
+ ExprKind::Closure { .. } | ExprKind::Return { .. } | ExprKind::Become { .. } => {
error(GenericConstantTooComplexSub::ClosureAndReturnNotSupported(node.span))?
}
// let expressions imply control flow
@@ -320,7 +324,7 @@ impl<'a, 'tcx> IsThirPolymorphic<'a, 'tcx> {
| thir::ExprKind::Cast { .. }
| thir::ExprKind::Use { .. }
| thir::ExprKind::NeverToAny { .. }
- | thir::ExprKind::Pointer { .. }
+ | thir::ExprKind::PointerCoercion { .. }
| thir::ExprKind::Loop { .. }
| thir::ExprKind::Let { .. }
| thir::ExprKind::Match { .. }
@@ -336,6 +340,7 @@ impl<'a, 'tcx> IsThirPolymorphic<'a, 'tcx> {
| thir::ExprKind::Break { .. }
| thir::ExprKind::Continue { .. }
| thir::ExprKind::Return { .. }
+ | thir::ExprKind::Become { .. }
| thir::ExprKind::Array { .. }
| thir::ExprKind::Tuple { .. }
| thir::ExprKind::Adt(_)
@@ -419,7 +424,7 @@ pub fn thir_abstract_const(
let root_span = body.exprs[body_id].span;
- Ok(Some(ty::EarlyBinder(recurse_build(tcx, body, body_id, root_span)?)))
+ Ok(Some(ty::EarlyBinder::bind(recurse_build(tcx, body, body_id, root_span)?)))
}
pub fn provide(providers: &mut Providers) {
diff --git a/compiler/rustc_ty_utils/src/errors.rs b/compiler/rustc_ty_utils/src/errors.rs
index 553bf40ef..947d4bbe8 100644
--- a/compiler/rustc_ty_utils/src/errors.rs
+++ b/compiler/rustc_ty_utils/src/errors.rs
@@ -113,7 +113,7 @@ pub struct DuplicateArg<'tcx> {
}
#[derive(Diagnostic)]
-#[diag(ty_utils_impl_trait_not_param)]
+#[diag(ty_utils_impl_trait_not_param, code = "E0792")]
pub struct NotParam<'tcx> {
pub arg: GenericArg<'tcx>,
#[primary_span]
diff --git a/compiler/rustc_ty_utils/src/implied_bounds.rs b/compiler/rustc_ty_utils/src/implied_bounds.rs
index 081be0658..10dec9a7a 100644
--- a/compiler/rustc_ty_utils/src/implied_bounds.rs
+++ b/compiler/rustc_ty_utils/src/implied_bounds.rs
@@ -1,45 +1,56 @@
-use rustc_hir::{def::DefKind, def_id::DefId};
+use rustc_hir as hir;
+use rustc_hir::def::DefKind;
+use rustc_hir::def_id::LocalDefId;
use rustc_middle::query::Providers;
use rustc_middle::ty::{self, Ty, TyCtxt};
+use rustc_span::Span;
+use std::iter;
pub fn provide(providers: &mut Providers) {
*providers = Providers { assumed_wf_types, ..*providers };
}
-fn assumed_wf_types(tcx: TyCtxt<'_>, def_id: DefId) -> &ty::List<Ty<'_>> {
+fn assumed_wf_types<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> &'tcx [(Ty<'tcx>, Span)] {
match tcx.def_kind(def_id) {
DefKind::Fn => {
let sig = tcx.fn_sig(def_id).subst_identity();
- let liberated_sig = tcx.liberate_late_bound_regions(def_id, sig);
- liberated_sig.inputs_and_output
+ let liberated_sig = tcx.liberate_late_bound_regions(def_id.to_def_id(), sig);
+ tcx.arena.alloc_from_iter(itertools::zip_eq(
+ liberated_sig.inputs_and_output,
+ fn_sig_spans(tcx, def_id),
+ ))
}
DefKind::AssocFn => {
let sig = tcx.fn_sig(def_id).subst_identity();
- let liberated_sig = tcx.liberate_late_bound_regions(def_id, sig);
+ let liberated_sig = tcx.liberate_late_bound_regions(def_id.to_def_id(), sig);
let mut assumed_wf_types: Vec<_> =
- tcx.assumed_wf_types(tcx.parent(def_id)).as_slice().into();
- assumed_wf_types.extend(liberated_sig.inputs_and_output);
- tcx.mk_type_list(&assumed_wf_types)
+ tcx.assumed_wf_types(tcx.local_parent(def_id)).into();
+ assumed_wf_types.extend(itertools::zip_eq(
+ liberated_sig.inputs_and_output,
+ fn_sig_spans(tcx, def_id),
+ ));
+ tcx.arena.alloc_slice(&assumed_wf_types)
}
DefKind::Impl { .. } => {
- match tcx.impl_trait_ref(def_id) {
- Some(trait_ref) => {
- let types: Vec<_> = trait_ref.skip_binder().substs.types().collect();
- tcx.mk_type_list(&types)
- }
- // Only the impl self type
- None => tcx.mk_type_list(&[tcx.type_of(def_id).subst_identity()]),
- }
+ // Trait arguments and the self type for trait impls or only the self type for
+ // inherent impls.
+ let tys = match tcx.impl_trait_ref(def_id) {
+ Some(trait_ref) => trait_ref.skip_binder().substs.types().collect(),
+ None => vec![tcx.type_of(def_id).subst_identity()],
+ };
+
+ let mut impl_spans = impl_spans(tcx, def_id);
+ tcx.arena.alloc_from_iter(tys.into_iter().map(|ty| (ty, impl_spans.next().unwrap())))
}
- DefKind::AssocConst | DefKind::AssocTy => tcx.assumed_wf_types(tcx.parent(def_id)),
- DefKind::OpaqueTy => match tcx.def_kind(tcx.parent(def_id)) {
+ DefKind::AssocConst | DefKind::AssocTy => tcx.assumed_wf_types(tcx.local_parent(def_id)),
+ DefKind::OpaqueTy => match tcx.def_kind(tcx.local_parent(def_id)) {
DefKind::TyAlias => ty::List::empty(),
- DefKind::AssocTy => tcx.assumed_wf_types(tcx.parent(def_id)),
+ DefKind::AssocTy => tcx.assumed_wf_types(tcx.local_parent(def_id)),
// Nested opaque types only occur in associated types:
// ` type Opaque<T> = impl Trait<&'static T, AssocTy = impl Nested>; `
// assumed_wf_types should include those of `Opaque<T>`, `Opaque<T>` itself
// and `&'static T`.
- DefKind::OpaqueTy => bug!("unimplemented implied bounds for neseted opaque types"),
+ DefKind::OpaqueTy => bug!("unimplemented implied bounds for nested opaque types"),
def_kind @ _ => {
bug!("unimplemented implied bounds for opaque types with parent {def_kind:?}")
}
@@ -72,3 +83,28 @@ fn assumed_wf_types(tcx: TyCtxt<'_>, def_id: DefId) -> &ty::List<Ty<'_>> {
| DefKind::Generator => ty::List::empty(),
}
}
+
+fn fn_sig_spans(tcx: TyCtxt<'_>, def_id: LocalDefId) -> impl Iterator<Item = Span> + '_ {
+ let node = tcx.hir().get(tcx.local_def_id_to_hir_id(def_id));
+ if let Some(decl) = node.fn_decl() {
+ decl.inputs.iter().map(|ty| ty.span).chain(iter::once(decl.output.span()))
+ } else {
+ bug!("unexpected item for fn {def_id:?}: {node:?}")
+ }
+}
+
+fn impl_spans(tcx: TyCtxt<'_>, def_id: LocalDefId) -> impl Iterator<Item = Span> + '_ {
+ let item = tcx.hir().expect_item(def_id);
+ if let hir::ItemKind::Impl(impl_) = item.kind {
+ let trait_args = impl_
+ .of_trait
+ .into_iter()
+ .flat_map(|trait_ref| trait_ref.path.segments.last().unwrap().args().args)
+ .map(|arg| arg.span());
+ let dummy_spans_for_default_args =
+ impl_.of_trait.into_iter().flat_map(|trait_ref| iter::repeat(trait_ref.path.span));
+ iter::once(impl_.self_ty.span).chain(trait_args).chain(dummy_spans_for_default_args)
+ } else {
+ bug!("unexpected item for impl {def_id:?}: {item:?}")
+ }
+}
diff --git a/compiler/rustc_ty_utils/src/instance.rs b/compiler/rustc_ty_utils/src/instance.rs
index 36a20c78f..1d93a79e5 100644
--- a/compiler/rustc_ty_utils/src/instance.rs
+++ b/compiler/rustc_ty_utils/src/instance.rs
@@ -80,7 +80,7 @@ fn resolve_associated_item<'tcx>(
let trait_ref = ty::TraitRef::from_method(tcx, trait_id, rcvr_substs);
- let vtbl = match tcx.codegen_select_candidate((param_env, ty::Binder::dummy(trait_ref))) {
+ let vtbl = match tcx.codegen_select_candidate((param_env, trait_ref)) {
Ok(vtbl) => vtbl,
Err(CodegenObligationError::Ambiguity) => {
let reported = tcx.sess.delay_span_bug(
@@ -177,85 +177,6 @@ fn resolve_associated_item<'tcx>(
Some(ty::Instance::new(leaf_def.item.def_id, substs))
}
- traits::ImplSource::Generator(generator_data) => {
- if cfg!(debug_assertions) && tcx.item_name(trait_item_id) != sym::resume {
- // For compiler developers who'd like to add new items to `Generator`,
- // you either need to generate a shim body, or perhaps return
- // `InstanceDef::Item` pointing to a trait default method body if
- // it is given a default implementation by the trait.
- span_bug!(
- tcx.def_span(generator_data.generator_def_id),
- "no definition for `{trait_ref}::{}` for built-in generator type",
- tcx.item_name(trait_item_id)
- )
- }
- Some(Instance {
- def: ty::InstanceDef::Item(generator_data.generator_def_id),
- substs: generator_data.substs,
- })
- }
- traits::ImplSource::Future(future_data) => {
- if Some(trait_item_id) == tcx.lang_items().future_poll_fn() {
- // `Future::poll` is generated by the compiler.
- Some(Instance {
- def: ty::InstanceDef::Item(future_data.generator_def_id),
- substs: future_data.substs,
- })
- } else {
- // All other methods are default methods of the `Future` trait.
- // (this assumes that `ImplSource::Future` is only used for methods on `Future`)
- debug_assert!(tcx.impl_defaultness(trait_item_id).has_value());
- Some(Instance::new(trait_item_id, rcvr_substs))
- }
- }
- traits::ImplSource::Closure(closure_data) => {
- if cfg!(debug_assertions)
- && ![sym::call, sym::call_mut, sym::call_once]
- .contains(&tcx.item_name(trait_item_id))
- {
- // For compiler developers who'd like to add new items to `Fn`/`FnMut`/`FnOnce`,
- // you either need to generate a shim body, or perhaps return
- // `InstanceDef::Item` pointing to a trait default method body if
- // it is given a default implementation by the trait.
- span_bug!(
- tcx.def_span(closure_data.closure_def_id),
- "no definition for `{trait_ref}::{}` for built-in closure type",
- tcx.item_name(trait_item_id)
- )
- }
- let trait_closure_kind = tcx.fn_trait_kind_from_def_id(trait_id).unwrap();
- Instance::resolve_closure(
- tcx,
- closure_data.closure_def_id,
- closure_data.substs,
- trait_closure_kind,
- )
- }
- traits::ImplSource::FnPointer(ref data) => match data.fn_ty.kind() {
- ty::FnDef(..) | ty::FnPtr(..) => {
- if cfg!(debug_assertions)
- && ![sym::call, sym::call_mut, sym::call_once]
- .contains(&tcx.item_name(trait_item_id))
- {
- // For compiler developers who'd like to add new items to `Fn`/`FnMut`/`FnOnce`,
- // you either need to generate a shim body, or perhaps return
- // `InstanceDef::Item` pointing to a trait default method body if
- // it is given a default implementation by the trait.
- bug!(
- "no definition for `{trait_ref}::{}` for built-in fn type",
- tcx.item_name(trait_item_id)
- )
- }
- Some(Instance {
- def: ty::InstanceDef::FnPtrShim(trait_item_id, data.fn_ty),
- substs: rcvr_substs,
- })
- }
- _ => bug!(
- "no built-in definition for `{trait_ref}::{}` for non-fn type",
- tcx.item_name(trait_item_id)
- ),
- },
traits::ImplSource::Object(ref data) => {
traits::get_vtable_index_of_object_method(tcx, data, trait_item_id).map(|index| {
Instance {
@@ -308,15 +229,71 @@ fn resolve_associated_item<'tcx>(
span: tcx.def_span(trait_item_id),
})
}
+ } else if Some(trait_ref.def_id) == lang_items.future_trait() {
+ let ty::Generator(generator_def_id, substs, _) = *rcvr_substs.type_at(0).kind() else {
+ bug!()
+ };
+ if Some(trait_item_id) == tcx.lang_items().future_poll_fn() {
+ // `Future::poll` is generated by the compiler.
+ Some(Instance { def: ty::InstanceDef::Item(generator_def_id), substs: substs })
+ } else {
+ // All other methods are default methods of the `Future` trait.
+ // (this assumes that `ImplSource::Builtin` is only used for methods on `Future`)
+ debug_assert!(tcx.defaultness(trait_item_id).has_value());
+ Some(Instance::new(trait_item_id, rcvr_substs))
+ }
+ } else if Some(trait_ref.def_id) == lang_items.gen_trait() {
+ let ty::Generator(generator_def_id, substs, _) = *rcvr_substs.type_at(0).kind() else {
+ bug!()
+ };
+ if cfg!(debug_assertions) && tcx.item_name(trait_item_id) != sym::resume {
+ // For compiler developers who'd like to add new items to `Generator`,
+ // you either need to generate a shim body, or perhaps return
+ // `InstanceDef::Item` pointing to a trait default method body if
+ // it is given a default implementation by the trait.
+ span_bug!(
+ tcx.def_span(generator_def_id),
+ "no definition for `{trait_ref}::{}` for built-in generator type",
+ tcx.item_name(trait_item_id)
+ )
+ }
+ Some(Instance { def: ty::InstanceDef::Item(generator_def_id), substs })
+ } else if tcx.fn_trait_kind_from_def_id(trait_ref.def_id).is_some() {
+ // FIXME: This doesn't check for malformed libcore that defines, e.g.,
+ // `trait Fn { fn call_once(&self) { .. } }`. This is mostly for extension
+ // methods.
+ if cfg!(debug_assertions)
+ && ![sym::call, sym::call_mut, sym::call_once]
+ .contains(&tcx.item_name(trait_item_id))
+ {
+ // For compiler developers who'd like to add new items to `Fn`/`FnMut`/`FnOnce`,
+ // you either need to generate a shim body, or perhaps return
+ // `InstanceDef::Item` pointing to a trait default method body if
+ // it is given a default implementation by the trait.
+ bug!(
+ "no definition for `{trait_ref}::{}` for built-in callable type",
+ tcx.item_name(trait_item_id)
+ )
+ }
+ match *rcvr_substs.type_at(0).kind() {
+ ty::Closure(closure_def_id, substs) => {
+ let trait_closure_kind = tcx.fn_trait_kind_from_def_id(trait_id).unwrap();
+ Instance::resolve_closure(tcx, closure_def_id, substs, trait_closure_kind)
+ }
+ ty::FnDef(..) | ty::FnPtr(..) => Some(Instance {
+ def: ty::InstanceDef::FnPtrShim(trait_item_id, rcvr_substs.type_at(0)),
+ substs: rcvr_substs,
+ }),
+ _ => bug!(
+ "no built-in definition for `{trait_ref}::{}` for non-fn type",
+ tcx.item_name(trait_item_id)
+ ),
+ }
} else {
None
}
}
- traits::ImplSource::AutoImpl(..)
- | traits::ImplSource::Param(..)
- | traits::ImplSource::TraitAlias(..)
- | traits::ImplSource::TraitUpcasting(_)
- | traits::ImplSource::ConstDestruct(_) => None,
+ traits::ImplSource::Param(..) | traits::ImplSource::TraitUpcasting(_) => None,
})
}
diff --git a/compiler/rustc_ty_utils/src/layout.rs b/compiler/rustc_ty_utils/src/layout.rs
index 16cd8bc8e..b67cd96a7 100644
--- a/compiler/rustc_ty_utils/src/layout.rs
+++ b/compiler/rustc_ty_utils/src/layout.rs
@@ -31,7 +31,7 @@ pub fn provide(providers: &mut Providers) {
fn layout_of<'tcx>(
tcx: TyCtxt<'tcx>,
query: ty::ParamEnvAnd<'tcx, Ty<'tcx>>,
-) -> Result<TyAndLayout<'tcx>, LayoutError<'tcx>> {
+) -> Result<TyAndLayout<'tcx>, &'tcx LayoutError<'tcx>> {
let (param_env, ty) = query.into_parts();
debug!(?ty);
@@ -45,7 +45,9 @@ fn layout_of<'tcx>(
let ty = match tcx.try_normalize_erasing_regions(param_env, ty) {
Ok(t) => t,
Err(normalization_error) => {
- return Err(LayoutError::NormalizationFailure(ty, normalization_error));
+ return Err(tcx
+ .arena
+ .alloc(LayoutError::NormalizationFailure(ty, normalization_error)));
}
};
@@ -66,27 +68,34 @@ fn layout_of<'tcx>(
Ok(layout)
}
+fn error<'tcx>(
+ cx: &LayoutCx<'tcx, TyCtxt<'tcx>>,
+ err: LayoutError<'tcx>,
+) -> &'tcx LayoutError<'tcx> {
+ cx.tcx.arena.alloc(err)
+}
+
fn univariant_uninterned<'tcx>(
cx: &LayoutCx<'tcx, TyCtxt<'tcx>>,
ty: Ty<'tcx>,
fields: &IndexSlice<FieldIdx, Layout<'_>>,
repr: &ReprOptions,
kind: StructKind,
-) -> Result<LayoutS, LayoutError<'tcx>> {
+) -> Result<LayoutS, &'tcx LayoutError<'tcx>> {
let dl = cx.data_layout();
let pack = repr.pack;
if pack.is_some() && repr.align.is_some() {
cx.tcx.sess.delay_span_bug(DUMMY_SP, "struct cannot be packed and aligned");
- return Err(LayoutError::Unknown(ty));
+ return Err(cx.tcx.arena.alloc(LayoutError::Unknown(ty)));
}
- cx.univariant(dl, fields, repr, kind).ok_or(LayoutError::SizeOverflow(ty))
+ cx.univariant(dl, fields, repr, kind).ok_or_else(|| error(cx, LayoutError::SizeOverflow(ty)))
}
fn layout_of_uncached<'tcx>(
cx: &LayoutCx<'tcx, TyCtxt<'tcx>>,
ty: Ty<'tcx>,
-) -> Result<Layout<'tcx>, LayoutError<'tcx>> {
+) -> Result<Layout<'tcx>, &'tcx LayoutError<'tcx>> {
let tcx = cx.tcx;
let param_env = cx.param_env;
let dl = cx.data_layout();
@@ -145,17 +154,35 @@ fn layout_of_uncached<'tcx>(
return Ok(tcx.mk_layout(LayoutS::scalar(cx, data_ptr)));
}
- let unsized_part = tcx.struct_tail_erasing_lifetimes(pointee, param_env);
-
let metadata = if let Some(metadata_def_id) = tcx.lang_items().metadata_type()
// Projection eagerly bails out when the pointee references errors,
// fall back to structurally deducing metadata.
&& !pointee.references_error()
{
- let metadata_ty = tcx.normalize_erasing_regions(
+ let pointee_metadata = Ty::new_projection(tcx,metadata_def_id, [pointee]);
+ let metadata_ty = match tcx.try_normalize_erasing_regions(
param_env,
- tcx.mk_projection(metadata_def_id, [pointee]),
- );
+ pointee_metadata,
+ ) {
+ Ok(metadata_ty) => metadata_ty,
+ Err(mut err) => {
+ // Usually `<Ty as Pointee>::Metadata` can't be normalized because
+ // its struct tail cannot be normalized either, so try to get a
+ // more descriptive layout error here, which will lead to less confusing
+ // diagnostics.
+ match tcx.try_normalize_erasing_regions(
+ param_env,
+ tcx.struct_tail_without_normalization(pointee),
+ ) {
+ Ok(_) => {},
+ Err(better_err) => {
+ err = better_err;
+ }
+ }
+ return Err(error(cx, LayoutError::NormalizationFailure(pointee, err)));
+ },
+ };
+
let metadata_layout = cx.layout_of(metadata_ty)?;
// If the metadata is a 1-zst, then the pointer is thin.
if metadata_layout.is_zst() && metadata_layout.align.abi.bytes() == 1 {
@@ -163,10 +190,13 @@ fn layout_of_uncached<'tcx>(
}
let Abi::Scalar(metadata) = metadata_layout.abi else {
- return Err(LayoutError::Unknown(unsized_part));
+ return Err(error(cx, LayoutError::Unknown(pointee)));
};
+
metadata
} else {
+ let unsized_part = tcx.struct_tail_erasing_lifetimes(pointee, param_env);
+
match unsized_part.kind() {
ty::Foreign(..) => {
return Ok(tcx.mk_layout(LayoutS::scalar(cx, data_ptr)));
@@ -178,7 +208,7 @@ fn layout_of_uncached<'tcx>(
vtable
}
_ => {
- return Err(LayoutError::Unknown(unsized_part));
+ return Err(error(cx, LayoutError::Unknown(pointee)));
}
}
};
@@ -200,14 +230,18 @@ fn layout_of_uncached<'tcx>(
if count.has_projections() {
count = tcx.normalize_erasing_regions(param_env, count);
if count.has_projections() {
- return Err(LayoutError::Unknown(ty));
+ return Err(error(cx, LayoutError::Unknown(ty)));
}
}
- let count =
- count.try_eval_target_usize(tcx, param_env).ok_or(LayoutError::Unknown(ty))?;
+ let count = count
+ .try_eval_target_usize(tcx, param_env)
+ .ok_or_else(|| error(cx, LayoutError::Unknown(ty)))?;
let element = cx.layout_of(element)?;
- let size = element.size.checked_mul(count, dl).ok_or(LayoutError::SizeOverflow(ty))?;
+ let size = element
+ .size
+ .checked_mul(count, dl)
+ .ok_or_else(|| error(cx, LayoutError::SizeOverflow(ty)))?;
let abi = if count != 0 && ty.is_privately_uninhabited(tcx, param_env) {
Abi::Uninhabited
@@ -295,7 +329,7 @@ fn layout_of_uncached<'tcx>(
DUMMY_SP,
"#[repr(simd)] was applied to an ADT that is not a struct",
);
- return Err(LayoutError::Unknown(ty));
+ return Err(error(cx, LayoutError::Unknown(ty)));
}
let fields = &def.non_enum_variant().fields;
@@ -325,7 +359,7 @@ fn layout_of_uncached<'tcx>(
DUMMY_SP,
"#[repr(simd)] was applied to an ADT with heterogeneous field type",
);
- return Err(LayoutError::Unknown(ty));
+ return Err(error(cx, LayoutError::Unknown(ty)));
}
}
@@ -347,7 +381,7 @@ fn layout_of_uncached<'tcx>(
// Extract the number of elements from the layout of the array field:
let FieldsShape::Array { count, .. } = cx.layout_of(f0_ty)?.layout.fields() else {
- return Err(LayoutError::Unknown(ty));
+ return Err(error(cx, LayoutError::Unknown(ty)));
};
(*e_ty, *count, true)
@@ -376,7 +410,10 @@ fn layout_of_uncached<'tcx>(
};
// Compute the size and alignment of the vector:
- let size = e_ly.size.checked_mul(e_len, dl).ok_or(LayoutError::SizeOverflow(ty))?;
+ let size = e_ly
+ .size
+ .checked_mul(e_len, dl)
+ .ok_or_else(|| error(cx, LayoutError::SizeOverflow(ty)))?;
let align = dl.vector_align(size);
let size = size.align_to(align.abi);
@@ -417,53 +454,101 @@ fn layout_of_uncached<'tcx>(
tcx.def_span(def.did()),
"union cannot be packed and aligned",
);
- return Err(LayoutError::Unknown(ty));
+ return Err(error(cx, LayoutError::Unknown(ty)));
}
return Ok(tcx.mk_layout(
- cx.layout_of_union(&def.repr(), &variants).ok_or(LayoutError::Unknown(ty))?,
+ cx.layout_of_union(&def.repr(), &variants)
+ .ok_or_else(|| error(cx, LayoutError::Unknown(ty)))?,
));
}
- tcx.mk_layout(
- cx.layout_of_struct_or_enum(
+ let get_discriminant_type =
+ |min, max| Integer::repr_discr(tcx, ty, &def.repr(), min, max);
+
+ let discriminants_iter = || {
+ def.is_enum()
+ .then(|| def.discriminants(tcx).map(|(v, d)| (v, d.val as i128)))
+ .into_iter()
+ .flatten()
+ };
+
+ let dont_niche_optimize_enum = def.repr().inhibit_enum_layout_opt()
+ || def
+ .variants()
+ .iter_enumerated()
+ .any(|(i, v)| v.discr != ty::VariantDiscr::Relative(i.as_u32()));
+
+ let maybe_unsized = def.is_struct()
+ && def.non_enum_variant().tail_opt().is_some_and(|last_field| {
+ let param_env = tcx.param_env(def.did());
+ !tcx.type_of(last_field.did).subst_identity().is_sized(tcx, param_env)
+ });
+
+ let Some(layout) = cx.layout_of_struct_or_enum(
+ &def.repr(),
+ &variants,
+ def.is_enum(),
+ def.is_unsafe_cell(),
+ tcx.layout_scalar_valid_range(def.did()),
+ get_discriminant_type,
+ discriminants_iter(),
+ dont_niche_optimize_enum,
+ !maybe_unsized,
+ ) else {
+ return Err(error(cx, LayoutError::SizeOverflow(ty)));
+ };
+
+ // If the struct tail is sized and can be unsized, check that unsizing doesn't move the fields around.
+ if cfg!(debug_assertions)
+ && maybe_unsized
+ && def.non_enum_variant().tail().ty(tcx, substs).is_sized(tcx, cx.param_env)
+ {
+ let mut variants = variants;
+ let tail_replacement = cx.layout_of(Ty::new_slice(tcx, tcx.types.u8)).unwrap();
+ *variants[FIRST_VARIANT].raw.last_mut().unwrap() = tail_replacement.layout;
+
+ let Some(unsized_layout) = cx.layout_of_struct_or_enum(
&def.repr(),
&variants,
def.is_enum(),
def.is_unsafe_cell(),
tcx.layout_scalar_valid_range(def.did()),
- |min, max| Integer::repr_discr(tcx, ty, &def.repr(), min, max),
- def.is_enum()
- .then(|| def.discriminants(tcx).map(|(v, d)| (v, d.val as i128)))
- .into_iter()
- .flatten(),
- def.repr().inhibit_enum_layout_opt()
- || def
- .variants()
- .iter_enumerated()
- .any(|(i, v)| v.discr != ty::VariantDiscr::Relative(i.as_u32())),
- {
- let param_env = tcx.param_env(def.did());
- def.is_struct()
- && match def.variants().iter().next().and_then(|x| x.fields.raw.last())
- {
- Some(last_field) => tcx
- .type_of(last_field.did)
- .subst_identity()
- .is_sized(tcx, param_env),
- None => false,
- }
- },
- )
- .ok_or(LayoutError::SizeOverflow(ty))?,
- )
+ get_discriminant_type,
+ discriminants_iter(),
+ dont_niche_optimize_enum,
+ !maybe_unsized,
+ ) else {
+ bug!("failed to compute unsized layout of {ty:?}");
+ };
+
+ let FieldsShape::Arbitrary { offsets: sized_offsets, .. } = &layout.fields else {
+ bug!("unexpected FieldsShape for sized layout of {ty:?}: {:?}", layout.fields);
+ };
+ let FieldsShape::Arbitrary { offsets: unsized_offsets, .. } = &unsized_layout.fields else {
+ bug!("unexpected FieldsShape for unsized layout of {ty:?}: {:?}", unsized_layout.fields);
+ };
+
+ let (sized_tail, sized_fields) = sized_offsets.raw.split_last().unwrap();
+ let (unsized_tail, unsized_fields) = unsized_offsets.raw.split_last().unwrap();
+
+ if sized_fields != unsized_fields {
+ bug!("unsizing {ty:?} changed field order!\n{layout:?}\n{unsized_layout:?}");
+ }
+
+ if sized_tail < unsized_tail {
+ bug!("unsizing {ty:?} moved tail backwards!\n{layout:?}\n{unsized_layout:?}");
+ }
+ }
+
+ tcx.mk_layout(layout)
}
// Types with no meaningful known layout.
ty::Alias(..) => {
// NOTE(eddyb) `layout_of` query should've normalized these away,
// if that was possible, so there's no reason to try again here.
- return Err(LayoutError::Unknown(ty));
+ return Err(error(cx, LayoutError::Unknown(ty)));
}
ty::Bound(..) | ty::GeneratorWitness(..) | ty::GeneratorWitnessMIR(..) | ty::Infer(_) => {
@@ -471,7 +556,7 @@ fn layout_of_uncached<'tcx>(
}
ty::Placeholder(..) | ty::Param(_) | ty::Error(_) => {
- return Err(LayoutError::Unknown(ty));
+ return Err(error(cx, LayoutError::Unknown(ty)));
}
})
}
@@ -607,13 +692,13 @@ fn generator_layout<'tcx>(
ty: Ty<'tcx>,
def_id: hir::def_id::DefId,
substs: SubstsRef<'tcx>,
-) -> Result<Layout<'tcx>, LayoutError<'tcx>> {
+) -> Result<Layout<'tcx>, &'tcx LayoutError<'tcx>> {
use SavedLocalEligibility::*;
let tcx = cx.tcx;
- let subst_field = |ty: Ty<'tcx>| EarlyBinder(ty).subst(tcx, substs);
+ let subst_field = |ty: Ty<'tcx>| EarlyBinder::bind(ty).subst(tcx, substs);
let Some(info) = tcx.generator_layout(def_id) else {
- return Err(LayoutError::Unknown(ty));
+ return Err(error(cx, LayoutError::Unknown(ty)));
};
let (ineligible_locals, assignments) = generator_saved_local_eligibility(&info);
@@ -634,7 +719,7 @@ fn generator_layout<'tcx>(
let promoted_layouts = ineligible_locals
.iter()
.map(|local| subst_field(info.field_tys[local].ty))
- .map(|ty| tcx.mk_maybe_uninit(ty))
+ .map(|ty| Ty::new_maybe_uninit(tcx, ty))
.map(|ty| Ok(cx.layout_of(ty)?.layout));
let prefix_layouts = substs
.as_generator()
@@ -944,7 +1029,7 @@ fn variant_info_for_generator<'tcx>(
return (vec![], None);
};
- let (generator, state_specific_names) = cx.tcx.generator_layout_and_saved_local_names(def_id);
+ let generator = cx.tcx.optimized_mir(def_id).generator_layout().unwrap();
let upvar_names = cx.tcx.closure_saved_names_of_captured_variables(def_id);
let mut upvars_size = Size::ZERO;
@@ -959,7 +1044,7 @@ fn variant_info_for_generator<'tcx>(
upvars_size = upvars_size.max(offset + field_layout.size);
FieldInfo {
kind: FieldKind::Upvar,
- name: Symbol::intern(&name),
+ name: *name,
offset: offset.bytes(),
size: field_layout.size.bytes(),
align: field_layout.align.abi.bytes(),
@@ -983,9 +1068,10 @@ fn variant_info_for_generator<'tcx>(
variant_size = variant_size.max(offset + field_layout.size);
FieldInfo {
kind: FieldKind::GeneratorLocal,
- name: state_specific_names.get(*local).copied().flatten().unwrap_or(
- Symbol::intern(&format!(".generator_field{}", local.as_usize())),
- ),
+ name: generator.field_names[*local].unwrap_or(Symbol::intern(&format!(
+ ".generator_field{}",
+ local.as_usize()
+ ))),
offset: offset.bytes(),
size: field_layout.size.bytes(),
align: field_layout.align.abi.bytes(),
diff --git a/compiler/rustc_ty_utils/src/needs_drop.rs b/compiler/rustc_ty_utils/src/needs_drop.rs
index 1f9701b93..9d593dc5e 100644
--- a/compiler/rustc_ty_utils/src/needs_drop.rs
+++ b/compiler/rustc_ty_utils/src/needs_drop.rs
@@ -210,7 +210,7 @@ fn drop_tys_helper<'tcx>(
match subty.kind() {
ty::Adt(adt_id, subst) => {
for subty in tcx.adt_drop_tys(adt_id.did())? {
- vec.push(EarlyBinder(subty).subst(tcx, subst));
+ vec.push(EarlyBinder::bind(subty).subst(tcx, subst));
}
}
_ => vec.push(subty),
diff --git a/compiler/rustc_ty_utils/src/opaque_types.rs b/compiler/rustc_ty_utils/src/opaque_types.rs
index 4e91dd380..570c3b245 100644
--- a/compiler/rustc_ty_utils/src/opaque_types.rs
+++ b/compiler/rustc_ty_utils/src/opaque_types.rs
@@ -1,12 +1,13 @@
use rustc_data_structures::fx::FxHashSet;
-use rustc_errors::ErrorGuaranteed;
+use rustc_hir::intravisit::Visitor;
use rustc_hir::{def::DefKind, def_id::LocalDefId};
+use rustc_hir::{intravisit, CRATE_HIR_ID};
use rustc_middle::query::Providers;
use rustc_middle::ty::util::{CheckRegions, NotUniqueParam};
use rustc_middle::ty::{self, Ty, TyCtxt};
use rustc_middle::ty::{TypeSuperVisitable, TypeVisitable, TypeVisitor};
use rustc_span::Span;
-use rustc_type_ir::AliasKind;
+use rustc_trait_selection::traits::check_substs_compatible;
use std::ops::ControlFlow;
use crate::errors::{DuplicateArg, NotParam};
@@ -19,26 +20,40 @@ struct OpaqueTypeCollector<'tcx> {
/// Avoid infinite recursion due to recursive declarations.
seen: FxHashSet<LocalDefId>,
+
+ span: Option<Span>,
}
impl<'tcx> OpaqueTypeCollector<'tcx> {
- fn collect(
- tcx: TyCtxt<'tcx>,
- item: LocalDefId,
- val: ty::Binder<'tcx, impl TypeVisitable<TyCtxt<'tcx>>>,
- ) -> Vec<LocalDefId> {
- let mut collector = Self { tcx, opaques: Vec::new(), item, seen: Default::default() };
- val.skip_binder().visit_with(&mut collector);
- collector.opaques
+ fn new(tcx: TyCtxt<'tcx>, item: LocalDefId) -> Self {
+ Self { tcx, opaques: Vec::new(), item, seen: Default::default(), span: None }
}
fn span(&self) -> Span {
- self.tcx.def_span(self.item)
+ self.span.unwrap_or_else(|| {
+ self.tcx.def_ident_span(self.item).unwrap_or_else(|| self.tcx.def_span(self.item))
+ })
+ }
+
+ fn visit_spanned(&mut self, span: Span, value: impl TypeVisitable<TyCtxt<'tcx>>) {
+ let old = self.span;
+ self.span = Some(span);
+ value.visit_with(self);
+ self.span = old;
+ }
+
+ fn parent_trait_ref(&self) -> Option<ty::TraitRef<'tcx>> {
+ let parent = self.parent()?;
+ if matches!(self.tcx.def_kind(parent), DefKind::Impl { .. }) {
+ Some(self.tcx.impl_trait_ref(parent)?.subst_identity())
+ } else {
+ None
+ }
}
fn parent(&self) -> Option<LocalDefId> {
match self.tcx.def_kind(self.item) {
- DefKind::Fn => None,
+ DefKind::AnonConst | DefKind::InlineConst | DefKind::Fn | DefKind::TyAlias => None,
DefKind::AssocFn | DefKind::AssocTy | DefKind::AssocConst => {
Some(self.tcx.local_parent(self.item))
}
@@ -48,119 +63,245 @@ impl<'tcx> OpaqueTypeCollector<'tcx> {
),
}
}
+
+ /// Returns `true` if `opaque_hir_id` is a sibling or a child of a sibling of `self.item`.
+ ///
+ /// Example:
+ /// ```ignore UNSOLVED (is this a bug?)
+ /// # #![feature(type_alias_impl_trait)]
+ /// pub mod foo {
+ /// pub mod bar {
+ /// pub trait Bar { /* ... */ }
+ /// pub type Baz = impl Bar;
+ ///
+ /// # impl Bar for () {}
+ /// fn f1() -> Baz { /* ... */ }
+ /// }
+ /// fn f2() -> bar::Baz { /* ... */ }
+ /// }
+ /// ```
+ ///
+ /// and `opaque_def_id` is the `DefId` of the definition of the opaque type `Baz`.
+ /// For the above example, this function returns `true` for `f1` and `false` for `f2`.
+ #[instrument(level = "trace", skip(self), ret)]
+ fn check_tait_defining_scope(&self, opaque_def_id: LocalDefId) -> bool {
+ let mut hir_id = self.tcx.hir().local_def_id_to_hir_id(self.item);
+ let opaque_hir_id = self.tcx.hir().local_def_id_to_hir_id(opaque_def_id);
+
+ // Named opaque types can be defined by any siblings or children of siblings.
+ let scope = self.tcx.hir().get_defining_scope(opaque_hir_id);
+ // We walk up the node tree until we hit the root or the scope of the opaque type.
+ while hir_id != scope && hir_id != CRATE_HIR_ID {
+ hir_id = self.tcx.hir().get_parent_item(hir_id).into();
+ }
+ // Syntactically, we are allowed to define the concrete type if:
+ hir_id == scope
+ }
+
+ fn collect_body_and_predicate_taits(&mut self) {
+ // Look at all where bounds.
+ self.tcx.predicates_of(self.item).instantiate_identity(self.tcx).visit_with(self);
+ // An item is allowed to constrain opaques declared within its own body (but not nested within
+ // nested functions).
+ self.collect_taits_declared_in_body();
+ }
+
+ #[instrument(level = "trace", skip(self))]
+ fn collect_taits_declared_in_body(&mut self) {
+ let body = self.tcx.hir().body(self.tcx.hir().body_owned_by(self.item)).value;
+ struct TaitInBodyFinder<'a, 'tcx> {
+ collector: &'a mut OpaqueTypeCollector<'tcx>,
+ }
+ impl<'v> intravisit::Visitor<'v> for TaitInBodyFinder<'_, '_> {
+ #[instrument(level = "trace", skip(self))]
+ fn visit_nested_item(&mut self, id: rustc_hir::ItemId) {
+ let id = id.owner_id.def_id;
+ if let DefKind::TyAlias = self.collector.tcx.def_kind(id) {
+ let items = self.collector.tcx.opaque_types_defined_by(id);
+ self.collector.opaques.extend(items);
+ }
+ }
+ #[instrument(level = "trace", skip(self))]
+ // Recurse into these, as they are type checked with their parent
+ fn visit_nested_body(&mut self, id: rustc_hir::BodyId) {
+ let body = self.collector.tcx.hir().body(id);
+ self.visit_body(body);
+ }
+ }
+ TaitInBodyFinder { collector: self }.visit_expr(body);
+ }
}
impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for OpaqueTypeCollector<'tcx> {
- type BreakTy = ErrorGuaranteed;
-
#[instrument(skip(self), ret, level = "trace")]
- fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<ErrorGuaranteed> {
+ fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<!> {
+ t.super_visit_with(self)?;
match t.kind() {
- ty::Alias(AliasKind::Opaque, alias_ty) if alias_ty.def_id.is_local() => {
+ ty::Alias(ty::Opaque, alias_ty) if alias_ty.def_id.is_local() => {
if !self.seen.insert(alias_ty.def_id.expect_local()) {
return ControlFlow::Continue(());
}
+
+ // TAITs outside their defining scopes are ignored.
+ let origin = self.tcx.opaque_type_origin(alias_ty.def_id.expect_local());
+ trace!(?origin);
+ match origin {
+ rustc_hir::OpaqueTyOrigin::FnReturn(_)
+ | rustc_hir::OpaqueTyOrigin::AsyncFn(_) => {}
+ rustc_hir::OpaqueTyOrigin::TyAlias { in_assoc_ty } => {
+ if !in_assoc_ty {
+ if !self.check_tait_defining_scope(alias_ty.def_id.expect_local()) {
+ return ControlFlow::Continue(());
+ }
+ }
+ }
+ }
+
+ self.opaques.push(alias_ty.def_id.expect_local());
+
match self.tcx.uses_unique_generic_params(alias_ty.substs, CheckRegions::Bound) {
Ok(()) => {
// FIXME: implement higher kinded lifetime bounds on nested opaque types. They are not
// supported at all, so this is sound to do, but once we want to support them, you'll
// start seeing the error below.
- self.opaques.push(alias_ty.def_id.expect_local());
-
// Collect opaque types nested within the associated type bounds of this opaque type.
- for (pred, _span) in self
+ // We use identity substs here, because we already know that the opaque type uses
+ // only generic parameters, and thus substituting would not give us more information.
+ for (pred, span) in self
.tcx
.explicit_item_bounds(alias_ty.def_id)
- .subst_iter_copied(self.tcx, alias_ty.substs)
+ .subst_identity_iter_copied()
{
trace!(?pred);
- pred.visit_with(self)?;
+ self.visit_spanned(span, pred);
}
-
- ControlFlow::Continue(())
}
Err(NotUniqueParam::NotParam(arg)) => {
- let err = self.tcx.sess.emit_err(NotParam {
+ self.tcx.sess.emit_err(NotParam {
arg,
span: self.span(),
opaque_span: self.tcx.def_span(alias_ty.def_id),
});
- ControlFlow::Break(err)
}
Err(NotUniqueParam::DuplicateParam(arg)) => {
- let err = self.tcx.sess.emit_err(DuplicateArg {
+ self.tcx.sess.emit_err(DuplicateArg {
arg,
span: self.span(),
opaque_span: self.tcx.def_span(alias_ty.def_id),
});
- ControlFlow::Break(err)
}
}
}
- ty::Alias(AliasKind::Projection, alias_ty) => {
- if let Some(parent) = self.parent() {
- trace!(?alias_ty);
- let (trait_ref, own_substs) = alias_ty.trait_ref_and_own_substs(self.tcx);
-
- trace!(?trait_ref, ?own_substs);
- // This avoids having to do normalization of `Self::AssocTy` by only
- // supporting the case of a method defining opaque types from assoc types
- // in the same impl block.
- if trait_ref.self_ty() == self.tcx.type_of(parent).subst_identity() {
- for assoc in self.tcx.associated_items(parent).in_definition_order() {
+ ty::Alias(ty::Weak, alias_ty) if alias_ty.def_id.is_local() => {
+ self.tcx
+ .type_of(alias_ty.def_id)
+ .subst(self.tcx, alias_ty.substs)
+ .visit_with(self)?;
+ }
+ ty::Alias(ty::Projection, alias_ty) => {
+ // This avoids having to do normalization of `Self::AssocTy` by only
+ // supporting the case of a method defining opaque types from assoc types
+ // in the same impl block.
+ if let Some(parent_trait_ref) = self.parent_trait_ref() {
+ // If the trait ref of the associated item and the impl differs,
+ // then we can't use the impl's identity substitutions below, so
+ // just skip.
+ if alias_ty.trait_ref(self.tcx) == parent_trait_ref {
+ let parent = self.parent().expect("we should have a parent here");
+
+ for &assoc in self.tcx.associated_items(parent).in_definition_order() {
trace!(?assoc);
- if assoc.trait_item_def_id == Some(alias_ty.def_id) {
- // We reconstruct the generic args of the associated type within the impl
- // from the impl's generics and the generic args passed to the type via the
- // projection.
- let substs = ty::InternalSubsts::identity_for_item(
- self.tcx,
- parent.to_def_id(),
- );
- trace!(?substs);
- let substs: Vec<_> =
- substs.iter().chain(own_substs.iter().copied()).collect();
- trace!(?substs);
- // Find opaque types in this associated type.
+ if assoc.trait_item_def_id != Some(alias_ty.def_id) {
+ continue;
+ }
+
+ // If the type is further specializable, then the type_of
+ // is not actually correct below.
+ if !assoc.defaultness(self.tcx).is_final() {
+ continue;
+ }
+
+ let impl_substs = alias_ty.substs.rebase_onto(
+ self.tcx,
+ parent_trait_ref.def_id,
+ ty::InternalSubsts::identity_for_item(self.tcx, parent),
+ );
+
+ if check_substs_compatible(self.tcx, assoc, impl_substs) {
return self
.tcx
.type_of(assoc.def_id)
- .subst(self.tcx, &substs)
+ .subst(self.tcx, impl_substs)
.visit_with(self);
+ } else {
+ self.tcx.sess.delay_span_bug(
+ self.tcx.def_span(assoc.def_id),
+ "item had incorrect substs",
+ );
}
}
}
}
- t.super_visit_with(self)
}
- _ => t.super_visit_with(self),
+ ty::Adt(def, _) if def.did().is_local() => {
+ if !self.seen.insert(def.did().expect_local()) {
+ return ControlFlow::Continue(());
+ }
+ for variant in def.variants().iter() {
+ for field in variant.fields.iter() {
+ // Don't use the `ty::Adt` substs, we either
+ // * found the opaque in the substs
+ // * will find the opaque in the unsubstituted fields
+ // The only other situation that can occur is that after substituting,
+ // some projection resolves to an opaque that we would have otherwise
+ // not found. While we could substitute and walk those, that would mean we
+ // would have to walk all substitutions of an Adt, which can quickly
+ // degenerate into looking at an exponential number of types.
+ let ty = self.tcx.type_of(field.did).subst_identity();
+ self.visit_spanned(self.tcx.def_span(field.did), ty);
+ }
+ }
+ }
+ _ => trace!(kind=?t.kind()),
}
+ ControlFlow::Continue(())
}
}
fn opaque_types_defined_by<'tcx>(tcx: TyCtxt<'tcx>, item: LocalDefId) -> &'tcx [LocalDefId] {
let kind = tcx.def_kind(item);
trace!(?kind);
- // FIXME(type_alias_impl_trait): This is definitely still wrong except for RPIT and impl trait in assoc types.
+ let mut collector = OpaqueTypeCollector::new(tcx, item);
match kind {
- // We're also doing this for `AssocTy` for the wf checks in `check_opaque_meets_bounds`
- DefKind::Fn | DefKind::AssocFn | DefKind::AssocTy | DefKind::AssocConst => {
- let defined_opaques = match kind {
- DefKind::Fn => {
- OpaqueTypeCollector::collect(tcx, item, tcx.fn_sig(item).subst_identity())
- }
- DefKind::AssocFn => {
- OpaqueTypeCollector::collect(tcx, item, tcx.fn_sig(item).subst_identity())
- }
- DefKind::AssocTy | DefKind::AssocConst => OpaqueTypeCollector::collect(
- tcx,
- item,
- ty::Binder::dummy(tcx.type_of(item).subst_identity()),
- ),
- _ => unreachable!(),
+ // Walk over the signature of the function-like to find the opaques.
+ DefKind::AssocFn | DefKind::Fn => {
+ let ty_sig = tcx.fn_sig(item).subst_identity();
+ let hir_sig = tcx.hir().get_by_def_id(item).fn_sig().unwrap();
+ // Walk over the inputs and outputs manually in order to get good spans for them.
+ collector.visit_spanned(hir_sig.decl.output.span(), ty_sig.output());
+ for (hir, ty) in hir_sig.decl.inputs.iter().zip(ty_sig.inputs().iter()) {
+ collector.visit_spanned(hir.span, ty.map_bound(|x| *x));
+ }
+ collector.collect_body_and_predicate_taits();
+ }
+ // Walk over the type of the item to find opaques.
+ DefKind::Static(_) | DefKind::Const | DefKind::AssocConst | DefKind::AnonConst => {
+ let span = match tcx.hir().get_by_def_id(item).ty() {
+ Some(ty) => ty.span,
+ _ => tcx.def_span(item),
};
- tcx.arena.alloc_from_iter(defined_opaques)
+ collector.visit_spanned(span, tcx.type_of(item).subst_identity());
+ collector.collect_body_and_predicate_taits();
+ }
+ // We're also doing this for `AssocTy` for the wf checks in `check_opaque_meets_bounds`
+ DefKind::TyAlias | DefKind::AssocTy => {
+ tcx.type_of(item).subst_identity().visit_with(&mut collector);
+ }
+ DefKind::OpaqueTy => {
+ for (pred, span) in tcx.explicit_item_bounds(item).subst_identity_iter_copied() {
+ collector.visit_spanned(span, pred);
+ }
}
DefKind::Mod
| DefKind::Struct
@@ -168,29 +309,26 @@ fn opaque_types_defined_by<'tcx>(tcx: TyCtxt<'tcx>, item: LocalDefId) -> &'tcx [
| DefKind::Enum
| DefKind::Variant
| DefKind::Trait
- | DefKind::TyAlias
| DefKind::ForeignTy
| DefKind::TraitAlias
| DefKind::TyParam
- | DefKind::Const
| DefKind::ConstParam
- | DefKind::Static(_)
| DefKind::Ctor(_, _)
| DefKind::Macro(_)
| DefKind::ExternCrate
| DefKind::Use
| DefKind::ForeignMod
- | DefKind::AnonConst
- | DefKind::InlineConst
- | DefKind::OpaqueTy
| DefKind::ImplTraitPlaceholder
| DefKind::Field
| DefKind::LifetimeParam
| DefKind::GlobalAsm
- | DefKind::Impl { .. }
- | DefKind::Closure
- | DefKind::Generator => &[],
+ | DefKind::Impl { .. } => {}
+ // Closures and generators are type checked with their parent, so there is no difference here.
+ DefKind::Closure | DefKind::Generator | DefKind::InlineConst => {
+ return tcx.opaque_types_defined_by(tcx.local_parent(item));
+ }
}
+ tcx.arena.alloc_from_iter(collector.opaques)
}
pub(super) fn provide(providers: &mut Providers) {
diff --git a/compiler/rustc_ty_utils/src/ty.rs b/compiler/rustc_ty_utils/src/ty.rs
index 65dc3c39c..6e5c50492 100644
--- a/compiler/rustc_ty_utils/src/ty.rs
+++ b/compiler/rustc_ty_utils/src/ty.rs
@@ -1,13 +1,11 @@
-use rustc_data_structures::fx::{FxHashSet, FxIndexSet};
+use rustc_data_structures::fx::FxHashSet;
use rustc_hir as hir;
use rustc_hir::def::DefKind;
use rustc_index::bit_set::BitSet;
use rustc_middle::query::Providers;
use rustc_middle::ty::{
- self, Binder, EarlyBinder, ImplTraitInTraitData, Predicate, PredicateKind, ToPredicate, Ty,
- TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitor,
+ self, EarlyBinder, ToPredicate, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitor,
};
-use rustc_session::config::TraitSolver;
use rustc_span::def_id::{DefId, LocalDefId, CRATE_DEF_ID};
use rustc_span::DUMMY_SP;
use rustc_trait_selection::traits;
@@ -44,9 +42,7 @@ fn sized_constraint_for_ty<'tcx>(
let adt_tys = adt.sized_constraint(tcx);
debug!("sized_constraint_for_ty({:?}) intermediate = {:?}", ty, adt_tys);
adt_tys
- .0
- .iter()
- .map(|ty| adt_tys.rebind(*ty).subst(tcx, substs))
+ .subst_iter_copied(tcx, substs)
.flat_map(|ty| sized_constraint_for_ty(tcx, adtdef, ty))
.collect()
}
@@ -77,13 +73,13 @@ fn sized_constraint_for_ty<'tcx>(
result
}
-fn impl_defaultness(tcx: TyCtxt<'_>, def_id: LocalDefId) -> hir::Defaultness {
+fn defaultness(tcx: TyCtxt<'_>, def_id: LocalDefId) -> hir::Defaultness {
match tcx.hir().get_by_def_id(def_id) {
hir::Node::Item(hir::Item { kind: hir::ItemKind::Impl(impl_), .. }) => impl_.defaultness,
hir::Node::ImplItem(hir::ImplItem { defaultness, .. })
| hir::Node::TraitItem(hir::TraitItem { defaultness, .. }) => *defaultness,
node => {
- bug!("`impl_defaultness` called on {:?}", node);
+ bug!("`defaultness` called on {:?}", node);
}
}
}
@@ -99,7 +95,7 @@ fn impl_defaultness(tcx: TyCtxt<'_>, def_id: LocalDefId) -> hir::Defaultness {
fn adt_sized_constraint(tcx: TyCtxt<'_>, def_id: DefId) -> &[Ty<'_>] {
if let Some(def_id) = def_id.as_local() {
if matches!(tcx.representability(def_id), ty::Representability::Infinite) {
- return tcx.mk_type_list(&[tcx.ty_error_misc()]);
+ return tcx.mk_type_list(&[Ty::new_misc_error(tcx)]);
}
}
let def = tcx.adt_def(def_id);
@@ -107,7 +103,7 @@ fn adt_sized_constraint(tcx: TyCtxt<'_>, def_id: DefId) -> &[Ty<'_>] {
let result = tcx.mk_type_list_from_iter(
def.variants()
.iter()
- .filter_map(|v| v.fields.raw.last())
+ .filter_map(|v| v.tail_opt())
.flat_map(|f| sized_constraint_for_ty(tcx, def, tcx.type_of(f.did).subst_identity())),
);
@@ -122,20 +118,6 @@ fn param_env(tcx: TyCtxt<'_>, def_id: DefId) -> ty::ParamEnv<'_> {
let ty::InstantiatedPredicates { mut predicates, .. } =
tcx.predicates_of(def_id).instantiate_identity(tcx);
- // When computing the param_env of an RPITIT, use predicates of the containing function,
- // *except* for the additional assumption that the RPITIT normalizes to the trait method's
- // default opaque type. This is needed to properly check the item bounds of the assoc
- // type hold (`check_type_bounds`), since that method already installs a similar projection
- // bound, so they will conflict.
- // FIXME(-Zlower-impl-trait-in-trait-to-assoc-ty): I don't like this, we should
- // at least be making sure that the generics in RPITITs and their parent fn don't
- // get out of alignment, or else we do actually need to substitute these predicates.
- if let Some(ImplTraitInTraitData::Trait { fn_def_id, .. })
- | Some(ImplTraitInTraitData::Impl { fn_def_id, .. }) = tcx.opt_rpitit_info(def_id)
- {
- predicates = tcx.predicates_of(fn_def_id).instantiate_identity(tcx).predicates;
- }
-
// Finally, we have to normalize the bounds in the environment, in
// case they contain any associated type projections. This process
// can yield errors if the put in illegal associated types, like
@@ -148,11 +130,6 @@ fn param_env(tcx: TyCtxt<'_>, def_id: DefId) -> ty::ParamEnv<'_> {
// are any errors at that point, so outside of type inference you can be
// sure that this will succeed without errors anyway.
- if tcx.sess.opts.unstable_opts.trait_solver == TraitSolver::Chalk {
- let environment = well_formed_types_in_env(tcx, def_id);
- predicates.extend(environment);
- }
-
if tcx.def_kind(def_id) == DefKind::AssocFn
&& tcx.associated_item(def_id).container == ty::AssocItemContainer::TraitContainer
{
@@ -188,6 +165,7 @@ fn param_env(tcx: TyCtxt<'_>, def_id: DefId) -> ty::ParamEnv<'_> {
kind: hir::TraitItemKind::Const(..), ..
})
| hir::Node::AnonConst(_)
+ | hir::Node::ConstBlock(_)
| hir::Node::ImplItem(hir::ImplItem { kind: hir::ImplItemKind::Const(..), .. })
| hir::Node::ImplItem(hir::ImplItem {
kind:
@@ -246,7 +224,7 @@ fn param_env(tcx: TyCtxt<'_>, def_id: DefId) -> ty::ParamEnv<'_> {
};
let unnormalized_env =
- ty::ParamEnv::new(tcx.mk_predicates(&predicates), traits::Reveal::UserFacing, constness);
+ ty::ParamEnv::new(tcx.mk_clauses(&predicates), traits::Reveal::UserFacing, constness);
let body_id = local_did.unwrap_or(CRATE_DEF_ID);
let cause = traits::ObligationCause::misc(tcx.def_span(def_id), body_id);
@@ -259,7 +237,7 @@ fn param_env(tcx: TyCtxt<'_>, def_id: DefId) -> ty::ParamEnv<'_> {
/// its corresponding opaque within the body of a default-body trait method.
struct ImplTraitInTraitFinder<'a, 'tcx> {
tcx: TyCtxt<'tcx>,
- predicates: &'a mut Vec<Predicate<'tcx>>,
+ predicates: &'a mut Vec<ty::Clause<'tcx>>,
fn_def_id: DefId,
bound_vars: &'tcx ty::List<ty::BoundVariableKind>,
seen: FxHashSet<DefId>,
@@ -289,12 +267,13 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for ImplTraitInTraitFinder<'_, 'tcx> {
let shifted_alias_ty = self.tcx.fold_regions(unshifted_alias_ty, |re, depth| {
if let ty::ReLateBound(index, bv) = re.kind() {
if depth != ty::INNERMOST {
- return self.tcx.mk_re_error_with_message(
+ return ty::Region::new_error_with_message(
+ self.tcx,
DUMMY_SP,
"we shouldn't walk non-predicate binders with `impl Trait`...",
);
}
- self.tcx.mk_re_late_bound(index.shifted_out_to_binder(self.depth), bv)
+ ty::Region::new_late_bound(self.tcx, index.shifted_out_to_binder(self.depth), bv)
} else {
re
}
@@ -306,7 +285,7 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for ImplTraitInTraitFinder<'_, 'tcx> {
let default_ty = if self.tcx.lower_impl_trait_in_trait_to_assoc_ty() {
self.tcx.type_of(shifted_alias_ty.def_id).subst(self.tcx, shifted_alias_ty.substs)
} else {
- self.tcx.mk_alias(ty::Opaque, shifted_alias_ty)
+ Ty::new_alias(self.tcx,ty::Opaque, shifted_alias_ty)
};
self.predicates.push(
@@ -334,118 +313,6 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for ImplTraitInTraitFinder<'_, 'tcx> {
}
}
-/// Elaborate the environment.
-///
-/// Collect a list of `Predicate`'s used for building the `ParamEnv`. Adds `TypeWellFormedFromEnv`'s
-/// that are assumed to be well-formed (because they come from the environment).
-///
-/// Used only in chalk mode.
-fn well_formed_types_in_env(tcx: TyCtxt<'_>, def_id: DefId) -> &ty::List<Predicate<'_>> {
- use rustc_hir::{ForeignItemKind, ImplItemKind, ItemKind, Node, TraitItemKind};
- use rustc_middle::ty::subst::GenericArgKind;
-
- debug!("environment(def_id = {:?})", def_id);
-
- // The environment of an impl Trait type is its defining function's environment.
- if let Some(parent) = ty::is_impl_trait_defn(tcx, def_id) {
- return well_formed_types_in_env(tcx, parent.to_def_id());
- }
-
- // Compute the bounds on `Self` and the type parameters.
- let ty::InstantiatedPredicates { predicates, .. } =
- tcx.predicates_of(def_id).instantiate_identity(tcx);
-
- let clauses = predicates.into_iter();
-
- if !def_id.is_local() {
- return ty::List::empty();
- }
- let node = tcx.hir().get_by_def_id(def_id.expect_local());
-
- enum NodeKind {
- TraitImpl,
- InherentImpl,
- Fn,
- Other,
- }
-
- let node_kind = match node {
- Node::TraitItem(item) => match item.kind {
- TraitItemKind::Fn(..) => NodeKind::Fn,
- _ => NodeKind::Other,
- },
-
- Node::ImplItem(item) => match item.kind {
- ImplItemKind::Fn(..) => NodeKind::Fn,
- _ => NodeKind::Other,
- },
-
- Node::Item(item) => match item.kind {
- ItemKind::Impl(hir::Impl { of_trait: Some(_), .. }) => NodeKind::TraitImpl,
- ItemKind::Impl(hir::Impl { of_trait: None, .. }) => NodeKind::InherentImpl,
- ItemKind::Fn(..) => NodeKind::Fn,
- _ => NodeKind::Other,
- },
-
- Node::ForeignItem(item) => match item.kind {
- ForeignItemKind::Fn(..) => NodeKind::Fn,
- _ => NodeKind::Other,
- },
-
- // FIXME: closures?
- _ => NodeKind::Other,
- };
-
- // FIXME(eddyb) isn't the unordered nature of this a hazard?
- let mut inputs = FxIndexSet::default();
-
- match node_kind {
- // In a trait impl, we assume that the header trait ref and all its
- // constituents are well-formed.
- NodeKind::TraitImpl => {
- let trait_ref = tcx.impl_trait_ref(def_id).expect("not an impl").subst_identity();
-
- // FIXME(chalk): this has problems because of late-bound regions
- //inputs.extend(trait_ref.substs.iter().flat_map(|arg| arg.walk()));
- inputs.extend(trait_ref.substs.iter());
- }
-
- // In an inherent impl, we assume that the receiver type and all its
- // constituents are well-formed.
- NodeKind::InherentImpl => {
- let self_ty = tcx.type_of(def_id).subst_identity();
- inputs.extend(self_ty.walk());
- }
-
- // In an fn, we assume that the arguments and all their constituents are
- // well-formed.
- NodeKind::Fn => {
- let fn_sig = tcx.fn_sig(def_id).subst_identity();
- let fn_sig = tcx.liberate_late_bound_regions(def_id, fn_sig);
-
- inputs.extend(fn_sig.inputs().iter().flat_map(|ty| ty.walk()));
- }
-
- NodeKind::Other => (),
- }
- let input_clauses = inputs.into_iter().filter_map(|arg| {
- match arg.unpack() {
- GenericArgKind::Type(ty) => {
- let binder = Binder::dummy(PredicateKind::TypeWellFormedFromEnv(ty));
- Some(tcx.mk_predicate(binder))
- }
-
- // FIXME(eddyb) no WF conditions from lifetimes?
- GenericArgKind::Lifetime(_) => None,
-
- // FIXME(eddyb) support const generics in Chalk
- GenericArgKind::Const(_) => None,
- }
- });
-
- tcx.mk_predicates_from_iter(clauses.chain(input_clauses))
-}
-
fn param_env_reveal_all_normalized(tcx: TyCtxt<'_>, def_id: DefId) -> ty::ParamEnv<'_> {
tcx.param_env(def_id).with_reveal_all_normalized(tcx)
}
@@ -508,7 +375,7 @@ fn issue33140_self_ty(tcx: TyCtxt<'_>, def_id: DefId) -> Option<EarlyBinder<Ty<'
if self_ty_matches {
debug!("issue33140_self_ty - MATCHES!");
- Some(EarlyBinder(self_ty))
+ Some(EarlyBinder::bind(self_ty))
} else {
debug!("issue33140_self_ty - non-matching self type");
None
@@ -575,7 +442,7 @@ pub fn provide(providers: &mut Providers) {
param_env_reveal_all_normalized,
instance_def_size_estimate,
issue33140_self_ty,
- impl_defaultness,
+ defaultness,
unsizing_params_for_adt,
..*providers
};