Skip to content

Trait implementation for reference to trait causes stack overflow at runtime #15966

Closed
@devyn

Description

@devyn

The following code produces a stack overflow at runtime, only when optimizations are turned off.

The behavior that occurs once optimizations are turned on is odd, too: "called Option::unwrap() on a None value" even though I don't see any way a None could possibly be produced, but presumably LLVM eliminates the recursive call to testcase::&'a T.Tag::to_tag somehow and the stack overflow doesn't occur anymore.

use std::sync::Arc;

pub trait Tag {
  fn to_tag(&self) -> Option<Arc<String>>;
}

impl Tag for Arc<String> {
  fn to_tag(&self) -> Option<Arc<String>> {
    Some(self.clone())
  }
}

impl Tag for String {
  fn to_tag(&self) -> Option<Arc<String>> {
    Some(Arc::new(self.clone()))
  }
}

impl<'a> Tag for &'a str {
  fn to_tag(&self) -> Option<Arc<String>> {
    Some(Arc::new(self.to_string()))
  }
}

impl<'a, T: Tag> Tag for &'a T {
  fn to_tag(&self) -> Option<Arc<String>> {
    self.to_tag()
  }
}

impl<T: Tag> Tag for Option<T> {
  fn to_tag(&self) -> Option<Arc<String>> {
    self.as_ref().and_then(|t| t.to_tag())
  }
}

fn main() {
  let tag = "hello".to_tag();

  println!("{}", *tag.as_ref().to_tag().unwrap())
}

Snippet of gdb backtrace:

#0  0x000000000045561a in rust_stack_exhausted ()
#1  0x00000000004050e1 in __morestack ()
#2  0x0000000000404f61 in testcase::&'a T.Tag::to_tag (self=0x7fffffffc810) at testcase.rs:27
#3  0x0000000000404f61 in testcase::&'a T.Tag::to_tag (self=0x7fffffffc810) at testcase.rs:27
#4  0x0000000000404f61 in testcase::&'a T.Tag::to_tag (self=0x7fffffffc810) at testcase.rs:27
...

Obviously this can just be fixed by correcting that particular implementation to:

impl<'a, T: Tag> Tag for &'a T {
  fn to_tag(&self) -> Option<Arc<String>> {
    (**self).to_tag()
  }
}

but I feel like the compiler should be able to detect this and either resolve the cycle or throw an error.

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-lintsArea: Lints (warnings about flaws in source code) such as unused_mut.E-mentorCall for participation: This issue has a mentor. Use #t-compiler/help on Zulip for discussion.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions