1
Fork 0

Add AliasKind::Weak for type aliases.

Only use it when the type alias contains an opaque type.

Also does wf-checking on such type aliases.
This commit is contained in:
Oli Scherer 2023-03-07 12:03:11 +00:00
parent 4fdd07fe88
commit f3b7dd6388
86 changed files with 474 additions and 199 deletions

View file

@ -1458,7 +1458,19 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
item_segment: &hir::PathSegment<'_>,
) -> Ty<'tcx> {
let substs = self.ast_path_substs_for_ty(span, did, item_segment);
self.tcx().at(span).type_of(did).subst(self.tcx(), substs)
let ty = self.tcx().at(span).type_of(did);
if matches!(self.tcx().def_kind(did), DefKind::TyAlias)
&& ty.skip_binder().has_opaque_types()
{
// Type aliases referring to types that contain opaque types (but aren't just directly
// referencing a single opaque type) get encoded as a type alias that normalization will
// then actually instantiate the where bounds of.
let alias_ty = self.tcx().mk_alias_ty(did, substs);
self.tcx().mk_alias(ty::Weak, alias_ty)
} else {
ty.subst(self.tcx(), substs)
}
}
fn conv_object_ty_poly_trait_ref(

View file

@ -217,10 +217,10 @@ fn check_item<'tcx>(tcx: TyCtxt<'tcx>, item: &'tcx hir::Item<'tcx>) {
check_item_fn(tcx, def_id, item.ident, item.span, sig.decl);
}
hir::ItemKind::Static(ty, ..) => {
check_item_type(tcx, def_id, ty.span, false);
check_item_type(tcx, def_id, ty.span, UnsizedHandling::Forbid);
}
hir::ItemKind::Const(ty, ..) => {
check_item_type(tcx, def_id, ty.span, false);
check_item_type(tcx, def_id, ty.span, UnsizedHandling::Forbid);
}
hir::ItemKind::Struct(_, ast_generics) => {
check_type_defn(tcx, item, false);
@ -242,6 +242,12 @@ fn check_item<'tcx>(tcx: TyCtxt<'tcx>, item: &'tcx hir::Item<'tcx>) {
}
// `ForeignItem`s are handled separately.
hir::ItemKind::ForeignMod { .. } => {}
hir::ItemKind::TyAlias(hir_ty, ..) => {
if tcx.type_of(item.owner_id.def_id).skip_binder().has_opaque_types() {
// Bounds are respected for `type X = impl Trait` and `type X = (impl Trait, Y);`
check_item_type(tcx, def_id, hir_ty.span, UnsizedHandling::Allow);
}
}
_ => {}
}
}
@ -258,7 +264,9 @@ fn check_foreign_item(tcx: TyCtxt<'_>, item: &hir::ForeignItem<'_>) {
hir::ForeignItemKind::Fn(decl, ..) => {
check_item_fn(tcx, def_id, item.ident, item.span, decl)
}
hir::ForeignItemKind::Static(ty, ..) => check_item_type(tcx, def_id, ty.span, true),
hir::ForeignItemKind::Static(ty, ..) => {
check_item_type(tcx, def_id, ty.span, UnsizedHandling::AllowIfForeignTail)
}
hir::ForeignItemKind::Type => (),
}
}
@ -1100,20 +1108,32 @@ fn check_item_fn(
})
}
fn check_item_type(tcx: TyCtxt<'_>, item_id: LocalDefId, ty_span: Span, allow_foreign_ty: bool) {
enum UnsizedHandling {
Forbid,
Allow,
AllowIfForeignTail,
}
fn check_item_type(
tcx: TyCtxt<'_>,
item_id: LocalDefId,
ty_span: Span,
unsized_handling: UnsizedHandling,
) {
debug!("check_item_type: {:?}", item_id);
enter_wf_checking_ctxt(tcx, ty_span, item_id, |wfcx| {
let ty = tcx.type_of(item_id).subst_identity();
let item_ty = wfcx.normalize(ty_span, Some(WellFormedLoc::Ty(item_id)), ty);
let mut forbid_unsized = true;
if allow_foreign_ty {
let tail = tcx.struct_tail_erasing_lifetimes(item_ty, wfcx.param_env);
if let ty::Foreign(_) = tail.kind() {
forbid_unsized = false;
let forbid_unsized = match unsized_handling {
UnsizedHandling::Forbid => true,
UnsizedHandling::Allow => false,
UnsizedHandling::AllowIfForeignTail => {
let tail = tcx.struct_tail_erasing_lifetimes(item_ty, wfcx.param_env);
!matches!(tail.kind(), ty::Foreign(_))
}
}
};
wfcx.register_wf_obligation(ty_span, Some(WellFormedLoc::Ty(item_id)), item_ty.into());
if forbid_unsized {

View file

@ -208,6 +208,9 @@ fn do_orphan_check_impl<'tcx>(
// }
// impl<T: ?Sized> AutoTrait for <T as Id>::This {}
AliasKind::Projection => "associated type",
// type Foo = (impl Sized, bool)
// impl AutoTrait for Foo {}
AliasKind::Weak => "type alias",
// type Opaque = impl Trait;
// impl AutoTrait for Opaque {}
AliasKind::Opaque => "opaque type",

View file

@ -122,6 +122,7 @@ pub(super) fn explicit_item_bounds(
};
opaque_type_bounds(tcx, def_id, bounds, item_ty, *span)
}
hir::Node::Item(hir::Item { kind: hir::ItemKind::TyAlias(..), .. }) => &[],
_ => bug!("item_bounds called on {:?}", def_id),
};
ty::EarlyBinder::bind(bounds)

View file

@ -128,7 +128,9 @@ fn diagnostic_hir_wf_check<'tcx>(
ref item => bug!("Unexpected TraitItem {:?}", item),
},
hir::Node::Item(item) => match item.kind {
hir::ItemKind::Static(ty, _, _) | hir::ItemKind::Const(ty, _) => vec![ty],
hir::ItemKind::TyAlias(ty, _)
| hir::ItemKind::Static(ty, _, _)
| hir::ItemKind::Const(ty, _) => vec![ty],
hir::ItemKind::Impl(impl_) => match &impl_.of_trait {
Some(t) => t
.path