-
Notifications
You must be signed in to change notification settings - Fork 12.7k
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
Make it a bit easier to debug TyKind::Error errors #70245
Conversation
cc @rust-lang/compiler Let's get some visibility on this! The other idea in this area is that we can make |
This is a really nice idea 👍 |
@eddyb In order for that to be meaningful, we would need to not intern |
I've pushed a rough prototype (not compiling yet, but I need to go to bed) with both of @eddyb's suggestions above. It's not clear that we need both, and between the two, I think prevention is better than detection, but I guess both can't hurt... |
The job Click to expand the log.
I'm a bot! I can only do what humans tell me to, so if this was not helpful or you have suggestions for improvements, please ping or otherwise contact |
I would call variables Btw there an issue for the |
☔ The latest upstream changes (presumably #70275) made this pull request unmergeable. Please resolve the merge conflicts. |
Which variable? I'm already using the name proof.
Do you mean the methods of
I had created a new |
Ugh, I accidentally a word. I meant to say I would call variables
Oh, is this about the "level" thing? Can we make that a const generic parameter of the Ideally calling
Ah, whereas I would start by changing |
Hmm, I think I would rather not add a generic argument to all uses of Another idea is to have something like: enum ErrorReported {
/// Emitted something with level < error
Emitted,
/// Emitted something with that will fail compilation
EmittedWithProof(ErrorProof),
}
impl DiagnosticBuilder {
pub fn emit(...) -> ErrorReported { ... }
} I think this would accomodate both the current use cases and the ones where we want a proof. |
|
Hmm, actually, a type parameter would make sense, whereas const generics would be hard to use. Only lints need variable level. And most error reporting code doesn't name |
@eddyb so let me see if I understand correctly. Are you thinking of something like this: // `true` if fails compilation
struct DiagnosticBuilder<const IS_ERROR: bool> {...}
impl DiagnosticBuilder<true> {
pub fn emit() {
// like today
}
}
impl DiagnosticBuilder<false> {
pub fn emit() -> Proof { ... } // returns proof
}
impl DiagnosticBuild<IS_ERROR> {
// all the others remain generic
} |
I played around with this a bit yesterday, and I feel like I ran into cases where |
Forget I ever mentioned What I have in mind most recently is this: // Could even make this not constructible without calling
// a method that registers something similar to delay_bug.
// But that's overkill for now.
pub struct AlwaysError;
mod sealed {
use super::{AlwaysError, ErrorReported, Level};
pub trait LevelTrait {
type Emitted;
fn emit(self) -> (Level, Self::Emitted);
}
impl LevelTrait for Level {
type Emitted = ();
fn emit(self) -> (Level, Self::Emitted) {
(self, ())
}
}
impl LevelTrait for AlwaysError {
type Emitted = ErrorReported;
fn emit(self) -> (Level, Self::Emitted) {
(Level::Error, ErrorReported { private: () })
}
}
}
struct DiagnosticBuilder<L> {
level: L,
...
}
impl<L: sealed::LevelTrait> DiagnosticBuilder<L> {
pub fn emit(self) -> L::Emitted {
...
let (level, emitted) = self.level.emit();
...
emitted
}
} |
Hmm... I could probably do something like that... |
How would one deal with cancellation of errors? Ideally one would need to return the proof to cancel an error. |
Hmm... ok this is getting very messy. There are too many weird edge cases. I still prefer the enum approach of #70245 (comment) . (Also, I think we can just forget about cancellation for now. Anyway, we can do something like track_callers above to help debug weird cases where an error is cancelled.) |
@eddyb after trying both, the enum approach is way easier to implement, largely because it doesn't clash with cancellation or lint levels; it just seems to be easier to do at runtime than compile time. Also, I'm not sure what to do about a bunch of uses of |
I still think it's a waste of time to try to change As for error cancellation, we should try to avoid that as much as possible.
Ah, wait, inference contexts have snapshots, so you can try something and not actually report any errors. This might mean |
AFAICT, a Ok, for now, I'm going to pursue the |
Make all uses of ty::Error delay a span bug r? @eddyb A second attempt at rust-lang#70245 resolves rust-lang#70866
Make all uses of ty::Error delay a span bug r? @eddyb A second attempt at rust-lang#70245 resolves rust-lang#70866
Make all uses of ty::Error delay a span bug r? @eddyb A second attempt at rust-lang#70245 resolves rust-lang#70866
r? @eddyb
Not sure how good of an idea this is... but it occurred to me that we can do more to enforce the invariant that
TyKind::Error
should only happen if errors are going to be emitted. We could also use the function to due a delay bug for good measure.