summaryrefslogtreecommitdiffstats
path: root/compiler/rustc_ty_utils
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-18 02:49:50 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-18 02:49:50 +0000
commit9835e2ae736235810b4ea1c162ca5e65c547e770 (patch)
tree3fcebf40ed70e581d776a8a4c65923e8ec20e026 /compiler/rustc_ty_utils
parentReleasing progress-linux version 1.70.0+dfsg2-1~progress7.99u1. (diff)
downloadrustc-9835e2ae736235810b4ea1c162ca5e65c547e770.tar.xz
rustc-9835e2ae736235810b4ea1c162ca5e65c547e770.zip
Merging upstream version 1.71.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/messages.ftl62
-rw-r--r--compiler/rustc_ty_utils/src/abi.rs40
-rw-r--r--compiler/rustc_ty_utils/src/assoc.rs7
-rw-r--r--compiler/rustc_ty_utils/src/common_traits.rs11
-rw-r--r--compiler/rustc_ty_utils/src/consts.rs77
-rw-r--r--compiler/rustc_ty_utils/src/errors.rs24
-rw-r--r--compiler/rustc_ty_utils/src/implied_bounds.rs18
-rw-r--r--compiler/rustc_ty_utils/src/instance.rs149
-rw-r--r--compiler/rustc_ty_utils/src/layout.rs7
-rw-r--r--compiler/rustc_ty_utils/src/layout_sanity_check.rs96
-rw-r--r--compiler/rustc_ty_utils/src/lib.rs7
-rw-r--r--compiler/rustc_ty_utils/src/needs_drop.rs9
-rw-r--r--compiler/rustc_ty_utils/src/opaque_types.rs198
-rw-r--r--compiler/rustc_ty_utils/src/representability.rs2
-rw-r--r--compiler/rustc_ty_utils/src/structural_match.rs4
-rw-r--r--compiler/rustc_ty_utils/src/ty.rs10
17 files changed, 491 insertions, 231 deletions
diff --git a/compiler/rustc_ty_utils/Cargo.toml b/compiler/rustc_ty_utils/Cargo.toml
index 52fbd3ae0..51885c9b4 100644
--- a/compiler/rustc_ty_utils/Cargo.toml
+++ b/compiler/rustc_ty_utils/Cargo.toml
@@ -9,6 +9,7 @@ rustc_middle = { path = "../rustc_middle" }
rustc_data_structures = { path = "../rustc_data_structures" }
rustc_errors = { path = "../rustc_errors" }
rustc_hir = { path = "../rustc_hir" }
+rustc_fluent_macro = { path = "../rustc_fluent_macro" }
rustc_infer = { path = "../rustc_infer" }
rustc_macros = { path = "../rustc_macros" }
rustc_span = { path = "../rustc_span" }
diff --git a/compiler/rustc_ty_utils/messages.ftl b/compiler/rustc_ty_utils/messages.ftl
index 15a14112f..c416aa52a 100644
--- a/compiler/rustc_ty_utils/messages.ftl
+++ b/compiler/rustc_ty_utils/messages.ftl
@@ -1,57 +1,65 @@
-ty_utils_needs_drop_overflow = overflow while checking whether `{$query_ty}` requires drop
+ty_utils_address_and_deref_not_supported = dereferencing or taking the address is not supported in generic constants
-ty_utils_generic_constant_too_complex = overly complex generic constant
- .help = consider moving this anonymous constant into a `const` function
- .maybe_supported = this operation may be supported in the future
+ty_utils_adt_not_supported = struct/enum construction is not supported in generic constants
-ty_utils_borrow_not_supported = borrowing is not supported in generic constants
+ty_utils_array_not_supported = array construction is not supported in generic constants
-ty_utils_address_and_deref_not_supported = dereferencing or taking the address is not supported in generic constants
+ty_utils_assign_not_supported = assignment is not supported in generic constants
-ty_utils_array_not_supported = array construction is not supported in generic constants
+ty_utils_binary_not_supported = unsupported binary operation in generic constants
ty_utils_block_not_supported = blocks are not supported in generic constants
-ty_utils_never_to_any_not_supported = coercing the `never` type is not supported in generic constants
-
-ty_utils_tuple_not_supported = tuple construction is not supported in generic constants
+ty_utils_borrow_not_supported = borrowing is not supported in generic constants
-ty_utils_index_not_supported = indexing is not supported in generic constants
+ty_utils_box_not_supported = allocations are not allowed in generic constants
-ty_utils_field_not_supported = field access is not supported in generic constants
+ty_utils_closure_and_return_not_supported = closures and function keywords are not supported in generic constants
ty_utils_const_block_not_supported = const blocks are not supported in generic constants
-ty_utils_adt_not_supported = struct/enum construction is not supported in generic constants
+ty_utils_control_flow_not_supported = control flow is not supported in generic constants
-ty_utils_pointer_not_supported = pointer casts are not allowed in generic constants
+ty_utils_field_not_supported = field access is not supported in generic constants
-ty_utils_yield_not_supported = generator control flow is not allowed in generic constants
+ty_utils_generic_constant_too_complex = overly complex generic constant
+ .help = consider moving this anonymous constant into a `const` function
+ .maybe_supported = this operation may be supported in the future
-ty_utils_loop_not_supported = loops and loop control flow are not supported in generic constants
+ty_utils_impl_trait_duplicate_arg = non-defining opaque type use in defining scope
+ .label = generic argument `{$arg}` used twice
+ .note = for this opaque type
-ty_utils_box_not_supported = allocations are not allowed in generic constants
+ty_utils_impl_trait_not_param = non-defining opaque type use in defining scope
+ .label = argument `{$arg}` is not a generic parameter
+ .note = for this opaque type
-ty_utils_binary_not_supported = unsupported binary operation in generic constants
+ty_utils_index_not_supported = indexing is not supported in generic constants
+
+ty_utils_inline_asm_not_supported = assembly is not supported in generic constants
ty_utils_logical_op_not_supported = unsupported operation in generic constants, short-circuiting operations would imply control flow
-ty_utils_assign_not_supported = assignment is not supported in generic constants
+ty_utils_loop_not_supported = loops and loop control flow are not supported in generic constants
-ty_utils_closure_and_return_not_supported = closures and function keywords are not supported in generic constants
+ty_utils_multiple_array_fields_simd_type = monomorphising SIMD type `{$ty}` with more than one array field
-ty_utils_control_flow_not_supported = control flow is not supported in generic constants
+ty_utils_needs_drop_overflow = overflow while checking whether `{$query_ty}` requires drop
-ty_utils_inline_asm_not_supported = assembly is not supported in generic constants
+ty_utils_never_to_any_not_supported = coercing the `never` type is not supported in generic constants
+
+ty_utils_non_primitive_simd_type = monomorphising SIMD type `{$ty}` with a non-primitive-scalar (integer/float/pointer) element type `{$e_ty}`
ty_utils_operation_not_supported = unsupported operation in generic constants
-ty_utils_unexpected_fnptr_associated_item = `FnPtr` trait with unexpected associated item
+ty_utils_oversized_simd_type = monomorphising SIMD type `{$ty}` of length greater than {$max_lanes}
-ty_utils_zero_length_simd_type = monomorphising SIMD type `{$ty}` of zero length
+ty_utils_pointer_not_supported = pointer casts are not allowed in generic constants
-ty_utils_multiple_array_fields_simd_type = monomorphising SIMD type `{$ty}` with more than one array field
+ty_utils_tuple_not_supported = tuple construction is not supported in generic constants
-ty_utils_oversized_simd_type = monomorphising SIMD type `{$ty}` of length greater than {$max_lanes}
+ty_utils_unexpected_fnptr_associated_item = `FnPtr` trait with unexpected associated item
-ty_utils_non_primitive_simd_type = monomorphising SIMD type `{$ty}` with a non-primitive-scalar (integer/float/pointer) element type `{$e_ty}`
+ty_utils_yield_not_supported = generator control flow is not allowed in generic constants
+
+ty_utils_zero_length_simd_type = monomorphising SIMD type `{$ty}` of zero length
diff --git a/compiler/rustc_ty_utils/src/abi.rs b/compiler/rustc_ty_utils/src/abi.rs
index 271284b2d..15c191046 100644
--- a/compiler/rustc_ty_utils/src/abi.rs
+++ b/compiler/rustc_ty_utils/src/abi.rs
@@ -1,5 +1,6 @@
use rustc_hir as hir;
use rustc_hir::lang_items::LangItem;
+use rustc_middle::query::Providers;
use rustc_middle::ty::layout::{
fn_can_unwind, FnAbiError, HasParamEnv, HasTyCtxt, LayoutCx, LayoutOf, TyAndLayout,
};
@@ -14,8 +15,8 @@ use rustc_target::spec::abi::Abi as SpecAbi;
use std::iter;
-pub fn provide(providers: &mut ty::query::Providers) {
- *providers = ty::query::Providers { fn_abi_of_fn_ptr, fn_abi_of_instance, ..*providers };
+pub fn provide(providers: &mut Providers) {
+ *providers = Providers { fn_abi_of_fn_ptr, fn_abi_of_instance, ..*providers };
}
// NOTE(eddyb) this is private to avoid using it from outside of
@@ -237,6 +238,7 @@ fn adjust_for_rust_scalar<'tcx>(
layout: TyAndLayout<'tcx>,
offset: Size,
is_return: bool,
+ drop_target_pointee: Option<Ty<'tcx>>,
) {
// Booleans are always a noundef i1 that needs to be zero-extended.
if scalar.is_bool() {
@@ -250,14 +252,24 @@ fn adjust_for_rust_scalar<'tcx>(
}
// Only pointer types handled below.
- let Scalar::Initialized { value: Pointer(_), valid_range} = scalar else { return };
+ let Scalar::Initialized { value: Pointer(_), valid_range } = scalar else { return };
- if !valid_range.contains(0) {
+ // Set `nonnull` if the validity range excludes zero, or for the argument to `drop_in_place`,
+ // which must be nonnull per its documented safety requirements.
+ if !valid_range.contains(0) || drop_target_pointee.is_some() {
attrs.set(ArgAttribute::NonNull);
}
if let Some(pointee) = layout.pointee_info_at(&cx, offset) {
- if let Some(kind) = pointee.safe {
+ let kind = if let Some(kind) = pointee.safe {
+ Some(kind)
+ } else if let Some(pointee) = drop_target_pointee {
+ // The argument to `drop_in_place` is semantically equivalent to a mutable reference.
+ Some(PointerKind::MutableRef { unpin: pointee.is_unpin(cx.tcx, cx.param_env()) })
+ } else {
+ None
+ };
+ if let Some(kind) = kind {
attrs.pointee_align = Some(pointee.align);
// `Box` are not necessarily dereferenceable for the entire duration of the function as
@@ -361,10 +373,18 @@ fn fn_abi_new_uncached<'tcx>(
use SpecAbi::*;
let rust_abi = matches!(sig.abi, RustIntrinsic | PlatformIntrinsic | Rust | RustCall);
+ 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 span = tracing::debug_span!("arg_of");
let _entered = span.enter();
let is_return = arg_idx.is_none();
+ let is_drop_target = is_drop_in_place && arg_idx == Some(0);
+ let drop_target_pointee = is_drop_target.then(|| match ty.kind() {
+ ty::RawPtr(ty::TypeAndMut { ty, .. }) => *ty,
+ _ => bug!("argument to drop_in_place is not a raw ptr: {:?}", ty),
+ });
let layout = cx.layout_of(ty)?;
let layout = if force_thin_self_ptr && arg_idx == Some(0) {
@@ -378,7 +398,15 @@ fn fn_abi_new_uncached<'tcx>(
let mut arg = ArgAbi::new(cx, layout, |layout, scalar, offset| {
let mut attrs = ArgAttributes::new();
- adjust_for_rust_scalar(*cx, &mut attrs, scalar, *layout, offset, is_return);
+ adjust_for_rust_scalar(
+ *cx,
+ &mut attrs,
+ scalar,
+ *layout,
+ offset,
+ is_return,
+ drop_target_pointee,
+ );
attrs
});
diff --git a/compiler/rustc_ty_utils/src/assoc.rs b/compiler/rustc_ty_utils/src/assoc.rs
index de1e1a527..ed574f22e 100644
--- a/compiler/rustc_ty_utils/src/assoc.rs
+++ b/compiler/rustc_ty_utils/src/assoc.rs
@@ -4,11 +4,12 @@ use rustc_hir::def::DefKind;
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_span::symbol::kw;
-pub fn provide(providers: &mut ty::query::Providers) {
- *providers = ty::query::Providers {
+pub fn provide(providers: &mut Providers) {
+ *providers = Providers {
associated_item,
associated_item_def_ids,
associated_items,
@@ -334,7 +335,7 @@ fn associated_type_for_impl_trait_in_trait(
parent_count,
params,
param_def_id_to_index,
- has_self: false,
+ has_self: opaque_ty_generics.has_self,
has_late_bound_regions: opaque_ty_generics.has_late_bound_regions,
}
});
diff --git a/compiler/rustc_ty_utils/src/common_traits.rs b/compiler/rustc_ty_utils/src/common_traits.rs
index 3b1abdcb2..51b908881 100644
--- a/compiler/rustc_ty_utils/src/common_traits.rs
+++ b/compiler/rustc_ty_utils/src/common_traits.rs
@@ -2,6 +2,7 @@
use rustc_hir::lang_items::LangItem;
use rustc_infer::infer::TyCtxtInferExt;
+use rustc_middle::query::Providers;
use rustc_middle::ty::{self, Ty, TyCtxt};
use rustc_trait_selection::traits;
@@ -32,12 +33,6 @@ fn is_item_raw<'tcx>(
traits::type_known_to_meet_bound_modulo_regions(&infcx, param_env, ty, trait_def_id)
}
-pub(crate) fn provide(providers: &mut ty::query::Providers) {
- *providers = ty::query::Providers {
- is_copy_raw,
- is_sized_raw,
- is_freeze_raw,
- is_unpin_raw,
- ..*providers
- };
+pub(crate) fn provide(providers: &mut Providers) {
+ *providers = Providers { is_copy_raw, is_sized_raw, is_freeze_raw, is_unpin_raw, ..*providers };
}
diff --git a/compiler/rustc_ty_utils/src/consts.rs b/compiler/rustc_ty_utils/src/consts.rs
index b67607a4d..1219bb400 100644
--- a/compiler/rustc_ty_utils/src/consts.rs
+++ b/compiler/rustc_ty_utils/src/consts.rs
@@ -2,6 +2,7 @@ use rustc_errors::ErrorGuaranteed;
use rustc_hir::def::DefKind;
use rustc_hir::def_id::LocalDefId;
use rustc_middle::mir::interpret::{LitToConstError, LitToConstInput};
+use rustc_middle::query::Providers;
use rustc_middle::thir::visit;
use rustc_middle::thir::visit::Visitor;
use rustc_middle::ty::abstract_const::CastKind;
@@ -115,9 +116,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_with_guaranteed(node.ty, guar)
- }
+ Err(LitToConstError::Reported(guar)) => tcx.const_error(node.ty, guar),
Err(LitToConstError::TypeError) => {
bug!("encountered type error in lit_to_const")
}
@@ -132,7 +131,7 @@ fn recurse_build<'tcx>(
tcx.mk_const(val, node.ty)
}
&ExprKind::NamedConst { def_id, substs, user_ty: _ } => {
- let uneval = ty::UnevaluatedConst::new(ty::WithOptConstParam::unknown(def_id), substs);
+ let uneval = ty::UnevaluatedConst::new(def_id, substs);
tcx.mk_const(uneval, node.ty)
}
ExprKind::ConstParam { param, .. } => tcx.mk_const(*param, node.ty),
@@ -256,6 +255,7 @@ fn recurse_build<'tcx>(
ExprKind::VarRef { .. }
| ExprKind::UpvarRef { .. }
| ExprKind::StaticRef { .. }
+ | ExprKind::OffsetOf { .. }
| ExprKind::ThreadLocalRef(_) => {
error(GenericConstantTooComplexSub::OperationNotSupported(node.span))?
}
@@ -347,6 +347,7 @@ impl<'a, 'tcx> IsThirPolymorphic<'a, 'tcx> {
| thir::ExprKind::ZstLiteral { .. }
| thir::ExprKind::StaticRef { .. }
| thir::ExprKind::InlineAsm(_)
+ | thir::ExprKind::OffsetOf { .. }
| thir::ExprKind::ThreadLocalRef(_)
| thir::ExprKind::Yield { .. } => false,
}
@@ -391,52 +392,36 @@ impl<'a, 'tcx> visit::Visitor<'a, 'tcx> for IsThirPolymorphic<'a, 'tcx> {
/// Builds an abstract const, do not use this directly, but use `AbstractConst::new` instead.
pub fn thir_abstract_const(
tcx: TyCtxt<'_>,
- def: ty::WithOptConstParam<LocalDefId>,
-) -> Result<Option<ty::Const<'_>>, ErrorGuaranteed> {
- if tcx.features().generic_const_exprs {
- match tcx.def_kind(def.did) {
- // FIXME(generic_const_exprs): We currently only do this for anonymous constants,
- // meaning that we do not look into associated constants. I(@lcnr) am not yet sure whether
- // we want to look into them or treat them as opaque projections.
- //
- // Right now we do neither of that and simply always fail to unify them.
- DefKind::AnonConst | DefKind::InlineConst => (),
- _ => return Ok(None),
- }
-
- let body = tcx.thir_body(def)?;
- let (body, body_id) = (&*body.0.borrow(), body.1);
+ def: LocalDefId,
+) -> Result<Option<ty::EarlyBinder<ty::Const<'_>>>, ErrorGuaranteed> {
+ if !tcx.features().generic_const_exprs {
+ return Ok(None);
+ }
- let mut is_poly_vis = IsThirPolymorphic { is_poly: false, thir: body };
- visit::walk_expr(&mut is_poly_vis, &body[body_id]);
- if !is_poly_vis.is_poly {
- return Ok(None);
- }
+ match tcx.def_kind(def) {
+ // FIXME(generic_const_exprs): We currently only do this for anonymous constants,
+ // meaning that we do not look into associated constants. I(@lcnr) am not yet sure whether
+ // we want to look into them or treat them as opaque projections.
+ //
+ // Right now we do neither of that and simply always fail to unify them.
+ DefKind::AnonConst | DefKind::InlineConst => (),
+ _ => return Ok(None),
+ }
- let root_span = body.exprs[body_id].span;
+ let body = tcx.thir_body(def)?;
+ let (body, body_id) = (&*body.0.borrow(), body.1);
- Some(recurse_build(tcx, body, body_id, root_span)).transpose()
- } else {
- Ok(None)
+ let mut is_poly_vis = IsThirPolymorphic { is_poly: false, thir: body };
+ visit::walk_expr(&mut is_poly_vis, &body[body_id]);
+ if !is_poly_vis.is_poly {
+ return Ok(None);
}
+
+ let root_span = body.exprs[body_id].span;
+
+ Ok(Some(ty::EarlyBinder(recurse_build(tcx, body, body_id, root_span)?)))
}
-pub fn provide(providers: &mut ty::query::Providers) {
- *providers = ty::query::Providers {
- destructure_const,
- thir_abstract_const: |tcx, def_id| {
- if let Some(def) = ty::WithOptConstParam::try_lookup(def_id, tcx) {
- tcx.thir_abstract_const_of_const_arg(def)
- } else {
- thir_abstract_const(tcx, ty::WithOptConstParam::unknown(def_id))
- }
- },
- thir_abstract_const_of_const_arg: |tcx, (did, param_did)| {
- thir_abstract_const(
- tcx,
- ty::WithOptConstParam { did, const_param_did: Some(param_did) },
- )
- },
- ..*providers
- };
+pub fn provide(providers: &mut Providers) {
+ *providers = Providers { destructure_const, thir_abstract_const, ..*providers };
}
diff --git a/compiler/rustc_ty_utils/src/errors.rs b/compiler/rustc_ty_utils/src/errors.rs
index 3d3fc50e6..553bf40ef 100644
--- a/compiler/rustc_ty_utils/src/errors.rs
+++ b/compiler/rustc_ty_utils/src/errors.rs
@@ -1,7 +1,7 @@
//! Errors emitted by ty_utils
use rustc_macros::{Diagnostic, Subdiagnostic};
-use rustc_middle::ty::Ty;
+use rustc_middle::ty::{GenericArg, Ty};
use rustc_span::Span;
#[derive(Diagnostic)]
@@ -100,3 +100,25 @@ pub struct NonPrimitiveSimdType<'tcx> {
pub ty: Ty<'tcx>,
pub e_ty: Ty<'tcx>,
}
+
+#[derive(Diagnostic)]
+#[diag(ty_utils_impl_trait_duplicate_arg)]
+pub struct DuplicateArg<'tcx> {
+ pub arg: GenericArg<'tcx>,
+ #[primary_span]
+ #[label]
+ pub span: Span,
+ #[note]
+ pub opaque_span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(ty_utils_impl_trait_not_param)]
+pub struct NotParam<'tcx> {
+ pub arg: GenericArg<'tcx>,
+ #[primary_span]
+ #[label]
+ pub span: Span,
+ #[note]
+ pub opaque_span: Span,
+}
diff --git a/compiler/rustc_ty_utils/src/implied_bounds.rs b/compiler/rustc_ty_utils/src/implied_bounds.rs
index 56d6cc28b..081be0658 100644
--- a/compiler/rustc_ty_utils/src/implied_bounds.rs
+++ b/compiler/rustc_ty_utils/src/implied_bounds.rs
@@ -1,8 +1,9 @@
use rustc_hir::{def::DefKind, def_id::DefId};
+use rustc_middle::query::Providers;
use rustc_middle::ty::{self, Ty, TyCtxt};
-pub fn provide(providers: &mut ty::query::Providers) {
- *providers = ty::query::Providers { assumed_wf_types, ..*providers };
+pub fn provide(providers: &mut Providers) {
+ *providers = Providers { assumed_wf_types, ..*providers };
}
fn assumed_wf_types(tcx: TyCtxt<'_>, def_id: DefId) -> &ty::List<Ty<'_>> {
@@ -31,6 +32,18 @@ fn assumed_wf_types(tcx: TyCtxt<'_>, def_id: DefId) -> &ty::List<Ty<'_>> {
}
}
DefKind::AssocConst | DefKind::AssocTy => tcx.assumed_wf_types(tcx.parent(def_id)),
+ DefKind::OpaqueTy => match tcx.def_kind(tcx.parent(def_id)) {
+ DefKind::TyAlias => ty::List::empty(),
+ DefKind::AssocTy => tcx.assumed_wf_types(tcx.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"),
+ def_kind @ _ => {
+ bug!("unimplemented implied bounds for opaque types with parent {def_kind:?}")
+ }
+ },
DefKind::Mod
| DefKind::Struct
| DefKind::Union
@@ -51,7 +64,6 @@ fn assumed_wf_types(tcx: TyCtxt<'_>, def_id: DefId) -> &ty::List<Ty<'_>> {
| DefKind::ForeignMod
| DefKind::AnonConst
| DefKind::InlineConst
- | DefKind::OpaqueTy
| DefKind::ImplTraitPlaceholder
| DefKind::Field
| DefKind::LifetimeParam
diff --git a/compiler/rustc_ty_utils/src/instance.rs b/compiler/rustc_ty_utils/src/instance.rs
index 0a6c11809..36a20c78f 100644
--- a/compiler/rustc_ty_utils/src/instance.rs
+++ b/compiler/rustc_ty_utils/src/instance.rs
@@ -1,6 +1,7 @@
use rustc_errors::ErrorGuaranteed;
-use rustc_hir::def_id::{DefId, LocalDefId};
+use rustc_hir::def_id::DefId;
use rustc_infer::infer::TyCtxtInferExt;
+use rustc_middle::query::Providers;
use rustc_middle::traits::CodegenObligationError;
use rustc_middle::ty::subst::SubstsRef;
use rustc_middle::ty::{self, Instance, TyCtxt, TypeVisitableExt};
@@ -14,54 +15,25 @@ fn resolve_instance<'tcx>(
tcx: TyCtxt<'tcx>,
key: ty::ParamEnvAnd<'tcx, (DefId, SubstsRef<'tcx>)>,
) -> Result<Option<Instance<'tcx>>, ErrorGuaranteed> {
- let (param_env, (did, substs)) = key.into_parts();
- if let Some(did) = did.as_local() {
- if let Some(param_did) = tcx.opt_const_param_of(did) {
- return tcx.resolve_instance_of_const_arg(param_env.and((did, param_did, substs)));
- }
- }
-
- inner_resolve_instance(tcx, param_env.and((ty::WithOptConstParam::unknown(did), substs)))
-}
-
-fn resolve_instance_of_const_arg<'tcx>(
- tcx: TyCtxt<'tcx>,
- key: ty::ParamEnvAnd<'tcx, (LocalDefId, DefId, SubstsRef<'tcx>)>,
-) -> Result<Option<Instance<'tcx>>, ErrorGuaranteed> {
- let (param_env, (did, const_param_did, substs)) = key.into_parts();
- inner_resolve_instance(
- tcx,
- param_env.and((
- ty::WithOptConstParam { did: did.to_def_id(), const_param_did: Some(const_param_did) },
- substs,
- )),
- )
-}
-
-fn inner_resolve_instance<'tcx>(
- tcx: TyCtxt<'tcx>,
- key: ty::ParamEnvAnd<'tcx, (ty::WithOptConstParam<DefId>, SubstsRef<'tcx>)>,
-) -> Result<Option<Instance<'tcx>>, ErrorGuaranteed> {
let (param_env, (def, substs)) = key.into_parts();
- let result = if let Some(trait_def_id) = tcx.trait_of_item(def.did) {
+ let result = if let Some(trait_def_id) = tcx.trait_of_item(def) {
debug!(" => associated item, attempting to find impl in param_env {:#?}", param_env);
resolve_associated_item(
tcx,
- def.did,
+ def,
param_env,
trait_def_id,
tcx.normalize_erasing_regions(param_env, substs),
)
} else {
- let ty = tcx.type_of(def.def_id_for_type_of());
- let item_type =
- tcx.subst_and_normalize_erasing_regions(substs, param_env, ty.skip_binder());
+ let ty = tcx.type_of(def);
+ let item_type = tcx.subst_and_normalize_erasing_regions(substs, param_env, ty);
let def = match *item_type.kind() {
ty::FnDef(def_id, ..) if tcx.is_intrinsic(def_id) => {
debug!(" => intrinsic");
- ty::InstanceDef::Intrinsic(def.did)
+ ty::InstanceDef::Intrinsic(def)
}
ty::FnDef(def_id, substs) if Some(def_id) == tcx.lang_items().drop_in_place_fn() => {
let ty = substs.type_at(0);
@@ -113,7 +85,7 @@ fn resolve_associated_item<'tcx>(
Err(CodegenObligationError::Ambiguity) => {
let reported = tcx.sess.delay_span_bug(
tcx.def_span(trait_item_id),
- &format!(
+ format!(
"encountered ambiguity selecting `{trait_ref:?}` during codegen, presuming due to \
overflow or prior type error",
),
@@ -132,8 +104,8 @@ fn resolve_associated_item<'tcx>(
"resolving ImplSource::UserDefined: {:?}, {:?}, {:?}, {:?}",
param_env, trait_item_id, rcvr_substs, impl_data
);
- assert!(!rcvr_substs.needs_infer());
- assert!(!trait_ref.needs_infer());
+ assert!(!rcvr_substs.has_infer());
+ assert!(!trait_ref.has_infer());
let trait_def_id = tcx.trait_id_of_impl(impl_data.impl_def_id).unwrap();
let trait_def = tcx.trait_def(trait_def_id);
@@ -205,19 +177,52 @@ fn resolve_associated_item<'tcx>(
Some(ty::Instance::new(leaf_def.item.def_id, substs))
}
- traits::ImplSource::Generator(generator_data) => Some(Instance {
- def: ty::InstanceDef::Item(ty::WithOptConstParam::unknown(
- generator_data.generator_def_id,
- )),
- substs: generator_data.substs,
- }),
- traits::ImplSource::Future(future_data) => Some(Instance {
- def: ty::InstanceDef::Item(ty::WithOptConstParam::unknown(
- future_data.generator_def_id,
- )),
- substs: future_data.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,
@@ -227,22 +232,37 @@ fn resolve_associated_item<'tcx>(
)
}
traits::ImplSource::FnPointer(ref data) => match data.fn_ty.kind() {
- ty::FnDef(..) | ty::FnPtr(..) => Some(Instance {
- def: ty::InstanceDef::FnPtrShim(trait_item_id, data.fn_ty),
- substs: rcvr_substs,
- }),
- _ => None,
- },
- traits::ImplSource::Object(ref data) => {
- if let Some(index) = traits::get_vtable_index_of_object_method(tcx, data, trait_item_id)
- {
+ 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::Virtual(trait_item_id, index),
+ def: ty::InstanceDef::FnPtrShim(trait_item_id, data.fn_ty),
substs: rcvr_substs,
})
- } else {
- None
}
+ _ => 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 {
+ def: ty::InstanceDef::Virtual(trait_item_id, index),
+ substs: rcvr_substs,
+ }
+ })
}
traits::ImplSource::Builtin(..) => {
let lang_items = tcx.lang_items();
@@ -300,7 +320,6 @@ fn resolve_associated_item<'tcx>(
})
}
-pub fn provide(providers: &mut ty::query::Providers) {
- *providers =
- ty::query::Providers { resolve_instance, resolve_instance_of_const_arg, ..*providers };
+pub fn provide(providers: &mut Providers) {
+ *providers = Providers { resolve_instance, ..*providers };
}
diff --git a/compiler/rustc_ty_utils/src/layout.rs b/compiler/rustc_ty_utils/src/layout.rs
index 63ef1c724..16cd8bc8e 100644
--- a/compiler/rustc_ty_utils/src/layout.rs
+++ b/compiler/rustc_ty_utils/src/layout.rs
@@ -1,8 +1,9 @@
use hir::def_id::DefId;
use rustc_hir as hir;
use rustc_index::bit_set::BitSet;
-use rustc_index::vec::{IndexSlice, IndexVec};
+use rustc_index::{IndexSlice, IndexVec};
use rustc_middle::mir::{GeneratorLayout, GeneratorSavedLocal};
+use rustc_middle::query::Providers;
use rustc_middle::ty::layout::{
IntegerExt, LayoutCx, LayoutError, LayoutOf, TyAndLayout, MAX_SIMD_LANES,
};
@@ -22,8 +23,8 @@ use crate::errors::{
};
use crate::layout_sanity_check::sanity_check_layout;
-pub fn provide(providers: &mut ty::query::Providers) {
- *providers = ty::query::Providers { layout_of, ..*providers };
+pub fn provide(providers: &mut Providers) {
+ *providers = Providers { layout_of, ..*providers };
}
#[instrument(skip(tcx, query), level = "debug")]
diff --git a/compiler/rustc_ty_utils/src/layout_sanity_check.rs b/compiler/rustc_ty_utils/src/layout_sanity_check.rs
index a5311dbd1..c4a4cda68 100644
--- a/compiler/rustc_ty_utils/src/layout_sanity_check.rs
+++ b/compiler/rustc_ty_utils/src/layout_sanity_check.rs
@@ -4,7 +4,7 @@ use rustc_middle::ty::{
};
use rustc_target::abi::*;
-use std::cmp;
+use std::assert_matches::assert_matches;
/// Enforce some basic invariants on layouts.
pub(super) fn sanity_check_layout<'tcx>(
@@ -68,21 +68,31 @@ pub(super) fn sanity_check_layout<'tcx>(
}
fn check_layout_abi<'tcx>(cx: &LayoutCx<'tcx, TyCtxt<'tcx>>, layout: &TyAndLayout<'tcx>) {
+ // Verify the ABI mandated alignment and size.
+ let align = layout.abi.inherent_align(cx).map(|align| align.abi);
+ let size = layout.abi.inherent_size(cx);
+ let Some((align, size)) = align.zip(size) else {
+ assert_matches!(
+ layout.layout.abi(),
+ Abi::Uninhabited | Abi::Aggregate { .. },
+ "ABI unexpectedly missing alignment and/or size in {layout:#?}"
+ );
+ return
+ };
+ assert_eq!(
+ layout.layout.align().abi,
+ align,
+ "alignment mismatch between ABI and layout in {layout:#?}"
+ );
+ assert_eq!(
+ layout.layout.size(),
+ size,
+ "size mismatch between ABI and layout in {layout:#?}"
+ );
+
+ // Verify per-ABI invariants
match layout.layout.abi() {
- Abi::Scalar(scalar) => {
- // No padding in scalars.
- let size = scalar.size(cx);
- let align = scalar.align(cx).abi;
- assert_eq!(
- layout.layout.size(),
- size,
- "size mismatch between ABI and layout in {layout:#?}"
- );
- assert_eq!(
- layout.layout.align().abi,
- align,
- "alignment mismatch between ABI and layout in {layout:#?}"
- );
+ Abi::Scalar(_) => {
// Check that this matches the underlying field.
let inner = skip_newtypes(cx, layout);
assert!(
@@ -135,24 +145,6 @@ pub(super) fn sanity_check_layout<'tcx>(
}
}
Abi::ScalarPair(scalar1, scalar2) => {
- // Sanity-check scalar pairs. Computing the expected size and alignment is a bit of work.
- let size1 = scalar1.size(cx);
- let align1 = scalar1.align(cx).abi;
- let size2 = scalar2.size(cx);
- let align2 = scalar2.align(cx).abi;
- let align = cmp::max(align1, align2);
- let field2_offset = size1.align_to(align2);
- let size = (field2_offset + size2).align_to(align);
- assert_eq!(
- layout.layout.size(),
- size,
- "size mismatch between ABI and layout in {layout:#?}"
- );
- assert_eq!(
- layout.layout.align().abi,
- align,
- "alignment mismatch between ABI and layout in {layout:#?}",
- );
// Check that the underlying pair of fields matches.
let inner = skip_newtypes(cx, layout);
assert!(
@@ -189,8 +181,9 @@ pub(super) fn sanity_check_layout<'tcx>(
"`ScalarPair` layout for type with less than two non-ZST fields: {inner:#?}"
)
});
- assert!(
- fields.next().is_none(),
+ assert_matches!(
+ fields.next(),
+ None,
"`ScalarPair` layout for type with at least three non-ZST fields: {inner:#?}"
);
// The fields might be in opposite order.
@@ -200,6 +193,10 @@ pub(super) fn sanity_check_layout<'tcx>(
(offset2, field2, offset1, field1)
};
// The fields should be at the right offset, and match the `scalar` layout.
+ let size1 = scalar1.size(cx);
+ let align1 = scalar1.align(cx).abi;
+ let size2 = scalar2.size(cx);
+ let align2 = scalar2.align(cx).abi;
assert_eq!(
offset1,
Size::ZERO,
@@ -213,10 +210,12 @@ pub(super) fn sanity_check_layout<'tcx>(
field1.align.abi, align1,
"`ScalarPair` first field with bad align in {inner:#?}",
);
- assert!(
- matches!(field1.abi, Abi::Scalar(_)),
+ assert_matches!(
+ field1.abi,
+ Abi::Scalar(_),
"`ScalarPair` first field with bad ABI in {inner:#?}",
);
+ let field2_offset = size1.align_to(align2);
assert_eq!(
offset2, field2_offset,
"`ScalarPair` second field at bad offset in {inner:#?}",
@@ -229,27 +228,14 @@ pub(super) fn sanity_check_layout<'tcx>(
field2.align.abi, align2,
"`ScalarPair` second field with bad align in {inner:#?}",
);
- assert!(
- matches!(field2.abi, Abi::Scalar(_)),
+ assert_matches!(
+ field2.abi,
+ Abi::Scalar(_),
"`ScalarPair` second field with bad ABI in {inner:#?}",
);
}
- Abi::Vector { count, element } => {
- // No padding in vectors, except possibly for trailing padding to make the size a multiple of align.
- let size = element.size(cx) * count;
- let align = cx.data_layout().vector_align(size).abi;
- let size = size.align_to(align); // needed e.g. for vectors of size 3
+ Abi::Vector { element, .. } => {
assert!(align >= element.align(cx).abi); // just sanity-checking `vector_align`.
- assert_eq!(
- layout.layout.size(),
- size,
- "size mismatch between ABI and layout in {layout:#?}"
- );
- assert_eq!(
- layout.layout.align().abi,
- align,
- "alignment mismatch between ABI and layout in {layout:#?}"
- );
// FIXME: Do some kind of check of the inner type, like for Scalar and ScalarPair.
}
Abi::Uninhabited | Abi::Aggregate { .. } => {} // Nothing to check.
@@ -285,7 +271,7 @@ pub(super) fn sanity_check_layout<'tcx>(
{
// These are never actually accessed anyway, so we can skip the coherence check
// for them. They also fail that check, since they have
- // `Aggregate`/`Uninhbaited` ABI even when the main type is
+ // `Aggregate`/`Uninhabited` ABI even when the main type is
// `Scalar`/`ScalarPair`. (Note that sometimes, variants with fields have size
// 0, and sometimes, variants without fields have non-0 size.)
continue;
diff --git a/compiler/rustc_ty_utils/src/lib.rs b/compiler/rustc_ty_utils/src/lib.rs
index 2613445f3..55b8857ed 100644
--- a/compiler/rustc_ty_utils/src/lib.rs
+++ b/compiler/rustc_ty_utils/src/lib.rs
@@ -5,6 +5,7 @@
//! This API is completely unstable and subject to change.
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
+#![feature(assert_matches)]
#![feature(iterator_try_collect)]
#![feature(let_chains)]
#![feature(never_type)]
@@ -19,8 +20,8 @@ extern crate rustc_middle;
extern crate tracing;
use rustc_errors::{DiagnosticMessage, SubdiagnosticMessage};
-use rustc_macros::fluent_messages;
-use rustc_middle::ty::query::Providers;
+use rustc_fluent_macro::fluent_messages;
+use rustc_middle::query::Providers;
mod abi;
mod assoc;
@@ -32,6 +33,7 @@ pub mod instance;
mod layout;
mod layout_sanity_check;
mod needs_drop;
+mod opaque_types;
pub mod representability;
mod structural_match;
mod ty;
@@ -46,6 +48,7 @@ pub fn provide(providers: &mut Providers) {
implied_bounds::provide(providers);
layout::provide(providers);
needs_drop::provide(providers);
+ opaque_types::provide(providers);
representability::provide(providers);
ty::provide(providers);
instance::provide(providers);
diff --git a/compiler/rustc_ty_utils/src/needs_drop.rs b/compiler/rustc_ty_utils/src/needs_drop.rs
index de7fd0031..1f9701b93 100644
--- a/compiler/rustc_ty_utils/src/needs_drop.rs
+++ b/compiler/rustc_ty_utils/src/needs_drop.rs
@@ -2,6 +2,7 @@
use rustc_data_structures::fx::FxHashSet;
use rustc_hir::def_id::DefId;
+use rustc_middle::query::Providers;
use rustc_middle::ty::subst::SubstsRef;
use rustc_middle::ty::util::{needs_drop_components, AlwaysRequiresDrop};
use rustc_middle::ty::{self, EarlyBinder, Ty, TyCtxt};
@@ -132,7 +133,7 @@ where
_ => {
tcx.sess.delay_span_bug(
tcx.hir().span_if_local(def_id).unwrap_or(DUMMY_SP),
- &format!("unexpected generator witness type {:?}", witness),
+ format!("unexpected generator witness type {:?}", witness),
);
return Some(Err(AlwaysRequiresDrop));
}
@@ -243,7 +244,7 @@ fn drop_tys_helper<'tcx>(
} else {
let field_tys = adt_def.all_fields().map(|field| {
let r = tcx.type_of(field.did).subst(tcx, substs);
- debug!("drop_tys_helper: Subst into {:?} with {:?} gettng {:?}", field, substs, r);
+ debug!("drop_tys_helper: Subst into {:?} with {:?} getting {:?}", field, substs, r);
r
});
if only_significant {
@@ -323,8 +324,8 @@ fn adt_significant_drop_tys(
.map(|components| tcx.mk_type_list(&components))
}
-pub(crate) fn provide(providers: &mut ty::query::Providers) {
- *providers = ty::query::Providers {
+pub(crate) fn provide(providers: &mut Providers) {
+ *providers = Providers {
needs_drop_raw,
has_significant_drop_raw,
adt_drop_tys,
diff --git a/compiler/rustc_ty_utils/src/opaque_types.rs b/compiler/rustc_ty_utils/src/opaque_types.rs
new file mode 100644
index 000000000..4e91dd380
--- /dev/null
+++ b/compiler/rustc_ty_utils/src/opaque_types.rs
@@ -0,0 +1,198 @@
+use rustc_data_structures::fx::FxHashSet;
+use rustc_errors::ErrorGuaranteed;
+use rustc_hir::{def::DefKind, def_id::LocalDefId};
+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 std::ops::ControlFlow;
+
+use crate::errors::{DuplicateArg, NotParam};
+
+struct OpaqueTypeCollector<'tcx> {
+ tcx: TyCtxt<'tcx>,
+ opaques: Vec<LocalDefId>,
+ /// The `DefId` of the item which we are collecting opaque types for.
+ item: LocalDefId,
+
+ /// Avoid infinite recursion due to recursive declarations.
+ seen: FxHashSet<LocalDefId>,
+}
+
+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 span(&self) -> Span {
+ self.tcx.def_span(self.item)
+ }
+
+ fn parent(&self) -> Option<LocalDefId> {
+ match self.tcx.def_kind(self.item) {
+ DefKind::Fn => None,
+ DefKind::AssocFn | DefKind::AssocTy | DefKind::AssocConst => {
+ Some(self.tcx.local_parent(self.item))
+ }
+ other => span_bug!(
+ self.tcx.def_span(self.item),
+ "unhandled item with opaque types: {other:?}"
+ ),
+ }
+ }
+}
+
+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> {
+ match t.kind() {
+ ty::Alias(AliasKind::Opaque, alias_ty) if alias_ty.def_id.is_local() => {
+ if !self.seen.insert(alias_ty.def_id.expect_local()) {
+ return ControlFlow::Continue(());
+ }
+ 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
+ .tcx
+ .explicit_item_bounds(alias_ty.def_id)
+ .subst_iter_copied(self.tcx, alias_ty.substs)
+ {
+ trace!(?pred);
+ pred.visit_with(self)?;
+ }
+
+ ControlFlow::Continue(())
+ }
+ Err(NotUniqueParam::NotParam(arg)) => {
+ let err = 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 {
+ 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() {
+ 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.
+ return self
+ .tcx
+ .type_of(assoc.def_id)
+ .subst(self.tcx, &substs)
+ .visit_with(self);
+ }
+ }
+ }
+ }
+ t.super_visit_with(self)
+ }
+ _ => t.super_visit_with(self),
+ }
+ }
+}
+
+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.
+ 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!(),
+ };
+ tcx.arena.alloc_from_iter(defined_opaques)
+ }
+ DefKind::Mod
+ | DefKind::Struct
+ | DefKind::Union
+ | 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 => &[],
+ }
+}
+
+pub(super) fn provide(providers: &mut Providers) {
+ *providers = Providers { opaque_types_defined_by, ..*providers };
+}
diff --git a/compiler/rustc_ty_utils/src/representability.rs b/compiler/rustc_ty_utils/src/representability.rs
index 26d6deab8..0b5e27c2c 100644
--- a/compiler/rustc_ty_utils/src/representability.rs
+++ b/compiler/rustc_ty_utils/src/representability.rs
@@ -2,7 +2,7 @@
use rustc_hir::def::DefKind;
use rustc_index::bit_set::BitSet;
-use rustc_middle::ty::query::Providers;
+use rustc_middle::query::Providers;
use rustc_middle::ty::{self, Representability, Ty, TyCtxt};
use rustc_span::def_id::LocalDefId;
diff --git a/compiler/rustc_ty_utils/src/structural_match.rs b/compiler/rustc_ty_utils/src/structural_match.rs
index a55bb7e7e..215acbe2c 100644
--- a/compiler/rustc_ty_utils/src/structural_match.rs
+++ b/compiler/rustc_ty_utils/src/structural_match.rs
@@ -1,5 +1,5 @@
use rustc_hir::lang_items::LangItem;
-use rustc_middle::ty::query::Providers;
+use rustc_middle::query::Providers;
use rustc_middle::ty::{self, Ty, TyCtxt};
use rustc_infer::infer::TyCtxtInferExt;
@@ -13,7 +13,7 @@ use rustc_trait_selection::traits::{ObligationCause, ObligationCtxt};
/// Note that this does *not* recursively check if the substructure of `adt_ty`
/// implements the traits.
fn has_structural_eq_impls<'tcx>(tcx: TyCtxt<'tcx>, adt_ty: Ty<'tcx>) -> bool {
- let ref infcx = tcx.infer_ctxt().build();
+ let infcx = &tcx.infer_ctxt().build();
let cause = ObligationCause::dummy();
let ocx = ObligationCtxt::new(infcx);
diff --git a/compiler/rustc_ty_utils/src/ty.rs b/compiler/rustc_ty_utils/src/ty.rs
index cb06c7acf..65dc3c39c 100644
--- a/compiler/rustc_ty_utils/src/ty.rs
+++ b/compiler/rustc_ty_utils/src/ty.rs
@@ -2,6 +2,7 @@ use rustc_data_structures::fx::{FxHashSet, FxIndexSet};
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,
@@ -62,9 +63,8 @@ fn sized_constraint_for_ty<'tcx>(
// it on the impl.
let Some(sized_trait) = tcx.lang_items().sized_trait() else { return vec![ty] };
- let sized_predicate = ty::Binder::dummy(tcx.mk_trait_ref(sized_trait, [ty]))
- .without_const()
- .to_predicate(tcx);
+ let sized_predicate =
+ ty::TraitRef::new(tcx, sized_trait, [ty]).without_const().to_predicate(tcx);
let predicates = tcx.predicates_of(adtdef.did()).predicates;
if predicates.iter().any(|(p, _)| *p == sized_predicate) { vec![] } else { vec![ty] }
}
@@ -567,8 +567,8 @@ fn unsizing_params_for_adt<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> BitSet<u32
unsizing_params
}
-pub fn provide(providers: &mut ty::query::Providers) {
- *providers = ty::query::Providers {
+pub fn provide(providers: &mut Providers) {
+ *providers = Providers {
asyncness,
adt_sized_constraint,
param_env,