From 21047f1a1c0dc1dd36c5d5a0a85d76234dd4a263 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sun, 11 Sep 2022 07:42:04 +0000 Subject: [PATCH 1/5] Support default-body trait functions with RPITIT --- .../rustc_hir_analysis/src/collect/type_of.rs | 5 +- .../src/traits/project.rs | 46 +++++++++++++++++-- .../ui/impl-trait/in-trait/default-body.rs | 15 ++++++ 3 files changed, 60 insertions(+), 6 deletions(-) create mode 100644 src/test/ui/impl-trait/in-trait/default-body.rs diff --git a/compiler/rustc_hir_analysis/src/collect/type_of.rs b/compiler/rustc_hir_analysis/src/collect/type_of.rs index f8a62c8491076..08a58f4fed801 100644 --- a/compiler/rustc_hir_analysis/src/collect/type_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/type_of.rs @@ -340,10 +340,9 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> { .. }) => { if in_trait { - span_bug!(item.span, "impl-trait in trait has no default") - } else { - find_opaque_ty_constraints_for_rpit(tcx, def_id, owner) + assert!(tcx.impl_defaultness(owner).has_value()); } + find_opaque_ty_constraints_for_rpit(tcx, def_id, owner) } ItemKind::Trait(..) | ItemKind::TraitAlias(..) diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs index 085045bcdcb50..99953be48853d 100644 --- a/compiler/rustc_trait_selection/src/traits/project.rs +++ b/compiler/rustc_trait_selection/src/traits/project.rs @@ -71,7 +71,15 @@ enum ProjectionCandidate<'tcx> { /// From an "impl" (or a "pseudo-impl" returned by select) Select(Selection<'tcx>), - ImplTraitInTrait(ImplSourceUserDefinedData<'tcx, PredicateObligation<'tcx>>), + ImplTraitInTrait(ImplTraitInTraitCandidate<'tcx>), +} + +#[derive(PartialEq, Eq, Debug)] +enum ImplTraitInTraitCandidate<'tcx> { + // The `impl Trait` from a trait function's default body + Trait, + // A concrete type provided from a trait's `impl Trait` from an impl + Impl(ImplSourceUserDefinedData<'tcx, PredicateObligation<'tcx>>), } enum ProjectionCandidateSet<'tcx> { @@ -1317,6 +1325,17 @@ 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 { + // If we are trying to project an RPITIT with the _identity_ substs, + // then we must be within a default trait body. + if obligation.predicate.substs + == ty::InternalSubsts::identity_for_item(tcx, obligation.predicate.item_def_id) + { + candidate_set.push_candidate(ProjectionCandidate::ImplTraitInTrait( + ImplTraitInTraitCandidate::Trait, + )); + 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 = @@ -1329,7 +1348,9 @@ fn assemble_candidate_for_impl_trait_in_trait<'cx, 'tcx>( let _ = selcx.infcx().commit_if_ok(|_| match selcx.select(&obligation.with(trait_predicate)) { Ok(Some(super::ImplSource::UserDefined(data))) => { - candidate_set.push_candidate(ProjectionCandidate::ImplTraitInTrait(data)); + candidate_set.push_candidate(ProjectionCandidate::ImplTraitInTrait( + ImplTraitInTraitCandidate::Impl(data), + )); Ok(()) } Ok(None) => { @@ -1792,9 +1813,18 @@ fn confirm_candidate<'cx, 'tcx>( ProjectionCandidate::Select(impl_source) => { confirm_select_candidate(selcx, obligation, impl_source) } - ProjectionCandidate::ImplTraitInTrait(data) => { + ProjectionCandidate::ImplTraitInTrait(ImplTraitInTraitCandidate::Impl(data)) => { confirm_impl_trait_in_trait_candidate(selcx, obligation, data) } + // If we're projecting an RPITIT for a default trait body, that's just + // the same def-id, but as an opaque type (with regular RPIT semantics). + ProjectionCandidate::ImplTraitInTrait(ImplTraitInTraitCandidate::Trait) => Progress { + term: selcx + .tcx() + .mk_opaque(obligation.predicate.item_def_id, obligation.predicate.substs) + .into(), + obligations: vec![], + }, }; // When checking for cycle during evaluation, we compare predicates with @@ -2212,6 +2242,16 @@ fn confirm_impl_trait_in_trait_candidate<'tcx>( return Progress { term: tcx.ty_error().into(), obligations }; } + // Use the default `impl Trait` for the trait, e.g., for a default trait body + if leaf_def.item.container == ty::AssocItemContainer::TraitContainer { + return Progress { + term: tcx + .mk_opaque(obligation.predicate.item_def_id, obligation.predicate.substs) + .into(), + obligations, + }; + } + let impl_fn_def_id = leaf_def.item.def_id; let impl_fn_substs = obligation.predicate.substs.rebase_onto(tcx, trait_fn_def_id, data.substs); diff --git a/src/test/ui/impl-trait/in-trait/default-body.rs b/src/test/ui/impl-trait/in-trait/default-body.rs new file mode 100644 index 0000000000000..effc4b1d951ad --- /dev/null +++ b/src/test/ui/impl-trait/in-trait/default-body.rs @@ -0,0 +1,15 @@ +// check-pass +// edition:2021 + +#![feature(return_position_impl_trait_in_trait)] +#![allow(incomplete_features)] + +use std::fmt::Debug; + +trait Foo { + async fn baz() -> impl Debug { + Self::baz().await + } +} + +fn main() {} From 79450360d279f169a40bc8fd55536830f5a939fe Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Wed, 5 Oct 2022 04:16:05 +0000 Subject: [PATCH 2/5] Fix test for default body with impl --- compiler/rustc_middle/src/ty/sty.rs | 1 + compiler/rustc_privacy/src/lib.rs | 16 ++++++++++++++-- .../rustc_trait_selection/src/traits/project.rs | 5 +++-- src/test/ui/impl-trait/in-trait/default-body.rs | 14 ++++++++++---- 4 files changed, 28 insertions(+), 8 deletions(-) diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index 2f6ec836c3c06..f8a169fc869f1 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -1160,6 +1160,7 @@ 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); let trait_generics = tcx.generics_of(def_id); ( diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs index 841e3ebb2a13b..4ec9d0b085283 100644 --- a/compiler/rustc_privacy/src/lib.rs +++ b/compiler/rustc_privacy/src/lib.rs @@ -122,8 +122,20 @@ where &mut self, projection: ty::ProjectionTy<'tcx>, ) -> ControlFlow { - let (trait_ref, assoc_substs) = - projection.trait_ref_and_own_substs(self.def_id_visitor.tcx()); + let tcx = self.def_id_visitor.tcx(); + let (trait_ref, assoc_substs) = if tcx.def_kind(projection.item_def_id) + != DefKind::ImplTraitPlaceholder + { + projection.trait_ref_and_own_substs(tcx) + } else { + // HACK(RPITIT): Remove this when RPITITs are lowered to regular assoc tys + let def_id = tcx.impl_trait_in_trait_parent(projection.item_def_id); + let trait_generics = tcx.generics_of(def_id); + ( + ty::TraitRef { def_id, substs: projection.substs.truncate_to(tcx, trait_generics) }, + &projection.substs[trait_generics.count()..], + ) + }; self.visit_trait(trait_ref)?; if self.def_id_visitor.shallow() { ControlFlow::CONTINUE diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs index 99953be48853d..6a4ea114b401e 100644 --- a/compiler/rustc_trait_selection/src/traits/project.rs +++ b/compiler/rustc_trait_selection/src/traits/project.rs @@ -1325,10 +1325,11 @@ 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 { - // If we are trying to project an RPITIT with the _identity_ substs, + // 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.substs + if obligation.predicate.self_ty() == ty::InternalSubsts::identity_for_item(tcx, obligation.predicate.item_def_id) + .type_at(0) { candidate_set.push_candidate(ProjectionCandidate::ImplTraitInTrait( ImplTraitInTraitCandidate::Trait, diff --git a/src/test/ui/impl-trait/in-trait/default-body.rs b/src/test/ui/impl-trait/in-trait/default-body.rs index effc4b1d951ad..b0baf5bb10dd2 100644 --- a/src/test/ui/impl-trait/in-trait/default-body.rs +++ b/src/test/ui/impl-trait/in-trait/default-body.rs @@ -1,15 +1,21 @@ // check-pass // edition:2021 -#![feature(return_position_impl_trait_in_trait)] +#![feature(async_fn_in_trait, return_position_impl_trait_in_trait)] #![allow(incomplete_features)] use std::fmt::Debug; trait Foo { - async fn baz() -> impl Debug { - Self::baz().await + async fn baz(&self) -> &str { + "" } } -fn main() {} +struct Bar; + +impl Foo for Bar {} + +fn main() { + let _ = Bar.baz(); +} From 86734b04a7c36da0f84226f687f0da331b7f921f Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sun, 11 Sep 2022 08:51:25 +0000 Subject: [PATCH 3/5] Bless tests --- src/test/ui/async-await/async-trait-fn.rs | 3 - src/test/ui/async-await/async-trait-fn.stderr | 56 ++----------------- .../edition-deny-async-fns-2015.rs | 1 - .../edition-deny-async-fns-2015.stderr | 26 ++------- ...021-incompatible-closure-captures-93117.rs | 1 - ...incompatible-closure-captures-93117.stderr | 22 ++------ 6 files changed, 14 insertions(+), 95 deletions(-) diff --git a/src/test/ui/async-await/async-trait-fn.rs b/src/test/ui/async-await/async-trait-fn.rs index 0ea685986db40..e2062e82725c0 100644 --- a/src/test/ui/async-await/async-trait-fn.rs +++ b/src/test/ui/async-await/async-trait-fn.rs @@ -1,11 +1,8 @@ // edition:2018 trait T { async fn foo() {} //~ ERROR functions in traits cannot be declared `async` - //~^ ERROR mismatched types async fn bar(&self) {} //~ ERROR functions in traits cannot be declared `async` - //~^ ERROR mismatched types async fn baz() { //~ ERROR functions in traits cannot be declared `async` - //~^ ERROR mismatched types // Nested item must not ICE. fn a() {} } diff --git a/src/test/ui/async-await/async-trait-fn.stderr b/src/test/ui/async-await/async-trait-fn.stderr index 4fa54c6e36960..afbe25cf7ab74 100644 --- a/src/test/ui/async-await/async-trait-fn.stderr +++ b/src/test/ui/async-await/async-trait-fn.stderr @@ -12,7 +12,7 @@ LL | async fn foo() {} = help: add `#![feature(async_fn_in_trait)]` to the crate attributes to enable error[E0706]: functions in traits cannot be declared `async` - --> $DIR/async-trait-fn.rs:5:5 + --> $DIR/async-trait-fn.rs:4:5 | LL | async fn bar(&self) {} | -----^^^^^^^^^^^^^^ @@ -25,7 +25,7 @@ LL | async fn bar(&self) {} = help: add `#![feature(async_fn_in_trait)]` to the crate attributes to enable error[E0706]: functions in traits cannot be declared `async` - --> $DIR/async-trait-fn.rs:7:5 + --> $DIR/async-trait-fn.rs:5:5 | LL | async fn baz() { | -----^^^^^^^^^ @@ -37,54 +37,6 @@ LL | async fn baz() { = note: see issue #91611 for more information = help: add `#![feature(async_fn_in_trait)]` to the crate attributes to enable -error[E0308]: mismatched types - --> $DIR/async-trait-fn.rs:3:20 - | -LL | async fn foo() {} - | ^^ expected associated type, found opaque type - | - ::: $SRC_DIR/core/src/future/mod.rs:LL:COL - | -LL | pub const fn from_generator(gen: T) -> impl Future - | ------------------------------- the found opaque type - | - = note: expected associated type `impl Future` (trait associated opaque type at <$DIR/async-trait-fn.rs:3:20>) - found opaque type `impl Future` (opaque type at <$SRC_DIR/core/src/future/mod.rs:LL:COL>) - -error[E0308]: mismatched types - --> $DIR/async-trait-fn.rs:5:25 - | -LL | async fn bar(&self) {} - | ^^ expected associated type, found opaque type - | - ::: $SRC_DIR/core/src/future/mod.rs:LL:COL - | -LL | pub const fn from_generator(gen: T) -> impl Future - | ------------------------------- the found opaque type - | - = note: expected associated type `impl Future` (trait associated opaque type at <$DIR/async-trait-fn.rs:5:25>) - found opaque type `impl Future` (opaque type at <$SRC_DIR/core/src/future/mod.rs:LL:COL>) - -error[E0308]: mismatched types - --> $DIR/async-trait-fn.rs:7:20 - | -LL | async fn baz() { - | ____________________^ -LL | | -LL | | // Nested item must not ICE. -LL | | fn a() {} -LL | | } - | |_____^ expected associated type, found opaque type - | - ::: $SRC_DIR/core/src/future/mod.rs:LL:COL - | -LL | pub const fn from_generator(gen: T) -> impl Future - | ------------------------------- the found opaque type - | - = note: expected associated type `impl Future` (trait associated opaque type at <$DIR/async-trait-fn.rs:7:20>) - found opaque type `impl Future` (opaque type at <$SRC_DIR/core/src/future/mod.rs:LL:COL>) - -error: aborting due to 6 previous errors +error: aborting due to 3 previous errors -Some errors have detailed explanations: E0308, E0706. -For more information about an error, try `rustc --explain E0308`. +For more information about this error, try `rustc --explain E0706`. diff --git a/src/test/ui/async-await/edition-deny-async-fns-2015.rs b/src/test/ui/async-await/edition-deny-async-fns-2015.rs index 22a61dcd25f98..6bd6d879a4ace 100644 --- a/src/test/ui/async-await/edition-deny-async-fns-2015.rs +++ b/src/test/ui/async-await/edition-deny-async-fns-2015.rs @@ -17,7 +17,6 @@ impl Foo { trait Bar { async fn foo() {} //~ ERROR `async fn` is not permitted in Rust 2015 //~^ ERROR functions in traits cannot be declared `async` - //~| ERROR mismatched types } fn main() { diff --git a/src/test/ui/async-await/edition-deny-async-fns-2015.stderr b/src/test/ui/async-await/edition-deny-async-fns-2015.stderr index 62a243e69e743..ba918eb28def1 100644 --- a/src/test/ui/async-await/edition-deny-async-fns-2015.stderr +++ b/src/test/ui/async-await/edition-deny-async-fns-2015.stderr @@ -53,7 +53,7 @@ LL | async fn foo() {} = note: for more on editions, read https://doc.rust-lang.org/edition-guide error[E0670]: `async fn` is not permitted in Rust 2015 - --> $DIR/edition-deny-async-fns-2015.rs:37:9 + --> $DIR/edition-deny-async-fns-2015.rs:36:9 | LL | async fn bar() {} | ^^^^^ to use `async fn`, switch to Rust 2018 or later @@ -62,7 +62,7 @@ LL | async fn bar() {} = note: for more on editions, read https://doc.rust-lang.org/edition-guide error[E0670]: `async fn` is not permitted in Rust 2015 - --> $DIR/edition-deny-async-fns-2015.rs:27:9 + --> $DIR/edition-deny-async-fns-2015.rs:26:9 | LL | async fn foo() {} | ^^^^^ to use `async fn`, switch to Rust 2018 or later @@ -71,7 +71,7 @@ LL | async fn foo() {} = note: for more on editions, read https://doc.rust-lang.org/edition-guide error[E0670]: `async fn` is not permitted in Rust 2015 - --> $DIR/edition-deny-async-fns-2015.rs:32:13 + --> $DIR/edition-deny-async-fns-2015.rs:31:13 | LL | async fn bar() {} | ^^^^^ to use `async fn`, switch to Rust 2018 or later @@ -92,21 +92,7 @@ LL | async fn foo() {} = note: see issue #91611 for more information = help: add `#![feature(async_fn_in_trait)]` to the crate attributes to enable -error[E0308]: mismatched types - --> $DIR/edition-deny-async-fns-2015.rs:18:20 - | -LL | async fn foo() {} - | ^^ expected associated type, found opaque type - | - ::: $SRC_DIR/core/src/future/mod.rs:LL:COL - | -LL | pub const fn from_generator(gen: T) -> impl Future - | ------------------------------- the found opaque type - | - = note: expected associated type `impl Future` (trait associated opaque type at <$DIR/edition-deny-async-fns-2015.rs:18:20>) - found opaque type `impl Future` (opaque type at <$SRC_DIR/core/src/future/mod.rs:LL:COL>) - -error: aborting due to 11 previous errors +error: aborting due to 10 previous errors -Some errors have detailed explanations: E0308, E0670, E0706. -For more information about an error, try `rustc --explain E0308`. +Some errors have detailed explanations: E0670, E0706. +For more information about an error, try `rustc --explain E0670`. diff --git a/src/test/ui/span/drop-location-span-error-rust-2021-incompatible-closure-captures-93117.rs b/src/test/ui/span/drop-location-span-error-rust-2021-incompatible-closure-captures-93117.rs index 94f578af209a8..4559da91e47a8 100644 --- a/src/test/ui/span/drop-location-span-error-rust-2021-incompatible-closure-captures-93117.rs +++ b/src/test/ui/span/drop-location-span-error-rust-2021-incompatible-closure-captures-93117.rs @@ -12,7 +12,6 @@ impl A { trait C{async fn new(val: T) {} //~ ERROR `async fn` is not permitted in Rust 2015 //~^ ERROR functions in traits cannot be declared `async` -//~| ERROR mismatched types //~| ERROR cannot find type `T` in this scope //~| WARN changes to closure capture in Rust 2021 will affect drop order [rust_2021_incompatible_closure_captures] diff --git a/src/test/ui/span/drop-location-span-error-rust-2021-incompatible-closure-captures-93117.stderr b/src/test/ui/span/drop-location-span-error-rust-2021-incompatible-closure-captures-93117.stderr index ee72a0c65c8e2..f7109d406d57a 100644 --- a/src/test/ui/span/drop-location-span-error-rust-2021-incompatible-closure-captures-93117.stderr +++ b/src/test/ui/span/drop-location-span-error-rust-2021-incompatible-closure-captures-93117.stderr @@ -1,5 +1,5 @@ error: this file contains an unclosed delimiter - --> $DIR/drop-location-span-error-rust-2021-incompatible-closure-captures-93117.rs:19:53 + --> $DIR/drop-location-span-error-rust-2021-incompatible-closure-captures-93117.rs:18:53 | LL | trait C{async fn new(val: T) {} | - unclosed delimiter @@ -74,20 +74,6 @@ help: add a dummy let to cause `path` to be fully captured LL | async fn create(path: impl AsRef) { let _ = &path; | ++++++++++++++ -error[E0308]: mismatched types - --> $DIR/drop-location-span-error-rust-2021-incompatible-closure-captures-93117.rs:13:30 - | -LL | trait C{async fn new(val: T) {} - | ^^ expected associated type, found opaque type - | - ::: $SRC_DIR/core/src/future/mod.rs:LL:COL - | -LL | pub const fn from_generator(gen: T) -> impl Future - | ------------------------------- the found opaque type - | - = note: expected associated type `impl Future` (trait associated opaque type at <$DIR/drop-location-span-error-rust-2021-incompatible-closure-captures-93117.rs:13:30>) - found opaque type `impl Future` (opaque type at <$SRC_DIR/core/src/future/mod.rs:LL:COL>) - warning: changes to closure capture in Rust 2021 will affect drop order --> $DIR/drop-location-span-error-rust-2021-incompatible-closure-captures-93117.rs:13:30 | @@ -103,7 +89,7 @@ help: add a dummy let to cause `val` to be fully captured LL | trait C{async fn new(val: T) { let _ = &val;} | +++++++++++++ -error: aborting due to 7 previous errors; 2 warnings emitted +error: aborting due to 6 previous errors; 2 warnings emitted -Some errors have detailed explanations: E0308, E0412, E0423, E0670, E0706. -For more information about an error, try `rustc --explain E0308`. +Some errors have detailed explanations: E0412, E0423, E0670, E0706. +For more information about an error, try `rustc --explain E0412`. From 9a5936b8144c412394ecd0d9dd931faeb4d2034d Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Fri, 30 Sep 2022 19:16:13 +0000 Subject: [PATCH 4/5] Validate opaques in default trait bodies, don't normalize unless a body is provided --- .../rustc_hir_analysis/src/check/check.rs | 56 +++++++++++-------- compiler/rustc_middle/src/ty/sty.rs | 2 +- .../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 824144aeac004..bf022286b8255 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 f8a169fc869f1..646369633133c 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 6a4ea114b401e..8e2f1d5def3da 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)); From 0eeeea9414d0ee5b22f6a33601282b46eca67bd6 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Wed, 5 Oct 2022 03:52:38 +0000 Subject: [PATCH 5/5] Add broken test for AFIT with RPITIT --- .../in-trait/default-body-with-rpit.rs | 21 +++++++++++++++++++ .../in-trait/default-body-with-rpit.stderr | 12 +++++++++++ 2 files changed, 33 insertions(+) create mode 100644 src/test/ui/impl-trait/in-trait/default-body-with-rpit.rs create mode 100644 src/test/ui/impl-trait/in-trait/default-body-with-rpit.stderr diff --git a/src/test/ui/impl-trait/in-trait/default-body-with-rpit.rs b/src/test/ui/impl-trait/in-trait/default-body-with-rpit.rs new file mode 100644 index 0000000000000..f0d407cd527d6 --- /dev/null +++ b/src/test/ui/impl-trait/in-trait/default-body-with-rpit.rs @@ -0,0 +1,21 @@ +// known-bug: #102688 +// edition:2021 + +#![feature(async_fn_in_trait, return_position_impl_trait_in_trait)] +#![allow(incomplete_features)] + +use std::fmt::Debug; + +trait Foo { + async fn baz(&self) -> impl Debug { + "" + } +} + +struct Bar; + +impl Foo for Bar {} + +fn main() { + let _ = Bar.baz(); +} diff --git a/src/test/ui/impl-trait/in-trait/default-body-with-rpit.stderr b/src/test/ui/impl-trait/in-trait/default-body-with-rpit.stderr new file mode 100644 index 0000000000000..4529d301f9e91 --- /dev/null +++ b/src/test/ui/impl-trait/in-trait/default-body-with-rpit.stderr @@ -0,0 +1,12 @@ +error[E0720]: cannot resolve opaque type + --> $DIR/default-body-with-rpit.rs:10:28 + | +LL | async fn baz(&self) -> impl Debug { + | ^^^^^^^^^^ cannot resolve opaque type + | + = note: these returned values have a concrete "never" type + = help: this error will resolve once the item's body returns a concrete type + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0720`.