Repository: rust
Issue: Hidden type of "discarded" and thus unconstrained RPIT(IT) opaque types gets inferred to be the unit type `()`
Labels: P-low,A-inference,A-impl-trait,C-bug,T-types,fixed-by-next-solver

This only affects RPIT(IT), not TAIT or ATPIT.
Fixing this issue would be a breaking change.
This exploits the issue #132212 (syntactically rejecting impl-Trait inside non-final path segments & inside fn ptr types is futile).

---

All subsequent snippets assume the following definitions:

```rs
type DiscardT<T> = <T as Discard>::Output;
trait Discard { type Output; }
impl<T: ?Sized> Discard for T { type Output = Point; } // you can substitute `Point` with `()` everywhere, this is just for clarity
struct Point;
trait NobodyImplsThis {}
```

RPIT check-pass reproducer ([playground](https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=f2cb70d7362bb7d48f0dcb88462d3676)):

```rs
fn demo0() -> DiscardT<impl ?Sized> { Point }
```

RPIT check-fail reproducer ([playground](https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=273bbd96006fe4bcb0784ec419d7c1dc)):

```rs
fn demo1() -> DiscardT<impl NobodyImplsThis + ?Sized> { Point }
//~^ ERROR the trait bound `(): NobodyImplsThis` is not satisfied
```

I expected both reproducers to get rejected by the compiler due to uninferable types or unconstrained opaque types (with an error roughly of the form *item does not constrain `demoN::{opaque#0}`, but has it in its signature* (mirroring TAIT/ATPIT)). The opaque types should be unconstrained because `DiscardT<{opaque}>` normalizes to `Point` which does not contain any opaque types.

However, in both cases the hidden type gets inferred to be `()`. See also the compiler log for the first reproducer:

```rs
rustc_hir_analysis::check::check::check_opaque_meets_bounds def_id=DefId(0:13 ~ oi[08b9]::demo0::{opaque#0}), span=oi.rs:6:24: 6:35 (#4), origin=FnReturn { parent: DefId(0:12 ~ oi[08b9]::demo0), in_trait_or_impl: None }
   rustc_middle::ty::sty::new_opaque def_id=DefId(0:13 ~ oi[08b9]::demo0::{opaque#0}), args=[]
   rustc_infer::infer::opaque_types::register_hidden_type opaque_type_key=OpaqueTypeKey { def_id: DefId(0:13 ~ oi[08b9]::demo0::{opaque#0}), args: [] }, span=oi.rs:6:24: 6:35 (#4), param_env=ParamEnv { caller_bounds: [], reveal: UserFacing }, hidden_ty=()
     rustc_infer::infer::opaque_types::table::register key=OpaqueTypeKey { def_id: DefId(0:13 ~ oi[08b9]::demo0::{opaque#0}), args: [] }, hidden_type=OpaqueHiddenType { span: oi.rs:6:24: 6:35 (#4), ty: () }
```

It's odd that some sort of type inference fallback occurs (in case you're wondering: In Rust 2024, it also falls back to `()`, not `!` (since we don't have anything diverging here)).

Related: The fixed issue #96460 (`PhantomData<{opaque}>`).
Ranking this P-low because it's pretty artificial and not unsound.

<details><summary>For completeness, RPITIT reproducers</summary>

```rs
trait Demo2 { fn f() -> DiscardT<impl ?Sized> { Point } }
```

```rs
trait Demo3 { fn f() -> DiscardT<impl NobodyImplsThis + ?Sized> { Point } }
//~^ ERROR the trait bound `(): NobodyImplsThis` is not satisfied
```

</details>

---

For comparison, the TAIT and ATPIT analogues result in an error (though I'm not sure if that's an interesting comparison to draw).

<details><summary>TAIT/ATPIT</summary>

```rs
#![feature(type_alias_impl_trait, impl_trait_in_assoc_type)]

type Weak0 = impl ?Sized;
fn demo4() -> DiscardT<Weak0> { Point }
//~^ ERROR item does not constrain `Weak0::{opaque#0}`, but has it in its signature

type Weak1 = DiscardT<impl ?Sized>;
fn demo5() -> Weak1 { Point }
//~^ ERROR item does not constrain `Weak1::{opaque#0}`, but has it in its signature

trait Demo6 {
    type Proj: ?Sized;
    fn f() -> DiscardT<Self::Proj>;
}
impl Demo6 for i32 {
    type Proj = impl ?Sized;
    fn f() -> DiscardT<Self::Proj> { Point }
    //~^ ERROR item does not constrain `<i32 as Demo6>::Proj::{opaque#0}`, but has it in its signature
}

trait Demo7 { 
    type Proj;
    fn f() -> Self::Proj;
}
impl Demo7 for i32 {
    type Proj = DiscardT<impl ?Sized>;
    fn f() -> Self::Proj { Point }
    //~^ ERROR item does not constrain `<i32 as Demo7>::Proj::{opaque#0}`, but has it in its signature
}
```

</details>