Skip to content

Commit f3b7dd6

Browse files
committed
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.
1 parent 4fdd07f commit f3b7dd6

File tree

86 files changed

+474
-199
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

86 files changed

+474
-199
lines changed

compiler/rustc_const_eval/src/util/type_name.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ impl<'tcx> Printer<'tcx> for AbsolutePathPrinter<'tcx> {
6363
| ty::Generator(def_id, substs, _) => self.print_def_path(def_id, substs),
6464
ty::Foreign(def_id) => self.print_def_path(def_id, &[]),
6565

66+
ty::Alias(ty::Weak, _) => bug!("type_name: unexpected weak projection"),
6667
ty::Alias(ty::Inherent, _) => bug!("type_name: unexpected inherent projection"),
6768
ty::GeneratorWitness(_) => bug!("type_name: unexpected `GeneratorWitness`"),
6869
ty::GeneratorWitnessMIR(..) => bug!("type_name: unexpected `GeneratorWitnessMIR`"),

compiler/rustc_hir_analysis/src/astconv/mod.rs

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1458,7 +1458,19 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
14581458
item_segment: &hir::PathSegment<'_>,
14591459
) -> Ty<'tcx> {
14601460
let substs = self.ast_path_substs_for_ty(span, did, item_segment);
1461-
self.tcx().at(span).type_of(did).subst(self.tcx(), substs)
1461+
let ty = self.tcx().at(span).type_of(did);
1462+
1463+
if matches!(self.tcx().def_kind(did), DefKind::TyAlias)
1464+
&& ty.skip_binder().has_opaque_types()
1465+
{
1466+
// Type aliases referring to types that contain opaque types (but aren't just directly
1467+
// referencing a single opaque type) get encoded as a type alias that normalization will
1468+
// then actually instantiate the where bounds of.
1469+
let alias_ty = self.tcx().mk_alias_ty(did, substs);
1470+
self.tcx().mk_alias(ty::Weak, alias_ty)
1471+
} else {
1472+
ty.subst(self.tcx(), substs)
1473+
}
14621474
}
14631475

14641476
fn conv_object_ty_poly_trait_ref(

compiler/rustc_hir_analysis/src/check/wfcheck.rs

Lines changed: 30 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -217,10 +217,10 @@ fn check_item<'tcx>(tcx: TyCtxt<'tcx>, item: &'tcx hir::Item<'tcx>) {
217217
check_item_fn(tcx, def_id, item.ident, item.span, sig.decl);
218218
}
219219
hir::ItemKind::Static(ty, ..) => {
220-
check_item_type(tcx, def_id, ty.span, false);
220+
check_item_type(tcx, def_id, ty.span, UnsizedHandling::Forbid);
221221
}
222222
hir::ItemKind::Const(ty, ..) => {
223-
check_item_type(tcx, def_id, ty.span, false);
223+
check_item_type(tcx, def_id, ty.span, UnsizedHandling::Forbid);
224224
}
225225
hir::ItemKind::Struct(_, ast_generics) => {
226226
check_type_defn(tcx, item, false);
@@ -242,6 +242,12 @@ fn check_item<'tcx>(tcx: TyCtxt<'tcx>, item: &'tcx hir::Item<'tcx>) {
242242
}
243243
// `ForeignItem`s are handled separately.
244244
hir::ItemKind::ForeignMod { .. } => {}
245+
hir::ItemKind::TyAlias(hir_ty, ..) => {
246+
if tcx.type_of(item.owner_id.def_id).skip_binder().has_opaque_types() {
247+
// Bounds are respected for `type X = impl Trait` and `type X = (impl Trait, Y);`
248+
check_item_type(tcx, def_id, hir_ty.span, UnsizedHandling::Allow);
249+
}
250+
}
245251
_ => {}
246252
}
247253
}
@@ -258,7 +264,9 @@ fn check_foreign_item(tcx: TyCtxt<'_>, item: &hir::ForeignItem<'_>) {
258264
hir::ForeignItemKind::Fn(decl, ..) => {
259265
check_item_fn(tcx, def_id, item.ident, item.span, decl)
260266
}
261-
hir::ForeignItemKind::Static(ty, ..) => check_item_type(tcx, def_id, ty.span, true),
267+
hir::ForeignItemKind::Static(ty, ..) => {
268+
check_item_type(tcx, def_id, ty.span, UnsizedHandling::AllowIfForeignTail)
269+
}
262270
hir::ForeignItemKind::Type => (),
263271
}
264272
}
@@ -1100,20 +1108,32 @@ fn check_item_fn(
11001108
})
11011109
}
11021110

