Skip to content

Type ambiguity not reported when it may exist? #21878

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

Closed
alexcrichton opened this issue Feb 3, 2015 · 10 comments
Closed

Type ambiguity not reported when it may exist? #21878

alexcrichton opened this issue Feb 3, 2015 · 10 comments
Labels
A-type-system Area: Type system P-medium Medium priority T-lang Relevant to the language team, which will review and decide on the PR/issue.

Comments

@alexcrichton
Copy link
Member

trait Foo {}
impl Foo for () {}
impl Foo for i32 {}

struct Error;
impl Error {
    fn foo(&self) -> ! { loop {} }
}

fn bar<T: Foo>() -> Result<T, Error> { loop {} }

fn main() {
    // what type does `_` have? is it `()` or is it `i32`?
    let _ = bar().unwrap_or_else(|e| e.foo());
}

This code compiles, but I find it somewhat surprising as I have no type annotations on _ so the compiler shouldn't know what type it is (I presume it selects one of () or i32 perhaps).

This issue is motivated by docopt/docopt.rs#89 and isn't necessarily a bug per se, but it does seem somewhat surprising so I just want to make sure it is intended.

@alexcrichton
Copy link
Member Author

cc @nikomatsakis

@pnkfelix
Copy link
Member

pnkfelix commented Feb 3, 2015

(it seems like the compiler must be deducing the type is (), since removing that impl causes the compile to fail and removing the other causes it to succeed...)

(Update:: but then again, explicitly instantiating bar to i32 via bar::<i32> within main causes the compiler to choose i32 for the type. So, it seems like it is committing early on for some reason even though it should not be, AFAICT.)

@kmcallister kmcallister changed the title Ambiguity not reported when it may exist? Type ambiguity not reported when it may exist? Feb 3, 2015
@ftxqxd
Copy link
Contributor

ftxqxd commented Feb 3, 2015

()-ness confirmed:

use std::default::Default;

trait Foo: Default { fn foo(); }
impl Foo for () { fn foo() { println!("()"); } }
impl Foo for i32 { fn foo() { println!("i32"); } }

struct Error;
impl Error {
    fn foo(&self) -> ! { loop {} }
}

fn bar<T: Foo>() -> Result<T, Error> { loop {} }

fn baz<T: Foo>(_: &T) { <T as Foo>::foo(); }

fn main() {
    let mut a = Default::default();
    |&mut:| a = bar().unwrap_or_else(|e| e.foo());
    baz(&a); // ()
}

Smaller case:

trait Foo { fn foo(&self) -> Self; }

fn foo<T: Foo>(x: T) -> T { x.foo() }

fn main() {
    // foo(x) and x.foo() should be equivalent, but aren’t

    // Bad:
    let _ = foo(loop {}); // error: the trait `Foo` is not implemented for the type `()`
    // Good:
    let _ = loop {}.foo(); // error: the type of this value must be known in this context
}

@nikomatsakis
Copy link
Contributor

This is probably because of the implicit fallback for bottom variables to ().

@pnkfelix
Copy link
Member

pnkfelix commented Feb 3, 2015

(from discussion with @nikomatsakis , this may have been injected by PR #17603 )

@pnkfelix
Copy link
Member

pnkfelix commented Feb 5, 2015

deciding what to do with this ticket is a 1.0 polish issue. (We would like to investigate consequences of removing the fallback to (), in particular)

@pnkfelix pnkfelix added the P-medium Medium priority label Feb 5, 2015
@pnkfelix pnkfelix added this to the 1.0 milestone Feb 5, 2015
@edwardw
Copy link
Contributor

edwardw commented Feb 6, 2015

It so happened that I fiddled with numeric and bot type fallbacks when trying to solve type inference issue for the new range expression. That branch reports the following error for the given testcase:

error: unable to infer enough type information about _; type annotations required [E0282]
let _ = bar().unwrap_or_else(|e| e.foo());

I'm looking into it now.

edwardw added a commit to edwardw/rust that referenced this issue Feb 6, 2015
PR rust-lang#17603 introduced bottom type fallback but did it a bit too
eagerly. This patch makes the fallback lazy so that `typeck` can run
its cause and detect as many type errors as possible with regard to
diverging types.

Closes rust-lang#21878
@nikomatsakis nikomatsakis self-assigned this Apr 2, 2015
@steveklabnik steveklabnik removed this from the 1.0 milestone May 21, 2015
@brson
Copy link
Contributor

brson commented Jul 14, 2016

Unassigning @nikomatsakis from ancient bug.

@brson brson added T-lang Relevant to the language team, which will review and decide on the PR/issue. I-nominated labels Jul 14, 2016
@brson
Copy link
Contributor

brson commented Jul 14, 2016

Nominating for close.

@nikomatsakis
Copy link
Contributor

Agreed, no bug here. TL;DR inference fallback can be surprising. Also not so relevant with !.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-type-system Area: Type system P-medium Medium priority T-lang Relevant to the language team, which will review and decide on the PR/issue.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

8 participants