Skip to content

Commit 9a5936b

Browse files
Validate opaques in default trait bodies, don't normalize unless a body is provided
1 parent 86734b0 commit 9a5936b

File tree

3 files changed

+36
-25
lines changed

3 files changed

+36
-25
lines changed

Diff for: compiler/rustc_hir_analysis/src/check/check.rs

+33-23
Original file line numberDiff line numberDiff line change
@@ -525,23 +525,33 @@ fn check_static_inhabited<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) {
525525

526526
/// Checks that an opaque type does not contain cycles and does not use `Self` or `T::Foo`
527527
/// projections that would result in "inheriting lifetimes".
528-
pub(super) fn check_opaque<'tcx>(
529-
tcx: TyCtxt<'tcx>,
530-
def_id: LocalDefId,
531-
substs: SubstsRef<'tcx>,
532-
origin: &hir::OpaqueTyOrigin,
533-
) {
534-
let span = tcx.def_span(def_id);
535-
check_opaque_for_inheriting_lifetimes(tcx, def_id, span);
536-
if tcx.type_of(def_id).references_error() {
528+
fn check_opaque<'tcx>(tcx: TyCtxt<'tcx>, id: hir::ItemId) {
529+
let item = tcx.hir().item(id);
530+
let hir::ItemKind::OpaqueTy(hir::OpaqueTy { origin, .. }) = item.kind else {
531+
tcx.sess.delay_span_bug(tcx.hir().span(id.hir_id()), "expected opaque item");
532+
return;
533+
};
534+
535+
// HACK(jynelson): trying to infer the type of `impl trait` breaks documenting
536+
// `async-std` (and `pub async fn` in general).
537+
// Since rustdoc doesn't care about the concrete type behind `impl Trait`, just don't look at it!
538+
// See https://github.com/rust-lang/rust/issues/75100
539+
if tcx.sess.opts.actually_rustdoc {
537540
return;
538541
}
539-
if check_opaque_for_cycles(tcx, def_id, substs, span, origin).is_err() {
542+
543+
let substs = InternalSubsts::identity_for_item(tcx, item.def_id.to_def_id());
544+
let span = tcx.def_span(item.def_id.def_id);
545+
546+
check_opaque_for_inheriting_lifetimes(tcx, item.def_id.def_id, span);
547+
if tcx.type_of(item.def_id.def_id).references_error() {
548+
return;
549+
}
550+
if check_opaque_for_cycles(tcx, item.def_id.def_id, substs, span, &origin).is_err() {
540551
return;
541552
}
542-
check_opaque_meets_bounds(tcx, def_id, substs, span, origin);
553+
check_opaque_meets_bounds(tcx, item.def_id.def_id, substs, span, &origin);
543554
}
544-
545555
/// Checks that an opaque type does not use `Self` or `T::Foo` projections that would result
546556
/// in "inheriting lifetimes".
547557
#[instrument(level = "debug", skip(tcx, span))]
@@ -858,17 +868,17 @@ fn check_item_type<'tcx>(tcx: TyCtxt<'tcx>, id: hir::ItemId) {
858868
check_union(tcx, id.def_id.def_id);
859869
}
860870
DefKind::OpaqueTy => {
861-
let item = tcx.hir().item(id);
862-
let hir::ItemKind::OpaqueTy(hir::OpaqueTy { origin, .. }) = item.kind else {
863-
return;
864-
};
865-
// HACK(jynelson): trying to infer the type of `impl trait` breaks documenting
866-
// `async-std` (and `pub async fn` in general).
867-
// Since rustdoc doesn't care about the concrete type behind `impl Trait`, just don't look at it!
868-
// See https://github.com/rust-lang/rust/issues/75100
869-
if !tcx.sess.opts.actually_rustdoc {
870-
let substs = InternalSubsts::identity_for_item(tcx, item.def_id.to_def_id());
871-
check_opaque(tcx, item.def_id.def_id, substs, &origin);
871+
check_opaque(tcx, id);
872+
}
873+
DefKind::ImplTraitPlaceholder => {
874+
let parent = tcx.impl_trait_in_trait_parent(id.def_id.to_def_id());
875+
// Only check the validity of this opaque type if the function has a default body
876+
if let hir::Node::TraitItem(hir::TraitItem {
877+
kind: hir::TraitItemKind::Fn(_, hir::TraitFn::Provided(_)),
878+
..
879+
}) = tcx.hir().get_by_def_id(parent.expect_local())
880+
{
881+
check_opaque(tcx, id);
872882
}
873883
}
874884
DefKind::TyAlias => {

Diff for: compiler/rustc_middle/src/ty/sty.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1160,8 +1160,8 @@ impl<'tcx> ProjectionTy<'tcx> {
11601160
&self,
11611161
tcx: TyCtxt<'tcx>,
11621162
) -> (ty::TraitRef<'tcx>, &'tcx [ty::GenericArg<'tcx>]) {
1163-
assert_eq!(tcx.def_kind(def_id), DefKind::Trait);
11641163
let def_id = tcx.parent(self.item_def_id);
1164+
assert_eq!(tcx.def_kind(def_id), DefKind::Trait);
11651165
let trait_generics = tcx.generics_of(def_id);
11661166
(
11671167
ty::TraitRef { def_id, substs: self.substs.truncate_to(tcx, trait_generics) },

Diff for: compiler/rustc_trait_selection/src/traits/project.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -1325,19 +1325,20 @@ fn assemble_candidate_for_impl_trait_in_trait<'cx, 'tcx>(
13251325
) {
13261326
let tcx = selcx.tcx();
13271327
if tcx.def_kind(obligation.predicate.item_def_id) == DefKind::ImplTraitPlaceholder {
1328+
let trait_fn_def_id = tcx.impl_trait_in_trait_parent(obligation.predicate.item_def_id);
13281329
// If we are trying to project an RPITIT with trait's default `Self` parameter,
13291330
// then we must be within a default trait body.
13301331
if obligation.predicate.self_ty()
13311332
== ty::InternalSubsts::identity_for_item(tcx, obligation.predicate.item_def_id)
13321333
.type_at(0)
1334+
&& tcx.associated_item(trait_fn_def_id).defaultness(tcx).has_value()
13331335
{
13341336
candidate_set.push_candidate(ProjectionCandidate::ImplTraitInTrait(
13351337
ImplTraitInTraitCandidate::Trait,
13361338
));
13371339
return;
13381340
}
13391341

1340-
let trait_fn_def_id = tcx.impl_trait_in_trait_parent(obligation.predicate.item_def_id);
13411342
let trait_def_id = tcx.parent(trait_fn_def_id);
13421343
let trait_substs =
13431344
obligation.predicate.substs.truncate_to(tcx, tcx.generics_of(trait_def_id));

0 commit comments

Comments
 (0)