Skip to content

bug with polymorphisation + closures that inherit unused parameters #74636

Closed
@davidtwco

Description

@davidtwco

#74614 discovered a regression in polymorphisation, fixed by disabling polymorphisation in #74633. This issue will track the fix for the regression, based on the discussion in Zulip (with thanks to @lcnr, @oli-obk and @eddyb).

#74614 can be reduced to the following MCVE (src/test/ui/issues/issue-74614.rs after #74633):

fn test<T>() { std::mem::size_of::<T>(); }

pub fn foo<T>(_: T) -> &'static fn() {
    &(test::<T> as fn())
}

fn outer<T>() {
    foo(|| ());
}


fn main() {
    outer::<u8>();
}

outer is polymorphized because T is not used in outer or outer::{{closure}}#0. outer::{{closure}}#0 therefore inherits T from outer and that ends up being T in foo<T>.

Without a transitive analysis (which isn't possible without hitting cycle errors), outer cannot consider T used based on how outer::{{closure}}#0 is used in other functions.

There are two issues that this can cause - when that closure is used in a cast or when that closure is used in reflection.

When used in a cast (as in the example above), the following lines will be hit:

// All reifications must be monomorphic, bail out otherwise.
if src.layout.ty.needs_subst() {
throw_inval!(TooGeneric);
}

// All reifications must be monomorphic, bail out otherwise.
if src.layout.ty.needs_subst() {
throw_inval!(TooGeneric);
}

Using still_further_specializable instead of needs_subst here fixes the issue, as that flag isn't set for the parent substitutions of closures.

When used in reflection (see the example below), then this will ICE once #74538 lands, but doesn't right now.

use std::any::TypeId;

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

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

fn main() {
    outer::<u8>();
}

Reflection is more complicated because it makes the result of polymorphisation observable.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions