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

Type inference regression in recent nightly #39984

Closed
Yamakaky opened this Issue Feb 20, 2017 · 17 comments

Comments

Projects
None yet
10 participants
@Yamakaky
Copy link
Contributor

Yamakaky commented Feb 20, 2017

https://play.rust-lang.org/?gist=188e52dc2ba423a8f78c6e381f278cf1&version=nightly&backtrace=1

source (copied by @pnkfelix from gist linked above):

fn main() {}

fn t() -> Result<(), String> {
    return Err("".into());
    Ok(())
}

Maybe it's because Ok(()) is unreachable?

See rust-lang-nursery/error-chain#132 for the original report.

The breakage happens between nightlies 668864d 2017-02-16 and 536a900 2017-02-17.

@golddranks

This comment has been minimized.

Copy link
Contributor

golddranks commented Feb 20, 2017

Seems similar to #39808, in the sense that there is some unreachable code that apparently was used to help inference before?

@TimNN

This comment has been minimized.

Copy link
Contributor

TimNN commented Feb 20, 2017

Diff between the nightly-2017-02-17 and nightly-2016-02-18.

I expect this was caused by #39485 (and thus is expected breakage?).

@Yamakaky

This comment has been minimized.

Copy link
Contributor Author

Yamakaky commented Feb 20, 2017

Seems like it.

@golddranks

This comment has been minimized.

Copy link
Contributor

golddranks commented Feb 22, 2017

Is it written somewhere what inference breaking was within range of "expected" and what is not? It started to bother me: the problem doesn't seem to be that some type info isn't available because it would be inferred from dead code. After all, the function signature here is not dead code, and everything's inferrable from there. The problem seems to be that the type of the dead expression isn't fully inferred from the non-dead code. But should the type of E matter since the code path is dead? And if it does, shouldn't it be fully inferrable from the function signature?

@Yamakaky

This comment has been minimized.

Copy link
Contributor Author

Yamakaky commented Feb 22, 2017

Exactly. BTW, it's not convenient if dead code doesn't typecheck. It happens to me a lot when I'm writing new code, along with unused variables for example.

@dhardy

This comment has been minimized.

Copy link
Contributor

dhardy commented Feb 26, 2017

As @nikomatsakis points out, existing code could be broken by doing proper type-checking in dead code.
However, this code would already have carried a dead_code warning (same as this case).

Ironic that disabling type checking of dead-code is actually causing type errors (this issue).

I stand by my reasoning that dead code should be type checked (even if it breaks some existing code), however it would also make sense if the dead code warning was reported before errors in the dead code.

@golddranks

This comment has been minimized.

Copy link
Contributor

golddranks commented Feb 27, 2017

So let me check: the recent changes disabled type-checking of dead code? And nevertheless it complains that the type of E in the dead code isn't known?

@dhardy

This comment has been minimized.

Copy link
Contributor

dhardy commented Feb 27, 2017

I'm not very familiar with how the compiler works, but I suspect the demand_coerce function also causes some type inference to happen, and without that some other part of the code complains that a type parameter never got deduced.
https://github.com/rust-lang/rust/pull/39485/files#diff-1d1b0d29a2e8da97c6bfb6e364d920c7L4165

I'd rather someone who actually understands the compiler answer that question though...

@nikomatsakis

This comment has been minimized.

Copy link
Contributor

nikomatsakis commented Mar 2, 2017

Hmm. I think what we're doing in #39485 isn't quite right. I'm not sure the best answer here. Before #39485, we mostly but not completely ignored the types that arose from dead code. I'm nominating this for discussion in compiler team meeting; I think we have to address this regression in some way.

@nikomatsakis

This comment has been minimized.

Copy link
Contributor

nikomatsakis commented Mar 2, 2017

triage: P-high

@tbu-

This comment has been minimized.

Copy link
Contributor

tbu- commented Mar 11, 2017

One of my crates is also experiencing this, with generated code similar to this (example heavily reduced):

pub fn encode() -> Result<(), ()> {
    try!(unimplemented!());
    Ok(())
}

Previously, this resulted in a dead code warning,

warning: unreachable expression, #[warn(unreachable_code)] on by default
 --> a.rs:3:5
  |
3 |     Ok(())
  |     ^^^^^^

but now, it errors out:

error[E0282]: type annotations needed
 --> a.rs:3:5
  |
3 |     Ok(())
  |     ^^ cannot infer type for `E`

error: aborting due to previous error

This is although the type for E is entirely clear, it should be () in this case, because the function has a result of Result<(), ()>.

@tbu-

This comment has been minimized.

Copy link
Contributor

tbu- commented Mar 11, 2017

I think this might be the same issue as #39808, although that one is tagged regression-from-stable-to-stable.

@arielb1

This comment has been minimized.

Copy link
Contributor

arielb1 commented Mar 16, 2017

1.17 is now beta.

@Yamakaky

This comment has been minimized.

Copy link
Contributor Author

Yamakaky commented Mar 16, 2017

So, is this issue considered a regression or a wontfix?

nikomatsakis added a commit to nikomatsakis/rust that referenced this issue Mar 17, 2017

