about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMichael Goulet <michael@errs.io>2022-09-30 19:16:13 +0000
committerMichael Goulet <michael@errs.io>2022-10-05 04:16:09 +0000
commit9a5936b8144c412394ecd0d9dd931faeb4d2034d (patch)
treef3bb7272557192dc491dbaedffa05ec388126a3c
parent86734b04a7c36da0f84226f687f0da331b7f921f (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.rs56
-rw-r--r--compiler/rustc_middle/src/ty/sty.rs2
-rw-r--r--compiler/rustc_trait_selection/src/traits/project.rs3
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));