Skip to content

Commit 6cb1358

Browse files
authored
Rollup merge of #110454 - oli-obk:limited_impl_trait_in_assoc_type, r=compiler-errors
Require impl Trait in associated types to appear in method signatures This implements the limited version of TAIT that was proposed in #107645 (comment) Similar to `impl Trait` in return types, `impl Trait` in associated types may only be used within the impl block which it is a part of. To make everything simpler and forward compatible to getting desugared to a plain type alias impl trait in the future, we're requiring that any associated functions or constants that want to register hidden types must be using the associated type in their signature (type of the constant or argument/return type of the associated method. Where bounds mentioning the associated type are ignored). We have preexisting tests checking that this works transitively across multiple associated types in situations like ```rust impl Foo for Bar { type A = impl Trait; type B = impl Iterator<Item = Self::A>; fn foo() -> Self::B { ...... } } ```
2 parents 9850584 + 4e92f76 commit 6cb1358

36 files changed

+560
-68
lines changed

compiler/rustc_ast_lowering/src/item.rs

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -305,7 +305,10 @@ impl<'hir> LoweringContext<'_, 'hir> {
305305
);
306306
this.arena.alloc(this.ty(span, hir::TyKind::Err(guar)))
307307
}
308-
Some(ty) => this.lower_ty(ty, &ImplTraitContext::TypeAliasesOpaqueTy),
308+
Some(ty) => this.lower_ty(
309+
ty,
310+
&ImplTraitContext::TypeAliasesOpaqueTy { in_assoc_ty: false },
311+
),
309312
},
310313
);
311314
hir::ItemKind::TyAlias(ty, generics)
@@ -852,7 +855,10 @@ impl<'hir> LoweringContext<'_, 'hir> {
852855
hir::ImplItemKind::Type(ty)
853856
}
854857
Some(ty) => {
855-
let ty = this.lower_ty(ty, &ImplTraitContext::TypeAliasesOpaqueTy);
858+
let ty = this.lower_ty(
859+
ty,
860+
&ImplTraitContext::TypeAliasesOpaqueTy { in_assoc_ty: true },
861+
);
856862
hir::ImplItemKind::Type(ty)
857863
}
858864
},

compiler/rustc_ast_lowering/src/lib.rs

Lines changed: 20 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -247,7 +247,7 @@ enum ImplTraitContext {
247247
in_trait: bool,
248248
},
249249
/// Impl trait in type aliases.
250-
TypeAliasesOpaqueTy,
250+
TypeAliasesOpaqueTy { in_assoc_ty: bool },
251251
/// `impl Trait` is unstably accepted in this position.
252252
FeatureGated(ImplTraitPosition, Symbol),
253253
/// `impl Trait` is not accepted in this position.
@@ -1407,14 +1407,15 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
14071407
*in_trait,
14081408
itctx,
14091409
),
1410-
ImplTraitContext::TypeAliasesOpaqueTy => self.lower_opaque_impl_trait(
1411-
span,
1412-
hir::OpaqueTyOrigin::TyAlias,
1413-
*def_node_id,
1414-
bounds,
1415-
false,
1416-
itctx,
1417-
),
1410+
&ImplTraitContext::TypeAliasesOpaqueTy { in_assoc_ty } => self
1411+
.lower_opaque_impl_trait(
1412+
span,
1413+
hir::OpaqueTyOrigin::TyAlias { in_assoc_ty },
1414+
*def_node_id,
1415+
bounds,
1416+
false,
1417+
itctx,
1418+
),
14181419
ImplTraitContext::Universal => {
14191420
let span = t.span;
14201421
self.create_def(
@@ -1534,13 +1535,16 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
15341535
// If this came from a TAIT (as opposed to a function that returns an RPIT), we only want
15351536
// to capture the lifetimes that appear in the bounds. So visit the bounds to find out
15361537
// exactly which ones those are.
1537-
let lifetimes_to_remap = if origin == hir::OpaqueTyOrigin::TyAlias {
1538-
// in a TAIT like `type Foo<'a> = impl Foo<'a>`, we don't keep all the lifetime parameters
1539-
Vec::new()
1540-
} else {
1541-
// in fn return position, like the `fn test<'a>() -> impl Debug + 'a` example,
1542-
// we only keep the lifetimes that appear in the `impl Debug` itself:
1543-
lifetime_collector::lifetimes_in_bounds(&self.resolver, bounds)
1538+
let lifetimes_to_remap = match origin {
1539+
hir::OpaqueTyOrigin::TyAlias { .. } => {
1540+
// in a TAIT like `type Foo<'a> = impl Foo<'a>`, we don't keep all the lifetime parameters
1541+
Vec::new()
1542+
}
1543+
hir::OpaqueTyOrigin::AsyncFn(..) | hir::OpaqueTyOrigin::FnReturn(..) => {
1544+
// in fn return position, like the `fn test<'a>() -> impl Debug + 'a` example,
1545+
// we only keep the lifetimes that appear in the `impl Debug` itself:
1546+
lifetime_collector::lifetimes_in_bounds(&self.resolver, bounds)
1547+
}
15441548
};
15451549
debug!(?lifetimes_to_remap);
15461550

compiler/rustc_borrowck/src/region_infer/opaque_types.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -265,7 +265,7 @@ impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> {
265265

266266
// Only check this for TAIT. RPIT already supports `tests/ui/impl-trait/nested-return-type2.rs`
267267
// on stable and we'd break that.
268-
let OpaqueTyOrigin::TyAlias = origin else {
268+
let OpaqueTyOrigin::TyAlias { .. } = origin else {
269269
return definition_ty;
270270
};
271271
let def_id = opaque_type_key.def_id;
@@ -360,7 +360,7 @@ fn check_opaque_type_parameter_valid(
360360
// which would error here on all of the `'static` args.
361361
OpaqueTyOrigin::FnReturn(..) | OpaqueTyOrigin::AsyncFn(..) => return Ok(()),
362362
// Check these
363-
OpaqueTyOrigin::TyAlias => {}
363+
OpaqueTyOrigin::TyAlias { .. } => {}
364364
}
365365
let opaque_generics = tcx.generics_of(opaque_type_key.def_id);
366366
let mut seen_params: FxIndexMap<_, Vec<_>> = FxIndexMap::default();

compiler/rustc_hir/src/hir.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2662,7 +2662,10 @@ pub enum OpaqueTyOrigin {
26622662
/// `async fn`
26632663
AsyncFn(LocalDefId),
26642664
/// type aliases: `type Foo = impl Trait;`
2665-
TyAlias,
2665+
TyAlias {
2666+
/// associated types in impl blocks for traits.
2667+
in_assoc_ty: bool,
2668+
},
26662669
}
26672670

26682671
/// The various kinds of types recognized by the compiler.

compiler/rustc_hir_analysis/src/check/check.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -397,7 +397,7 @@ fn check_opaque_meets_bounds<'tcx>(
397397
) {
398398
let defining_use_anchor = match *origin {
399399
hir::OpaqueTyOrigin::FnReturn(did) | hir::OpaqueTyOrigin::AsyncFn(did) => did,
400-
hir::OpaqueTyOrigin::TyAlias => def_id,
400+
hir::OpaqueTyOrigin::TyAlias { .. } => tcx.impl_trait_parent(def_id),
401401
};
402402
let param_env = tcx.param_env(defining_use_anchor);
403403

@@ -455,10 +455,10 @@ fn check_opaque_meets_bounds<'tcx>(
455455
// They can only be referenced as `<Opaque<T> as Trait<&'static T>>::AssocTy`.
456456
// We don't have to check them here because their well-formedness follows from the WF of
457457
// the projection input types in the defining- and use-sites.
458-
hir::OpaqueTyOrigin::TyAlias
458+
hir::OpaqueTyOrigin::TyAlias { .. }
459459
if tcx.def_kind(tcx.parent(def_id.to_def_id())) == DefKind::OpaqueTy => {}
460460
// Can have different predicates to their defining use
461-
hir::OpaqueTyOrigin::TyAlias => {
461+
hir::OpaqueTyOrigin::TyAlias { .. } => {
462462
let wf_tys = ocx.assumed_wf_types(param_env, span, def_id);
463463
let implied_bounds = infcx.implied_bounds_tys(param_env, def_id, wf_tys);
464464
let outlives_env = OutlivesEnvironment::with_bounds(param_env, implied_bounds);

compiler/rustc_hir_analysis/src/check/dropck.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ use rustc_errors::{struct_span_err, ErrorGuaranteed};
66
use rustc_infer::infer::outlives::env::OutlivesEnvironment;
77
use rustc_infer::infer::{RegionResolutionError, TyCtxtInferExt};
88
use rustc_middle::ty::subst::SubstsRef;
9-
use rustc_middle::ty::util::IgnoreRegions;
9+
use rustc_middle::ty::util::CheckRegions;
1010
use rustc_middle::ty::{self, TyCtxt};
1111
use rustc_trait_selection::traits::{self, ObligationCtxt};
1212

@@ -81,7 +81,7 @@ fn ensure_drop_params_and_item_params_correspond<'tcx>(
8181
self_type_did: DefId,
8282
adt_to_impl_substs: SubstsRef<'tcx>,
8383
) -> Result<(), ErrorGuaranteed> {
84-
let Err(arg) = tcx.uses_unique_generic_params(adt_to_impl_substs, IgnoreRegions::No) else {
84+
let Err(arg) = tcx.uses_unique_generic_params(adt_to_impl_substs, CheckRegions::OnlyEarlyBound) else {
8585
return Ok(())
8686
};
8787

compiler/rustc_hir_analysis/src/coherence/orphan.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ use rustc_errors::{struct_span_err, DelayDm};
66
use rustc_errors::{Diagnostic, ErrorGuaranteed};
77
use rustc_hir as hir;
88
use rustc_middle::ty::subst::InternalSubsts;
9-
use rustc_middle::ty::util::IgnoreRegions;
9+
use rustc_middle::ty::util::CheckRegions;
1010
use rustc_middle::ty::{
1111
self, AliasKind, ImplPolarity, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitableExt,
1212
TypeVisitor,
@@ -507,7 +507,7 @@ fn lint_auto_trait_impl<'tcx>(
507507
// Impls which completely cover a given root type are fine as they
508508
// disable auto impls entirely. So only lint if the substs
509509
// are not a permutation of the identity substs.
510-
let Err(arg) = tcx.uses_unique_generic_params(substs, IgnoreRegions::Yes) else {
510+
let Err(arg) = tcx.uses_unique_generic_params(substs, CheckRegions::No) else {
511511
// ok
512512
return;
513513
};

compiler/rustc_hir_analysis/src/collect.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1483,7 +1483,7 @@ fn generator_kind(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<hir::GeneratorK
14831483
fn is_type_alias_impl_trait<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> bool {
14841484
match tcx.hir().get_by_def_id(def_id) {
14851485
Node::Item(hir::Item { kind: hir::ItemKind::OpaqueTy(opaque), .. }) => {
1486-
matches!(opaque.origin, hir::OpaqueTyOrigin::TyAlias)
1486+
matches!(opaque.origin, hir::OpaqueTyOrigin::TyAlias { .. })
14871487
}
14881488
_ => bug!("tried getting opaque_ty_origin for non-opaque: {:?}", def_id),
14891489
}

compiler/rustc_hir_analysis/src/collect/generics_of.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -159,7 +159,10 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics {
159159
}
160160
Some(fn_def_id.to_def_id())
161161
}
162-
ItemKind::OpaqueTy(hir::OpaqueTy { origin: hir::OpaqueTyOrigin::TyAlias, .. }) => {
162+
ItemKind::OpaqueTy(hir::OpaqueTy {
163+
origin: hir::OpaqueTyOrigin::TyAlias { .. },
164+
..
165+
}) => {
163166
let parent_id = tcx.hir().get_parent_item(hir_id);
164167
assert_ne!(parent_id, hir::CRATE_OWNER_ID);
165168
debug!("generics_of: parent of opaque ty {:?} is {:?}", def_id, parent_id);

compiler/rustc_hir_analysis/src/collect/predicates_of.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -721,7 +721,7 @@ pub(super) fn type_param_predicates(
721721
| ItemKind::TyAlias(_, generics)
722722
| ItemKind::OpaqueTy(OpaqueTy {
723723
generics,
724-
origin: hir::OpaqueTyOrigin::TyAlias,
724+
origin: hir::OpaqueTyOrigin::TyAlias { .. },
725725
..
726726
})
727727
| ItemKind::Enum(_, generics)

0 commit comments

Comments
 (0)