Skip to content

TypeId and Polymorphization #75325

Closed as not planned
Closed as not planned
@davidtwco

Description

@davidtwco

When polymorphization is enabled (-Zpolymorphization=on), then this can currently be observed by TypeId. For example, the following code when built with a polymorphization-enabled compiler will fail the asserts (and succeeds normally; playground):

fn nop<T>() {}

fn test_the_waters<A: 'static, B: 'static>(a: A, _: B) {
    let any: Box<dyn std::any::Any> = Box::new(a);
    assert!(any.downcast_ref::<A>().is_some());
    assert!(any.downcast_ref::<B>().is_none());
    assert!(any.downcast_ref::<fn()>().is_none());
}

fn main() {
    test_the_waters(nop::<u32>, nop::<u64>);
}

This issue was discovered while investigating an earlier regression. After #74538 landed, the example shown below, where a polymorphized closure is indirectly passed to TypeId, would result in an ICE (discussion from that investigation):

use std::any::TypeId;

pub fn foo<T: 'static>(_: T) -> TypeId {
    TypeId::of::<T>()
}

fn outer<T: 'static>() -> TypeId {
    foo(|| ())
}

fn main() {
    assert!(outer::<u8>() != outer::<u16>());
}

In #74717, the check introduced in #74538 was modified so that this case (and another unrelated case) would no longer ICE for polymorphized functions (discussion regarding that PR). There have been more recent discussion regarding this in a dedicated Zulip topic.

Unresolved questions:

  • What is the appropriate behaviour here w/r/t polymorphization?
    • Current consensus appears to be that functions involving reflection cannot be polymorphized.
  • How do we fix this?
    • Without triggering cycle errors, detecting when polymorphization is not appropriate due to later use of TypeId seems very challenging.

Metadata

Metadata

Assignees

No one assigned

    Labels

    -ZpolymorphizeUnstable option: Polymorphization.T-compilerRelevant to the compiler 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