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

error causes subsequent spurious error about literal cast #35772

Closed
durka opened this Issue Aug 18, 2016 · 7 comments

Comments

Projects
None yet
5 participants
@durka
Contributor

durka commented Aug 18, 2016

See this code:

fn main() {
    error;
    1 as f32;
}

It has an error on the second line, obviously. But it also prints an error about the third line (illegal cast). But the cast is perfectly legal and removing the first error also "fixes" the second one.

@durka

This comment has been minimized.

Contributor

durka commented Aug 18, 2016

I suspect this somehow has to do with the constant evaluator. @oli-obk?

@oli-obk

This comment has been minimized.

Contributor

oli-obk commented Aug 18, 2016

nope, it's not const eval, it's typeck.

beta/nightly even produce "non-scalar cast: {integer} as f32", so it's not something weird like the error; turning the 1 into another type.

@durka

This comment has been minimized.

Contributor

durka commented Aug 18, 2016

But it is a scalar cast. Maybe the first error leaves some kind of boolean flag around that "there was an error", and the casting code picks up on it?

@Detegr

This comment has been minimized.

Contributor

Detegr commented Aug 18, 2016

I've investigated this a bit. Apologies if I've understood something wrong, I'm still a total compiler noob :)

Looks like the reason this happens is when there's an error before the cast, the type inference of 1 differs from the case when there's just the cast. These types are checked in src/librustc_typeck/check/cast.rs in a function called do_check.

In the working version self.expr_ty.sty looks like this (from rust-gdb):

TyS = {sty = TyInt = {I32}, flags = Cell<rustc::ty::TypeFlags> = {
  value = UnsafeCell<rustc::ty::TypeFlags> = {value = TypeFlags = {
    bits = 0}}}, region_depth = 0}

where in the version with the error it looks like this:

TyS = {sty = TyInfer = {IntVar = {IntVid = {index = 0}}},
  flags = Cell<rustc::ty::TypeFlags> = {
    value = UnsafeCell<rustc::ty::TypeFlags> = {value = TypeFlags = {
      bits = 3076}}}, region_depth = 0}

If do_check results in an error (it does if sty is TyInfer, see from_ty) the compiler reports the cast error.

Why the types are resolved differently I have no idea.

EDIT: I dug around a bit more and I think I found the root cause. The reason was what @durka was anticipating, default_type_parameters() treats all uninstantiated type variables as TyError if an error had been discovered earlier. This causes do_check to fail and the code handling the failure does not check if is_tainted_by_errors() is true or not but just outputs the error anyway.

Detegr added a commit to Detegr/rust that referenced this issue Aug 22, 2016

Do not report cast errors if an error had been previously detected
If `InferCtxt` is tainted by errors, the result of `CastCheck::do_check`
may fail even though the cast is valid. We don't want any wrong error
messages in those cases so checking `is_tainted_by_errors()` before
reporting cast errors.

Fixes rust-lang#35772
@durka

This comment has been minimized.

Contributor

durka commented Aug 22, 2016

Nice detective work @Detegr.

@Detegr

This comment has been minimized.

Contributor

Detegr commented Aug 22, 2016

Thanks, however my initial solution to the problem was too shortsighted and caused more harm than good. Anyway this has been a fun dive to the compiler internals so I'll keep trying.

@estebank

This comment has been minimized.

Contributor

estebank commented Jan 16, 2018

@estebank estebank closed this Jan 16, 2018

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment