diff options
| author | Michael Goulet <michael@errs.io> | 2022-09-30 19:16:13 +0000 |
|---|---|---|
| committer | Michael Goulet <michael@errs.io> | 2022-10-05 04:16:09 +0000 |
| commit | 9a5936b8144c412394ecd0d9dd931faeb4d2034d (patch) | |
| tree | f3bb7272557192dc491dbaedffa05ec388126a3c | |
| parent | 86734b04a7c36da0f84226f687f0da331b7f921f (diff) | |
Validate opaques in default trait bodies, don't normalize unless a body is provided
| -rw-r--r-- | compiler/rustc_hir_analysis/src/check/check.rs | 56 | ||||
| -rw-r--r-- | compiler/rustc_middle/src/ty/sty.rs | 2 | ||||
| -rw-r--r-- | compiler/rustc_trait_selection/src/traits/project.rs | 3 |
3 files changed, 36 insertions, 25 deletions
diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs index 824144aeac0..bf022286b82 100644 --- a/compiler/rustc_hir_analysis/src/check/check.rs +++ b/compiler/rustc_hir_analysis/src/check/check.rs @@ -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` /// projections that would result in "inheriting lifetimes". -pub(super) fn check_opaque<'tcx>( - tcx: TyCtxt<'tcx>, - def_id: LocalDefId, - substs: SubstsRef<'tcx>, - 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() { +fn check_opaque<'tcx>(tcx: TyCtxt<'tcx>, id: hir::ItemId) { + let item = tcx.hir().item(id); + let hir::ItemKind::OpaqueTy(hir::OpaqueTy { origin, .. }) = item.kind else { + tcx.sess.delay_span_bug(tcx.hir().span(id.hir_id()), "expected opaque item"); + return; + }; + + // 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; } - if check_opaque_for_cycles(tcx, def_id, substs, span, origin).is_err() { + + 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, def_id, substs, span, origin); + 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 /// in "inheriting lifetimes". #[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); } DefKind::OpaqueTy => { - let item = tcx.hir().item(id); - let hir::ItemKind::OpaqueTy(hir::OpaqueTy { origin, .. }) = item.kind else { - return; - }; - // 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 { - 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::ImplTraitPlaceholder => { + let parent = tcx.impl_trait_in_trait_parent(id.def_id.to_def_id()); + // Only check the validity of this opaque type if the function has a default body + if let hir::Node::TraitItem(hir::TraitItem { + kind: hir::TraitItemKind::Fn(_, hir::TraitFn::Provided(_)), + .. + }) = tcx.hir().get_by_def_id(parent.expect_local()) + { + check_opaque(tcx, id); } } DefKind::TyAlias => { diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index f8a169fc869..64636963313 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -1160,8 +1160,8 @@ impl<'tcx> ProjectionTy<'tcx> { &self, tcx: TyCtxt<'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); + assert_eq!(tcx.def_kind(def_id), DefKind::Trait); let trait_generics = tcx.generics_of(def_id); ( ty::TraitRef { def_id, substs: self.substs.truncate_to(tcx, trait_generics) }, diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs index 6a4ea114b40..8e2f1d5def3 100644 --- a/compiler/rustc_trait_selection/src/traits/project.rs +++ b/compiler/rustc_trait_selection/src/traits/project.rs @@ -1325,11 +1325,13 @@ fn assemble_candidate_for_impl_trait_in_trait<'cx, 'tcx>( ) { let tcx = selcx.tcx(); 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, // then we must be within a default trait body. if obligation.predicate.self_ty() == ty::InternalSubsts::identity_for_item(tcx, obligation.predicate.item_def_id) .type_at(0) + && tcx.associated_item(trait_fn_def_id).defaultness(tcx).has_value() { candidate_set.push_candidate(ProjectionCandidate::ImplTraitInTrait( ImplTraitInTraitCandidate::Trait, @@ -1337,7 +1339,6 @@ fn assemble_candidate_for_impl_trait_in_trait<'cx, 'tcx>( 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_substs = obligation.predicate.substs.truncate_to(tcx, tcx.generics_of(trait_def_id)); |
