Skip to content

ICE on generic impl trait convergence #58344

Closed
@leops

Description

@leops

Using a generic function to "converge" two impl Trait<T> into T when T is an associated type for another trait causes the following error:

error: internal compiler error: broken MIR in DefId(0/0:14 ~ playground[c5d2]::main[0]) (NoSolution): could not prove Binder(TraitPredicate(<impl Trait<<u32 as std::ops::Add>::Output> as Trait<u32>>))

error: internal compiler error: broken MIR in DefId(0/0:14 ~ playground[c5d2]::main[0]) (Terminator { source_info: SourceInfo { span: src/main.rs:46:5: 46:26, scope: scope[0] }, kind: _1 = const <Either<L, R>>::converge(move _2) -> [return: bb3, unwind: bb4] }): call dest mismatch (<u32 as std::ops::Add>::Output <- u32): NoSolution
  --> src/main.rs:45:1
   |
45 | / pub fn main() {
46 | |     add_one(3).converge();
47 | | }
   | |_^

Example code (Playground link):

use std::ops::Add;

trait Trait<T> {
    fn get(self) -> T;
}

struct Holder<T>(T);

impl<T> Trait<T> for Holder<T> {
    fn get(self) -> T {
        self.0
    }
}

enum Either<L, R> {
    Left(L),
    Right(R),
}

impl<L, R> Either<L, R> {
    fn converge<T>(self) -> T where L: Trait<T>, R: Trait<T> {
        match self {
            Either::Left(val) => val.get(),
            Either::Right(val) => val.get(),
        }
    }
}

fn add_generic<A: Add<B>, B>(lhs: A, rhs: B) -> Either<
    impl Trait<<A as Add<B>>::Output>,
    impl Trait<<A as Add<B>>::Output>
> {
    if true {
        Either::Left(Holder(lhs + rhs))
    } else {
        Either::Right(Holder(lhs + rhs))
    }
}

// FAIL: fn add_one(value: u32) -> Either<impl Trait<u32>, impl Trait<u32>> {
fn add_one(value: u32) -> Either<impl Trait<<u32 as Add<u32>>::Output>, impl Trait<<u32 as Add<u32>>::Output>> {
    add_generic(value, 1u32)
}

pub fn main() {
    add_one(3).converge();
}

This may or may not be related to the compiler seemingly failing to assert that <u32 as Add<u32>>::Output == u32, an error that can be triggered by using the alternate signature for add_one at line 40 of the example.

Meta

I tested this with the linked playground on the latest stable (1.32.0), as well as a recent nightly:

rustc 1.33.0-nightly (bf669d1e3 2019-01-25)
binary: rustc
commit-hash: bf669d1e3295bc688f71b8c91f48a6beaf895f67
commit-date: 2019-01-25
host: x86_64-pc-windows-msvc
release: 1.33.0-nightly
LLVM version: 8.0

Compiling with RUST_BACKTRACE=1 doesn't seem to yield a very useful stack but here it is:

thread 'rustc' panicked at 'no errors encountered even though `delay_span_bug` issued', src\librustc_errors\lib.rs:323:17
stack backtrace:
   0: std::sys_common::alloc::realloc_fallback
   1: std::panicking::take_hook
   2: std::panicking::take_hook
   3: <rustc::ty::SymbolName as core::fmt::Debug>::fmt
   4: std::panicking::rust_panic_with_hook
   5: <rustc_errors::Level as core::fmt::Debug>::fmt
   6: <rustc_errors::Handler as core::ops::drop::Drop>::drop
   7: <rustc_driver::CompilationFailure as core::fmt::Debug>::fmt
   8: <rustc_driver::CompilationFailure as core::fmt::Debug>::fmt
   9: <rustc_driver::CompilationFailure as core::fmt::Debug>::fmt
  10: <rustc_driver::CompilationFailure as core::fmt::Debug>::fmt
  11: <humantime::duration::Error as std::error::Error>::cause
  12: _rust_maybe_catch_panic
  13: <humantime::duration::Error as std::error::Error>::cause
  14: std::sys::windows::thread::Thread::new
  15: BaseThreadInitThunk
  16: RtlUserThreadStart
query stack during panic:
end of query stack

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-MIRArea: Mid-level IR (MIR) - https://blog.rust-lang.org/2016/04/19/MIR.htmlA-impl-traitArea: `impl Trait`. Universally / existentially quantified anonymous types with static dispatch.C-bugCategory: This is a bug.E-needs-testCall for participation: An issue has been fixed and does not reproduce, but no test has been added.I-ICEIssue: The compiler panicked, giving an Internal Compilation Error (ICE) ❄️P-mediumMedium priorityT-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