nikomatsakis added a commit to nikomatsakis/rust that referenced this issue Mar 17, 2017

nikomatsakis added a commit to nikomatsakis/rust that referenced this issue Mar 18, 2017

nikomatsakis added a commit to nikomatsakis/rust that referenced this issue Mar 18, 2017

nikomatsakis added a commit to nikomatsakis/rust that referenced this issue Mar 21, 2017

nikomatsakis added a commit to nikomatsakis/rust that referenced this issue Mar 22, 2017

nikomatsakis added a commit to nikomatsakis/rust that referenced this issue Mar 22, 2017

@brson

This comment has been minimized.

Copy link
Contributor

brson commented Mar 23, 2017

Fix is enqueued.

@sunjay

This comment has been minimized.

Copy link
Member

sunjay commented Mar 23, 2017

@brson Does this also fix my issue here? #40662

If so, you can close that issue as a duplicate.

@nikomatsakis

This comment has been minimized.

Copy link
Contributor

nikomatsakis commented Mar 23, 2017

@sunjay done

nikomatsakis added a commit to nikomatsakis/rust that referenced this issue Mar 24, 2017

nikomatsakis added a commit to nikomatsakis/rust that referenced this issue Mar 24, 2017

nikomatsakis added a commit to nikomatsakis/rust that referenced this issue Mar 24, 2017

@bors bors closed this in 0f1eb8a Mar 25, 2017

bors added a commit that referenced this issue Mar 26, 2017

Auto merge of #40224 - nikomatsakis:issue-39808, r=eddyb
change the strategy for diverging types

The new strategy is as follows. First, the `!` type is assigned
in two cases:

- a block with a diverging statement and no tail expression (e.g.,
  `{return;}`);
- any expression with the type `!` is considered diverging.

Second, we track when we are in a diverging state, and we permit a value
of any type to be coerced **into** `!` if the expression that produced
it is diverging. This means that `fn foo() -> ! { panic!(); 22 }`
type-checks, even though the block has a type of `usize`.

Finally, coercions **from** the `!` type to any other are always
permitted.

Fixes #39808.
Fixes #39984.

bors added a commit that referenced this issue Mar 27, 2017

Auto merge of #40224 - nikomatsakis:issue-39808, r=eddyb
change the strategy for diverging types

The new strategy is as follows. First, the `!` type is assigned
in two cases:

- a block with a diverging statement and no tail expression (e.g.,
  `{return;}`);
- any expression with the type `!` is considered diverging.

Second, we track when we are in a diverging state, and we permit a value
of any type to be coerced **into** `!` if the expression that produced
it is diverging. This means that `fn foo() -> ! { panic!(); 22 }`
type-checks, even though the block has a type of `usize`.

Finally, coercions **from** the `!` type to any other are always
permitted.

Fixes #39808.
Fixes #39984.

bors added a commit that referenced this issue Mar 27, 2017

Auto merge of #40224 - nikomatsakis:issue-39808, r=eddyb
change the strategy for diverging types

The new strategy is as follows. First, the `!` type is assigned
in two cases:

- a block with a diverging statement and no tail expression (e.g.,
  `{return;}`);
- any expression with the type `!` is considered diverging.

Second, we track when we are in a diverging state, and we permit a value
of any type to be coerced **into** `!` if the expression that produced
it is diverging. This means that `fn foo() -> ! { panic!(); 22 }`
type-checks, even though the block has a type of `usize`.

Finally, coercions **from** the `!` type to any other are always
permitted.

Fixes #39808.
Fixes #39984.

frewsxcv added a commit to frewsxcv/rust that referenced this issue Mar 29, 2017

Rollup merge of rust-lang#40224 - nikomatsakis:issue-39808, r=eddyb
change the strategy for diverging types

The new strategy is as follows. First, the `!` type is assigned
in two cases:

- a block with a diverging statement and no tail expression (e.g.,
  `{return;}`);
- any expression with the type `!` is considered diverging.

Second, we track when we are in a diverging state, and we permit a value
of any type to be coerced **into** `!` if the expression that produced
it is diverging. This means that `fn foo() -> ! { panic!(); 22 }`
type-checks, even though the block has a type of `usize`.

Finally, coercions **from** the `!` type to any other are always
permitted.

Fixes rust-lang#39808.
Fixes rust-lang#39984.

bors added a commit that referenced this issue Mar 30, 2017

Auto merge of #40224 - nikomatsakis:issue-39808, r=eddyb
change the strategy for diverging types

The new strategy is as follows. First, the `!` type is assigned
in two cases:

- a block with a diverging statement and no tail expression (e.g.,
  `{return;}`);
- any expression with the type `!` is considered diverging.

Second, we track when we are in a diverging state, and we permit a value
of any type to be coerced **into** `!` if the expression that produced
it is diverging. This means that `fn foo() -> ! { panic!(); 22 }`
type-checks, even though the block has a type of `usize`.

Finally, coercions **from** the `!` type to any other are always
permitted.

Fixes #39808.
Fixes #39984.

nikomatsakis added a commit to nikomatsakis/rust that referenced this issue Mar 31, 2017

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.