Skip to content

recursive type_alias_impl_trait unsoundly allows different underlying types #113314

Closed
@kwannoel

Description

@kwannoel

edit: minimized

#![feature(type_alias_impl_trait)]

type Op = impl std::fmt::Display;
fn foo() -> Op { &"hello world" }

fn transform<S>() -> impl std::fmt::Display {
    &0usize
}
fn bad() -> Op {
    transform::<Op>()
}

fn main() {
    let mut x = foo();
    println!("{x}");
    x = bad();
    println!("{x}");
}

see #113314 (comment) for more details


I tried this code:

#![feature(type_alias_impl_trait)]
#![feature(generators)]
#![feature(stmt_expr_attributes)]
#![feature(proc_macro_hygiene)]

use anyhow::{anyhow, Result};
use futures::stream::Stream;
use futures_async_stream::{stream, for_await};

type Op = impl Stream<Item = Result<usize>>;
async fn iter() -> Op {
    futures::stream::iter(vec![Ok(1), Err(anyhow!(""))])
}

#[stream(item = Result<usize>)]
async fn transform<S>(stream: S)
where
    S: Stream<Item = Result<usize>> + Unpin,
{
    #[for_await]
    for i in stream {
        yield i;
    }
}

async fn bad() -> Op {
    transform(Box::pin(iter().await))
}

#[allow(dead_code)]
#[stream(item = Result<usize>)]
async fn good() {
    #[for_await]
    for i in transform(Box::pin(iter().await)) {
        yield i;
    }
}

#[tokio::main]
async fn main() {
    let s = bad().await;
    // let s = good(); // may comment this out, this works instead.
    #[for_await]
    for i in s {
        println!("{:#?}", i);
    }
}

I expected to see this happen: Compilation should fail, because different generator types should be generated by calling transform, meaning bad and iter should not share the same type Op.

Instead, compilation passes, and SEGFAULT occurs during runtime:

    Finished dev [unoptimized + debuginfo] target(s) in 0.05s
     Running `target/debug/async-stream-min`
Ok(
    2334106421097295465,
)
Err(
zsh: segmentation fault  cargo run --bin async-stream-min

More context: https://github.com/risingwavelabs/risingwave/pull/10266/files#r1244771828

Meta

rustc --version --verbose:

rustc 1.69.0-nightly (31f858d9a 2023-02-28)
binary: rustc
commit-hash: 31f858d9a511f24fedb8ed997b28304fec809630
commit-date: 2023-02-28
host: aarch64-apple-darwin
release: 1.69.0-nightly
LLVM version: 15.0.7
No Backtrace from running it

$ RUST_BACKTRACE=1 cargo run --bin async-stream-min
    Finished dev [unoptimized + debuginfo] target(s) in 0.05s
     Running `target/debug/async-stream-min`
Ok(
    2334106421097295465,
)
Err(
zsh: segmentation fault  RUST_BACKTRACE=1 cargo run --bin async-stream-min
noelkwan@Noels-MacBook-Pro rust-experiments % 

Metadata

Metadata

Assignees

No one assigned

    Labels

    C-bugCategory: This is a bug.F-type_alias_impl_trait`#[feature(type_alias_impl_trait)]`I-unsoundIssue: A soundness hole (worst kind of bug), see: https://en.wikipedia.org/wiki/SoundnessT-typesRelevant to the types team, which will review and decide on the PR/issue.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions