Validate opaques in default trait bodies, don't normalize unless a body is provided
This commit is contained in:
parent
86734b04a7
commit
9a5936b814
3 changed files with 39 additions and 28 deletions
|
@ -525,23 +525,33 @@ fn check_static_inhabited<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) {
|
||||||
|
|
||||||
/// Checks that an opaque type does not contain cycles and does not use `Self` or `T::Foo`
|
/// Checks that an opaque type does not contain cycles and does not use `Self` or `T::Foo`
|
||||||
/// projections that would result in "inheriting lifetimes".
|
/// projections that would result in "inheriting lifetimes".
|
||||||
pub(super) fn check_opaque<'tcx>(
|
fn check_opaque<'tcx>(tcx: TyCtxt<'tcx>, id: hir::ItemId) {
|
||||||
tcx: TyCtxt<'tcx>,
|
let item = tcx.hir().item(id);
|
||||||
def_id: LocalDefId,
|
let hir::ItemKind::OpaqueTy(hir::OpaqueTy { origin, .. }) = item.kind else {
|
||||||
substs: SubstsRef<'tcx>,
|
tcx.sess.delay_span_bug(tcx.hir().span(id.hir_id()), "expected opaque item");
|
||||||
origin: &hir::OpaqueTyOrigin,
|
|
||||||
) {
|
|
||||||
let span = tcx.def_span(def_id);
|
|
||||||
check_opaque_for_inheriting_lifetimes(tcx, def_id, span);
|
|
||||||
if tcx.type_of(def_id).references_error() {
|
|
||||||
return;
|
return;
|
||||||
}
|
};
|
||||||
if check_opaque_for_cycles(tcx, def_id, substs, span, origin).is_err() {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
check_opaque_meets_bounds(tcx, def_id, substs, span, origin);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
// HACK(jynelson): trying to infer the type of `impl trait` breaks documenting
|
||||||
|
// `async-std` (and `pub async fn` in general).
|
||||||
|
// Since rustdoc doesn't care about the concrete type behind `impl Trait`, just don't look at it!
|
||||||
|
// See https://github.com/rust-lang/rust/issues/75100
|
||||||
|
if tcx.sess.opts.actually_rustdoc {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let substs = InternalSubsts::identity_for_item(tcx, item.def_id.to_def_id());
|
||||||
|
let span = tcx.def_span(item.def_id.def_id);
|
||||||
|
|
||||||
|
check_opaque_for_inheriting_lifetimes(tcx, item.def_id.def_id, span);
|
||||||
|
if tcx.type_of(item.def_id.def_id).references_error() {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if check_opaque_for_cycles(tcx, item.def_id.def_id, substs, span, &origin).is_err() {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
check_opaque_meets_bounds(tcx, item.def_id.def_id, substs, span, &origin);
|
||||||
|
}
|
||||||
/// Checks that an opaque type does not use `Self` or `T::Foo` projections that would result
|
/// Checks that an opaque type does not use `Self` or `T::Foo` projections that would result
|
||||||
/// in "inheriting lifetimes".
|
/// in "inheriting lifetimes".
|
||||||
#[instrument(level = "debug", skip(tcx, span))]
|
#[instrument(level = "debug", skip(tcx, span))]
|
||||||
|
@ -858,17 +868,17 @@ fn check_item_type<'tcx>(tcx: TyCtxt<'tcx>, id: hir::ItemId) {
|
||||||
check_union(tcx, id.def_id.def_id);
|
check_union(tcx, id.def_id.def_id);
|
||||||
}
|
}
|
||||||
DefKind::OpaqueTy => {
|
DefKind::OpaqueTy => {
|
||||||
let item = tcx.hir().item(id);
|
check_opaque(tcx, id);
|
||||||
let hir::ItemKind::OpaqueTy(hir::OpaqueTy { origin, .. }) = item.kind else {
|
}
|
||||||
return;
|
DefKind::ImplTraitPlaceholder => {
|
||||||
};
|
let parent = tcx.impl_trait_in_trait_parent(id.def_id.to_def_id());
|
||||||
// HACK(jynelson): trying to infer the type of `impl trait` breaks documenting
|
// Only check the validity of this opaque type if the function has a default body
|
||||||
// `async-std` (and `pub async fn` in general).
|
if let hir::Node::TraitItem(hir::TraitItem {
|
||||||
// Since rustdoc doesn't care about the concrete type behind `impl Trait`, just don't look at it!
|
kind: hir::TraitItemKind::Fn(_, hir::TraitFn::Provided(_)),
|
||||||
// See https://github.com/rust-lang/rust/issues/75100
|
..
|
||||||
if !tcx.sess.opts.actually_rustdoc {
|
}) = tcx.hir().get_by_def_id(parent.expect_local())
|
||||||
let substs = InternalSubsts::identity_for_item(tcx, item.def_id.to_def_id());
|
{
|
||||||
check_opaque(tcx, item.def_id.def_id, substs, &origin);
|
check_opaque(tcx, id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
DefKind::TyAlias => {
|
DefKind::TyAlias => {
|
||||||
|
|
|
@ -1160,8 +1160,8 @@ impl<'tcx> ProjectionTy<'tcx> {
|
||||||
&self,
|
&self,
|
||||||
tcx: TyCtxt<'tcx>,
|
tcx: TyCtxt<'tcx>,
|
||||||
) -> (ty::TraitRef<'tcx>, &'tcx [ty::GenericArg<'tcx>]) {
|
) -> (ty::TraitRef<'tcx>, &'tcx [ty::GenericArg<'tcx>]) {
|
||||||
assert_eq!(tcx.def_kind(def_id), DefKind::Trait);
|
|
||||||
let def_id = tcx.parent(self.item_def_id);
|
let def_id = tcx.parent(self.item_def_id);
|
||||||
|
assert_eq!(tcx.def_kind(def_id), DefKind::Trait);
|
||||||
let trait_generics = tcx.generics_of(def_id);
|
let trait_generics = tcx.generics_of(def_id);
|
||||||
(
|
(
|
||||||
ty::TraitRef { def_id, substs: self.substs.truncate_to(tcx, trait_generics) },
|
ty::TraitRef { def_id, substs: self.substs.truncate_to(tcx, trait_generics) },
|
||||||
|
|
|
@ -1325,11 +1325,13 @@ fn assemble_candidate_for_impl_trait_in_trait<'cx, 'tcx>(
|
||||||
) {
|
) {
|
||||||
let tcx = selcx.tcx();
|
let tcx = selcx.tcx();
|
||||||
if tcx.def_kind(obligation.predicate.item_def_id) == DefKind::ImplTraitPlaceholder {
|
if tcx.def_kind(obligation.predicate.item_def_id) == DefKind::ImplTraitPlaceholder {
|
||||||
|
let trait_fn_def_id = tcx.impl_trait_in_trait_parent(obligation.predicate.item_def_id);
|
||||||
// If we are trying to project an RPITIT with trait's default `Self` parameter,
|
// If we are trying to project an RPITIT with trait's default `Self` parameter,
|
||||||
// then we must be within a default trait body.
|
// then we must be within a default trait body.
|
||||||
if obligation.predicate.self_ty()
|
if obligation.predicate.self_ty()
|
||||||
== ty::InternalSubsts::identity_for_item(tcx, obligation.predicate.item_def_id)
|
== ty::InternalSubsts::identity_for_item(tcx, obligation.predicate.item_def_id)
|
||||||
.type_at(0)
|
.type_at(0)
|
||||||
|
&& tcx.associated_item(trait_fn_def_id).defaultness(tcx).has_value()
|
||||||
{
|
{
|
||||||
candidate_set.push_candidate(ProjectionCandidate::ImplTraitInTrait(
|
candidate_set.push_candidate(ProjectionCandidate::ImplTraitInTrait(
|
||||||
ImplTraitInTraitCandidate::Trait,
|
ImplTraitInTraitCandidate::Trait,
|
||||||
|
@ -1337,7 +1339,6 @@ fn assemble_candidate_for_impl_trait_in_trait<'cx, 'tcx>(
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let trait_fn_def_id = tcx.impl_trait_in_trait_parent(obligation.predicate.item_def_id);
|
|
||||||
let trait_def_id = tcx.parent(trait_fn_def_id);
|
let trait_def_id = tcx.parent(trait_fn_def_id);
|
||||||
let trait_substs =
|
let trait_substs =
|
||||||
obligation.predicate.substs.truncate_to(tcx, tcx.generics_of(trait_def_id));
|
obligation.predicate.substs.truncate_to(tcx, tcx.generics_of(trait_def_id));
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue