Skip to content

opaque type needlessly inferred to be recursive #115017

Open
@aliemjay

Description

@aliemjay

The following code should compile. However we infer two conflicting hidden types, Opaque<A> := Opaque<A> and Opaque<B> := u8, causing an error:

#![feature(type_alias_impl_trait)]
type Opaque<T> = impl Sized;
fn test<A, B>(
    arg: Vec<(Opaque<A>, u8)>,
) -> impl IntoIterator<Item = (Opaque<A>, Opaque<B>)> {
    arg
    //~^ ERROR concrete type differs from previous defining opaque type use
    //~| expected `Opaque<T>`, got `u8`
}

Another case to show that it is not enough to naively ignore the recursive definition, as it may have different arguments (Opaque<'a, 'b> := Opaque<'static, 'static>).

#![feature(type_alias_impl_trait)]

type Opaque<'a, 'b> = impl Sized + 'a + 'b;
//~^ ERROR concrete type differs from previous defining opaque type use
//~| expected `Opaque<'static, 'static>`, got `()`

// `Opaque<'a, 'b> := ()`
fn get_one<'a, 'b>() -> Opaque<'a, 'b> {}

// `Opaque<'a, 'b> := Opaque<'static, 'static>`
fn get_iter<'a, 'b>() -> impl IntoIterator<Item = Opaque<'a, 'b>> {
    Some(get_one())
}

Normally when we encounter an equality Opaque<A> == Opaque<A>, we equate substs and never register a hidden type.

The only way we infer an opaque type to be recursive in borrowck is through replace_opaque_types_with_inference_vars here:

// For an example where this is necessary see tests/ui/impl-trait/nested-return-type2.rs
// This allows users to omit re-mentioning all bounds on an associated type and just use an
// `impl Trait` for the assoc type to add more bounds.
let InferOk { value: actual, obligations: new } =
selcx.infcx.replace_opaque_types_with_inference_vars(
actual,
obligation.cause.body_id,
obligation.cause.span,
obligation.param_env,
);

Metadata

Metadata

Assignees

Labels

A-impl-traitArea: `impl Trait`. Universally / existentially quantified anonymous types with static dispatch.C-bugCategory: This is a bug.F-type_alias_impl_trait`#[feature(type_alias_impl_trait)]`T-typesRelevant to the types team, which will review and decide on the PR/issue.

Type

No type

Projects

Status

Todo

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions