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:
parent
4fdd07fe88
commit
f3b7dd6388
86 changed files with 474 additions and 199 deletions
|
@ -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(
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue