diff options
| author | bors <bors@rust-lang.org> | 2023-05-13 05:52:50 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2023-05-13 05:52:50 +0000 |
| commit | 69fef92ab2f287f072b66fb7b4f62c8bb4acba43 (patch) | |
| tree | 9c35e104a85958c2e5779572d67da3406f61a5b2 /compiler/rustc_ty_utils/src | |
| parent | 16d3e18281fde75eb6c62ebb8363af28de8a3ef0 (diff) | |
| parent | 1533eafa15942f9e66a28a19baa492b2ce6126c4 (diff) | |
| download | rust-69fef92ab2f287f072b66fb7b4f62c8bb4acba43.tar.gz rust-69fef92ab2f287f072b66fb7b4f62c8bb4acba43.zip | |
Auto merge of #111526 - Dylan-DPC:rollup-h75agro, r=Dylan-DPC
Rollup of 6 pull requests Successful merges: - #110454 (Require impl Trait in associated types to appear in method signatures) - #111096 (Add support for `cfg(overflow_checks)`) - #111451 (Note user-facing types of coercion failure) - #111469 (Fix data race in llvm source code coverage) - #111494 (Encode `VariantIdx` so we can decode ADT variants in the right order) - #111499 (asm: loongarch64: Drop efiapi) Failed merges: r? `@ghost` `@rustbot` modify labels: rollup
Diffstat (limited to 'compiler/rustc_ty_utils/src')
| -rw-r--r-- | compiler/rustc_ty_utils/src/errors.rs | 24 | ||||
| -rw-r--r-- | compiler/rustc_ty_utils/src/lib.rs | 2 | ||||
| -rw-r--r-- | compiler/rustc_ty_utils/src/opaque_types.rs | 197 |
3 files changed, 222 insertions, 1 deletions
diff --git a/compiler/rustc_ty_utils/src/errors.rs b/compiler/rustc_ty_utils/src/errors.rs index 3d3fc50e6e5..553bf40ef3a 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/lib.rs b/compiler/rustc_ty_utils/src/lib.rs index 73a2f6af579..8306c5ae493 100644 --- a/compiler/rustc_ty_utils/src/lib.rs +++ b/compiler/rustc_ty_utils/src/lib.rs @@ -33,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; @@ -47,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/opaque_types.rs b/compiler/rustc_ty_utils/src/opaque_types.rs new file mode 100644 index 00000000000..25ebb333bf7 --- /dev/null +++ b/compiler/rustc_ty_utils/src/opaque_types.rs @@ -0,0 +1,197 @@ +use rustc_data_structures::fx::FxHashSet; +use rustc_errors::ErrorGuaranteed; +use rustc_hir::{def::DefKind, def_id::LocalDefId}; +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 ty::query::Providers) { + *providers = ty::query::Providers { opaque_types_defined_by, ..*providers }; +} |