1103-
fn check_item_type(tcx: TyCtxt<'_>, item_id: LocalDefId, ty_span: Span, allow_foreign_ty: bool) {
1111+
enum UnsizedHandling {
1112+
Forbid,
1113+
Allow,
1114+
AllowIfForeignTail,
1115+
}
1116+
1117+
fn check_item_type(
1118+
tcx: TyCtxt<'_>,
1119+
item_id: LocalDefId,
1120+
ty_span: Span,
1121+
unsized_handling: UnsizedHandling,
1122+
) {
11041123
debug!("check_item_type: {:?}", item_id);
11051124

11061125
enter_wf_checking_ctxt(tcx, ty_span, item_id, |wfcx| {
11071126
let ty = tcx.type_of(item_id).subst_identity();
11081127
let item_ty = wfcx.normalize(ty_span, Some(WellFormedLoc::Ty(item_id)), ty);
11091128

1110-
let mut forbid_unsized = true;
1111-
if allow_foreign_ty {
1112-
let tail = tcx.struct_tail_erasing_lifetimes(item_ty, wfcx.param_env);
1113-
if let ty::Foreign(_) = tail.kind() {
1114-
forbid_unsized = false;
1129+
let forbid_unsized = match unsized_handling {
1130+
UnsizedHandling::Forbid => true,
1131+
UnsizedHandling::Allow => false,
1132+
UnsizedHandling::AllowIfForeignTail => {
1133+
let tail = tcx.struct_tail_erasing_lifetimes(item_ty, wfcx.param_env);
1134+
!matches!(tail.kind(), ty::Foreign(_))
11151135
}
1116-
}
1136+
};
11171137

11181138
wfcx.register_wf_obligation(ty_span, Some(WellFormedLoc::Ty(item_id)), item_ty.into());
11191139
if forbid_unsized {

compiler/rustc_hir_analysis/src/coherence/orphan.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,9 @@ fn do_orphan_check_impl<'tcx>(
208208
// }
209209
// impl<T: ?Sized> AutoTrait for <T as Id>::This {}
210210
AliasKind::Projection => "associated type",
211+
// type Foo = (impl Sized, bool)
212+
// impl AutoTrait for Foo {}
213+
AliasKind::Weak => "type alias",
211214
// type Opaque = impl Trait;
212215
// impl AutoTrait for Opaque {}
213216
AliasKind::Opaque => "opaque type",

compiler/rustc_hir_analysis/src/collect/item_bounds.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,7 @@ pub(super) fn explicit_item_bounds(
122122
};
123123
opaque_type_bounds(tcx, def_id, bounds, item_ty, *span)
124124
}
125+
hir::Node::Item(hir::Item { kind: hir::ItemKind::TyAlias(..), .. }) => &[],
125126
_ => bug!("item_bounds called on {:?}", def_id),
126127
};
127128
ty::EarlyBinder::bind(bounds)

compiler/rustc_hir_analysis/src/hir_wf_check.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,9 @@ fn diagnostic_hir_wf_check<'tcx>(
128128
ref item => bug!("Unexpected TraitItem {:?}", item),
129129
},
130130
hir::Node::Item(item) => match item.kind {
131-
hir::ItemKind::Static(ty, _, _) | hir::ItemKind::Const(ty, _) => vec![ty],
131+
hir::ItemKind::TyAlias(ty, _)
132+
| hir::ItemKind::Static(ty, _, _)
133+
| hir::ItemKind::Const(ty, _) => vec![ty],
132134
hir::ItemKind::Impl(impl_) => match &impl_.of_trait {
133135
Some(t) => t
134136
.path

compiler/rustc_infer/src/infer/error_reporting/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2375,6 +2375,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
23752375
ty::AliasKind::Projection | ty::AliasKind::Inherent => {
23762376
format!("the associated type `{}`", p)
23772377
}
2378+
ty::AliasKind::Weak => format!("the type alias `{}`", p),
23782379
ty::AliasKind::Opaque => format!("the opaque type `{}`", p),
23792380
},
23802381
};

compiler/rustc_lint/src/builtin.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1465,8 +1465,8 @@ impl<'tcx> LateLintPass<'tcx> for TypeAliasBounds {
14651465
let hir::ItemKind::TyAlias(ty, type_alias_generics) = &item.kind else {
14661466
return
14671467
};
1468-
if let hir::TyKind::OpaqueDef(..) = ty.kind {
1469-
// Bounds are respected for `type X = impl Trait`
1468+
if cx.tcx.type_of(item.owner_id.def_id).skip_binder().has_opaque_types() {
1469+
// Bounds are respected for `type X = impl Trait` and `type X = (impl Trait, Y);`
14701470
return;
14711471
}
14721472
if cx.tcx.type_of(item.owner_id).skip_binder().has_inherent_projections() {

compiler/rustc_lint/src/types.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1255,7 +1255,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
12551255
}
12561256

12571257
ty::Param(..)
1258-
| ty::Alias(ty::Projection | ty::Inherent, ..)
1258+
| ty::Alias(ty::Projection | ty::Inherent | ty::Weak, ..)
12591259
| ty::Infer(..)
12601260
| ty::Bound(..)
12611261
| ty::Error(_)

compiler/rustc_middle/src/query/mod.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1903,6 +1903,16 @@ rustc_queries! {
19031903
desc { "normalizing `{}`", goal.value.value }
19041904
}
19051905

1906+
/// Do not call this query directly: invoke `normalize` instead.
1907+
query normalize_weak_ty(
1908+
goal: CanonicalProjectionGoal<'tcx>
1909+
) -> Result<
1910+
&'tcx Canonical<'tcx, canonical::QueryResponse<'tcx, NormalizationResult<'tcx>>>,
1911+
NoSolution,
1912+
> {
1913+
desc { "normalizing `{}`", goal.value.value }
1914+
}
1915+
19061916
/// Do not call this query directly: invoke `normalize` instead.
19071917
query normalize_inherent_projection_ty(
19081918
goal: CanonicalProjectionGoal<'tcx>

0 commit comments

Comments
 (0)