Skip to content

Returning Self in impl Trait does not resolve member types (+ Compiler Crash) #57399

Closed

Description

@ISibboI

A code sample demonstrating the problem:

trait T {
    type T;
}

impl T for i32 {
    type T = u32;
}

struct S<A> {
    a: A,
}

/*// Works
impl From<u32> for S<<i32 as T>::T> {
    fn from(a: u32) -> S<<i32 as T>::T> {
        S::<<i32 as T>::T> {a}
    }
}*/

/*// Works
impl From<u32> for S<<i32 as T>::T> {
    fn from(a: u32) -> Self {
        S::<<i32 as T>::T> {a}
    }
}*/

/*// Fails
impl From<u32> for S<<i32 as T>::T> {
    fn from(a: u32) -> Self {
        Self {a}
    }
}*/

// Fails
impl From<u32> for S<<i32 as T>::T> {
    fn from(a: u32) -> S<<i32 as T>::T> {
        Self {a}
    }
}

fn main() {
}

Playground

The error:

  --> src/main.rs:37:9
   |
36 |     fn from(a: u32) -> S<<i32 as T>::T> {
   |                        ---------------- expected `S<u32>` because of return type
37 |         Self {a}
   |         ^^^^^^^^ expected u32, found associated type
   |
   = note: expected type `S<u32>`
              found type `S<<i32 as T>::T>`

The Observed behaviour occurs on stable 1.31.1.
I would expect this to compile, as Self is just an alias for S<<i32 as T>::T> in this case.

On the current nightly (nightly-x86_64-unknown-linux-gnu unchanged - rustc 1.33.0-nightly (b92552d55 2019-01-06)), using the same construction in a more complicated environment leads to a compiler crash:

   --> src/graph/td_cch/mod.rs:973:26
    |
973 |           let mut result = Self {
    |  __________________________^
974 | |             source_nodes,
975 | |             first_in,
976 | |             first_out,
...   |
982 | |             weights: functions,
983 | |         };
    | |_________^

error: internal compiler error: broken MIR in DefId(0/0:390 ~ proof_of_concept[a4c9]::graph[0]::td_cch[0]::{{impl}}[6]::from[0]) (_0 = move _103): bad assignment (graph::td_cch::TDCCH<plf::Point, plf::PLFunctionBuilder> = graph::td_cch::TDCCH<<plf::PLFunctionBuilder as graph::WeightFunctionBuilder>::Weight, plf::PLFunctionBuilder>): NoSolution
   --> src/graph/td_cch/mod.rs:984:9
    |
984 |         result
    |         ^^^^^^

thread 'rustc' panicked at 'no errors encountered even though `delay_span_bug` issued', src/librustc_errors/lib.rs:324:17
note: Run with `RUST_BACKTRACE=1` environment variable to display a backtrace.

error: internal compiler error: unexpected panic

note: the compiler unexpectedly panicked. this is a bug.

note: we would appreciate a bug report: https://github.com/rust-lang/rust/blob/master/CONTRIBUTING.md#bug-reports

note: rustc 1.33.0-nightly (b92552d55 2019-01-06) running on x86_64-unknown-linux-gnu

note: compiler flags: -C debuginfo=2 -C incremental -C target-cpu=native --crate-type bin

note: some of the compiler flags provided by cargo are hidden

error: Could not compile `proof_of_concept`.

I cannot disclose the full code, but here are some samples I think are relevant:
The method around the crash:

impl From<EdgeList<Point, ()>> for PLTDCCH {
    fn from(edge_list: EdgeList<Point, ()>) -> Self {
        let edges = edge_list.edges;
        let functions = edge_list.weights;

        let mut source_nodes = vec![0; edges.len()];
        let mut first_in = vec![0; edge_list.node_count as usize + 2];
        let mut first_out = vec![0; edge_list.node_count as usize + 1];
        let mut target_nodes = Vec::with_capacity(edges.len());
        let mut weight_builders = Vec::with_capacity(edges.len());

        for edge in &edges {
            first_in[edge.end as usize + 1] += 1;
            first_out[edge.start as usize] += 1;
            target_nodes.push(edge.end);
            weight_builders.push(PLFunctionBuilder::new(edge.weight_start, edge.weight_end));
        }

        first_in.prefix_sum();
        first_out.prefix_sum();

        for edge in &edges {
            let index = &mut first_in[edge.end as usize + 1];
            source_nodes[*index as usize] = edge.start;
            let weights = &functions[edge.weight_start as usize..edge.weight_end as usize];
            *index += 1;
        }

        first_in.pop();

        let mut result = Self {
            source_nodes,
            first_in,
            first_out,
            target_nodes,
            out_to_in_edges: Vec::new(),
            in_to_out_edges: Vec::new(),

            weight_builders: weight_builders,
            weights: functions,
        };
        result
    }
}

The PLTDCCH type:

#[derive(Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct TDCCH<W, WFB> {
    source_nodes: Vec<NodeId>,
    first_in: Vec<EdgeId>,
    first_out: Vec<EdgeId>,
    target_nodes: Vec<NodeId>,
    out_to_in_edges: Vec<EdgeId>,
    in_to_out_edges: Vec<EdgeId>,

    weight_builders: Vec<WFB>,
    weights: Vec<W>,
}

pub type PLTDCCH = TDCCH<<PLFunctionBuilder as WeightFunctionBuilder>::Weight, PLFunctionBuilder>;

The WeightFunctionBuilder trait:

pub trait WeightFunctionBuilder: Link<Self> + Merge<Self> + Clone + Serialize + for<'de> Deserialize<'de> {
    type Weight: Clone + Debug;
    // [...]
}

Activity

  1. changed the title [-]Returning Self in impl Trait does not resolve member types[/-] [+]Returning Self in impl Trait does not resolve member types (+ Compiler Crash)[/+] on Jan 7, 2019
  2. added
    I-ICEIssue: The compiler panicked, giving an Internal Compilation Error (ICE) ❄️
    on Jan 7, 2019
  3. added
    C-bugCategory: This is a bug.
    T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.
    on Aug 6, 2019
  4. jakubadamw commented on Sep 29, 2019

    @jakubadamw
    Contributor

    The very first snippet has been successfully compiling since 1.35.0.

    @rustbot modify labels: E-needstest

  5. added
    E-needs-testCall for participation: An issue has been fixed and does not reproduce, but no test has been added.
    on Sep 29, 2019
  6. ISibboI commented on Sep 30, 2019

    @ISibboI
    Author

    Amazing. The project this code was for actually is over, but if it helps I can try to find the old commit and check if it compiles without ICE on the current nightly. Would that be required for this issue to move forward?

  7. jakubadamw commented on Oct 1, 2019

    @jakubadamw
    Contributor

    @ISibboI, thank you for your offer but I don't think that's strictly necessary! 🙂 I added the E-needstest label, which means that for this issue to be closed a regression test will need to be added to the test suite. There are dozens of issues with the tag open¹ and every now and then contributors go over them, often adding test cases en masse.

    ¹ https://github.com/rust-lang/rust/issues?q=is%3Aopen+is%3Aissue+label%3AE-needstest

  8. added 2 commits that reference this issue on Oct 11, 2019
    ece23fc
    c2e7af5
  9. added a commit that references this issue on Oct 11, 2019
    6f6e42c
  10. added a commit that references this issue on Oct 11, 2019
    728adc4
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    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) ❄️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