Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

IllegalAccessError when using Raise #3235

Closed
CLOVIS-AI opened this issue Oct 21, 2023 · 4 comments · Fixed by #3316
Closed

IllegalAccessError when using Raise #3235

CLOVIS-AI opened this issue Oct 21, 2023 · 4 comments · Fixed by #3316

Comments

@CLOVIS-AI
Copy link
Contributor

Arrow version: 1.2.1

I'm trying to integrate Raise into my test library, Prepared. Since raising usually represents an error, I want to be able to declare that a test fails if an error is raised. To help with debugging, I'd like to enable tracing in those cases (since this is only for testing, I don't mind the performance implications).

I want to be able to declare something like:

test("Some test") {
    failOnRaise {
        raise(5)
    }
}

For now, here's the implementation I have:

@ExperimentalTraceApi
inline fun <Failure, Success> failOnRaise(block: Raise<Failure>.() -> Success): Success {
	val result = either {
		traced(block) { trace, error ->
			throw AssertionError("An operation raised $error\n${trace.stackTraceToString()}")
				.apply {
					for (suppressed in trace.suppressedExceptions())
						addSuppressed(suppressed)
				}
		}
	}

	check(result is Either.Right) { "Impossible situation: we throw an error when the passed block raises, but it still gave us a failed either: $result" }
	return result.value
}

However, when I execute it, I get:

java.lang.AssertionError: Expected exception java.lang.AssertionError but a IllegalAccessError was thrown instead.

The stack trace is unhelpful (it doesn't go further than the test function).

Do you know what could cause this?


The entire code is available here.

As an aside, would it be possible to expose the underlying exception in traced? It would be easier to simply mark it as the cause of the AssertionError.

@nomisRev
Copy link
Member

Hey @CLOVIS-AI,

Your code doesn't compile for me 🤯 Removing () from suppressedExceptions, and works for me

for (suppressed in trace.suppressedExceptions)
  addSuppressed(suppressed)

But I think it's actually related somehow to how suppressedExceptions works, it uses reflection to get access to getSuppressed. https://github.com/JetBrains/kotlin/blob/f98451e38169a833f60b87618db4602133e02cf2/libraries/stdlib/jvm/src/kotlin/internal/PlatformImplementations.kt#L37
Calling Method::invoke from java.lang.reflect throws IllegalAccessError .

@CLOVIS-AI
Copy link
Contributor Author

I don't understand it, then. The Arrow documentation does say it is a function… It doesn't compile on my side if I try to access it any other way.

kyay10 added a commit to kyay10/arrow that referenced this issue Dec 8, 2023
@kyay10 kyay10 mentioned this issue Dec 8, 2023
kyay10 added a commit to kyay10/arrow that referenced this issue Dec 8, 2023
@kyay10
Copy link
Collaborator

kyay10 commented Dec 8, 2023

Debugging, I think it has something to do with RaiseCancellationException being private, yet being used inside the inline method traced. I'm surprised that the compiler even allowed that. I think Kotlin doesn't allow that occurring with methods, but lets it happen with types, which results in client code trying to catch an exception of type RaiseCancellationException. I'm not sure how to reproduce this, but the fix is very simple. Testing locally, it seems to work. See #3316

serras added a commit that referenced this issue Dec 19, 2023
Co-authored-by: Alejandro Serrano <trupill@gmail.com>
@CLOVIS-AI
Copy link
Contributor Author

Can confirm this is fixed for me with Arrow 1.2.3.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants