From af24d0b66081bebc881769145385f5baeeed390d Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Mon, 26 Aug 2024 16:39:44 -0400 Subject: [PATCH] Resolve self type alias in impl for RTN --- .../src/collect/resolve_bound_vars.rs | 26 ++++++++++++++++++- .../path-constrained-in-method.rs | 24 +++++++++++++++++ .../path-constrained-in-method.stderr | 11 ++++++++ .../return-type-notation/path-self-qself.rs | 11 ++++++++ 4 files changed, 71 insertions(+), 1 deletion(-) create mode 100644 tests/ui/associated-type-bounds/return-type-notation/path-constrained-in-method.rs create mode 100644 tests/ui/associated-type-bounds/return-type-notation/path-constrained-in-method.stderr diff --git a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs index 3be908fbaea..71d9703bb0e 100644 --- a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs +++ b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs @@ -1910,6 +1910,7 @@ fn try_append_return_type_notation_params( // from the generics of the parameter's definition, since we want // to be able to resolve an RTN path on a nested body (e.g. method // inside an impl) using the where clauses on the method. + // FIXME(return_type_notation): Think of some better way of doing this. let Some(generics) = self.tcx.hir_owner_node(hir_id.owner).generics() else { return; @@ -1948,7 +1949,30 @@ fn try_append_return_type_notation_params( }; (bound_vars, assoc_item.def_id, item_segment) } - Res::SelfTyAlias { is_trait_impl: true, .. } => todo!(), + // If we have a self type alias (in an impl), try to resolve an + // associated item from one of the supertraits of the impl's trait. + Res::SelfTyAlias { alias_to: impl_def_id, is_trait_impl: true, .. } => { + let hir::ItemKind::Impl(hir::Impl { of_trait: Some(trait_ref), .. }) = self + .tcx + .hir_node_by_def_id(impl_def_id.expect_local()) + .expect_item() + .kind + else { + return; + }; + let Some(trait_def_id) = trait_ref.trait_def_id() else { + return; + }; + let Some((bound_vars, assoc_item)) = BoundVarContext::supertrait_hrtb_vars( + self.tcx, + trait_def_id, + item_segment.ident, + ty::AssocKind::Fn, + ) else { + return; + }; + (bound_vars, assoc_item.def_id, item_segment) + } _ => return, } } diff --git a/tests/ui/associated-type-bounds/return-type-notation/path-constrained-in-method.rs b/tests/ui/associated-type-bounds/return-type-notation/path-constrained-in-method.rs new file mode 100644 index 00000000000..56abd167fb6 --- /dev/null +++ b/tests/ui/associated-type-bounds/return-type-notation/path-constrained-in-method.rs @@ -0,0 +1,24 @@ +//@ check-pass + +#![feature(return_type_notation)] +//~^ WARN the feature `return_type_notation` is incomplete + +trait Trait { + fn method() -> impl Sized; +} + +fn is_send(_: impl Send) {} + +struct W(T); + +impl W { + fn test() + where + T: Trait, + T::method(..): Send, + { + is_send(T::method()); + } +} + +fn main() {} diff --git a/tests/ui/associated-type-bounds/return-type-notation/path-constrained-in-method.stderr b/tests/ui/associated-type-bounds/return-type-notation/path-constrained-in-method.stderr new file mode 100644 index 00000000000..3db033d8cf5 --- /dev/null +++ b/tests/ui/associated-type-bounds/return-type-notation/path-constrained-in-method.stderr @@ -0,0 +1,11 @@ +warning: the feature `return_type_notation` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/path-constrained-in-method.rs:3:12 + | +LL | #![feature(return_type_notation)] + | ^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #109417 for more information + = note: `#[warn(incomplete_features)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/associated-type-bounds/return-type-notation/path-self-qself.rs b/tests/ui/associated-type-bounds/return-type-notation/path-self-qself.rs index 1173101ae45..0cf84457ba7 100644 --- a/tests/ui/associated-type-bounds/return-type-notation/path-self-qself.rs +++ b/tests/ui/associated-type-bounds/return-type-notation/path-self-qself.rs @@ -13,4 +13,15 @@ fn other() Self::method(..): Send; } +fn is_send(_: impl Send) {} + +impl Bar for T { + fn other() + where + Self::method(..): Send, + { + is_send(Self::method()); + } +} + fn main() {}