Skip to content

The scope of associated existential types #57933

@Centril

Description

@Centril

Given the following snippet (playground):

#![feature(existential_type)]

trait A { type B; }

mod enclosing {
    struct C;
    
    impl crate::A for C { existential type B: Copy; }
    
    pub fn make() -> <C as crate::A>::B {
        42u8 // This is a defining use.
    }
}

It seems that rustc considers the scope of seeing the underlying type to be impl crate::A for C and not enclosing:

error: could not find defining uses
 --> src/lib.rs:8:27
  |
8 |     impl crate::A for C { existential type B: Copy; }
  |                           ^^^^^^^^^^^^^^^^^^^^^^^^^

The RFC states that:

Each existential type declaration must be constrained by at least one function body or const/static initializer. A body or initializer must either fully constrain or place no constraints upon a given existential type.

Existential types are similar to normal type aliases, except that their concrete type is determined from the scope in which they are defined (usually a module or a trait impl).

The latter quote suggests that the behavior seen above may be correct.
However, in a comment, the RFC also states:

impl Iterator for MyStruct {
    // Here we can declare an associated type whose concrete type is hidden
    // to other modules.
    //
    // External users only know that `Item` implements the `Debug` trait.
    existential type Item: Debug;

   ...
}

This suggests (note the word module) that the current implementation is wrong and that the snippet should be allowed.

So which behavior is correct? And why? cc @cramertj @nikomatsakis @alexreg

As a final note, currently, the user has a recourse in writing:

#![feature(existential_type)]

trait A { type B; }

mod enclosing {
    struct C;

    existential type B: Copy;

    impl crate::A for C { type B = B; }
    
    pub fn make() -> B {
        42u8
    }
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-associated-itemsArea: Associated items (types, constants & functions)A-impl-traitArea: `impl Trait`. Universally / existentially quantified anonymous types with static dispatch.A-trait-systemArea: Trait systemA-type-systemArea: Type systemT-langRelevant to the language team

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions