Skip to content

Commit f08b517

Browse files
committed
Require impl Trait in associated types to appear in method signatures
1 parent 699a862 commit f08b517

File tree

20 files changed

+242
-53
lines changed

20 files changed

+242
-53
lines changed

compiler/rustc_ast_lowering/src/item.rs

+8-2
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

+20-16
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

+2-2
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

+4-1
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

+10-3
Original file line numberDiff line numberDiff line change
@@ -397,7 +397,14 @@ 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 { .. } => {
401+
let mut def_id = def_id;
402+
// Find the surrounding item (type alias or assoc type)
403+
while let DefKind::OpaqueTy = tcx.def_kind(def_id) {
404+
def_id = tcx.local_parent(def_id);
405+
}
406+
def_id
407+
}
401408
};
402409
let param_env = tcx.param_env(defining_use_anchor);
403410

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

compiler/rustc_hir_analysis/src/collect.rs

+1-1
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

+4-1
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

+1-1
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)

compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -526,7 +526,8 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> {
526526
});
527527
}
528528
hir::ItemKind::OpaqueTy(hir::OpaqueTy {
529-
origin: hir::OpaqueTyOrigin::TyAlias, ..
529+
origin: hir::OpaqueTyOrigin::TyAlias { .. },
530+
..
530531
}) => {
531532
// Opaque types are visited when we visit the
532533
// `TyKind::OpaqueDef`, so that they have the lifetimes from
@@ -707,7 +708,7 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> {
707708
let opaque_ty = self.tcx.hir().item(item_id);
708709
match &opaque_ty.kind {
709710
hir::ItemKind::OpaqueTy(hir::OpaqueTy {
710-
origin: hir::OpaqueTyOrigin::TyAlias,
711+
origin: hir::OpaqueTyOrigin::TyAlias { .. },
711712
..
712713
}) => {
713714
intravisit::walk_ty(self, ty);

compiler/rustc_hir_analysis/src/collect/type_of.rs

+4-3
Original file line numberDiff line numberDiff line change
@@ -426,9 +426,10 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<Ty
426426
let substs = InternalSubsts::identity_for_item(tcx, def_id);
427427
tcx.mk_adt(def, substs)
428428
}
429-
ItemKind::OpaqueTy(OpaqueTy { origin: hir::OpaqueTyOrigin::TyAlias, .. }) => {
430-
find_opaque_ty_constraints_for_tait(tcx, def_id)
431-
}
429+
ItemKind::OpaqueTy(OpaqueTy {
430+
origin: hir::OpaqueTyOrigin::TyAlias { .. },
431+
..
432+
}) => find_opaque_ty_constraints_for_tait(tcx, def_id),
432433
// Opaque types desugared from `impl Trait`.
433434
ItemKind::OpaqueTy(OpaqueTy {
434435
origin:

compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -735,7 +735,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
735735
if let ty::subst::GenericArgKind::Type(ty) = ty.unpack()
736736
&& let ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }) = *ty.kind()
737737
&& let Some(def_id) = def_id.as_local()
738-
&& self.opaque_type_origin(def_id).is_some() {
738+
&& self.opaque_type_origin(def_id, self.param_env).is_some() {
739739
return None;
740740
}
741741
}

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

+12-1
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
1+
use crate::infer::opaque_types::may_define_impl_trait_in_assoc_ty_modulo_sig;
2+
13
use super::TypeErrCtxt;
24
use rustc_errors::Applicability::{MachineApplicable, MaybeIncorrect};
35
use rustc_errors::{pluralize, Diagnostic, MultiSpan};
46
use rustc_hir as hir;
5-
use rustc_middle::traits::ObligationCauseCode;
7+
use rustc_middle::traits::ObligationCauseCode::{self, MiscObligation};
68
use rustc_middle::ty::error::ExpectedFound;
79
use rustc_middle::ty::print::Printer;
810
use rustc_middle::{
@@ -256,6 +258,15 @@ impl<T> Trait<T> for X {
256258
);
257259
}
258260
}
261+
(ty::Alias(ty::Opaque, alias), _) | (_, ty::Alias(ty::Opaque, alias)) if matches!(cause.code(), MiscObligation) => {
262+
if let Some(def_id) = alias.def_id.as_local() {
263+
if may_define_impl_trait_in_assoc_ty_modulo_sig(tcx, body_owner_def_id.expect_local(), def_id).is_some() {
264+
diag.span_note(tcx.def_span(body_owner_def_id), "\
265+
this item must have the opaque type in its signature \
266+
in order to be able to register hidden types");
267+
}
268+
}
269+
}
259270
(ty::FnPtr(_), ty::FnDef(def, _))
260271
if let hir::def::DefKind::Fn = tcx.def_kind(def) => {
261272
diag.note(

0 commit comments

Comments
 (0)