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

Struct with an error magically becomes a function, causing misleading diagnostics (arc is a function, perhaps you wish to call it) #82323

Closed
kornelski opened this issue Feb 20, 2021 · 5 comments · Fixed by #106302
Labels
A-diagnostics Area: Messages for errors, warnings, and lints C-bug Category: This is a bug.

Comments

@kornelski
Copy link
Contributor

fn main() {
    let arc = std::sync::Arc::new(oops);
    arc.clone();
}

It correctly diagnoses that oops is undeclared. It should stop after this error, and not display any further errors related to the incomplete arc object.

But it continues and displays a second error, which doesn't make any sense and has a nonsense suggestion:

error[E0599]: no method named `clone` found for struct `Arc<_>` in the current scope
 --> src/main.rs:5:9
  |
5 |     arc.clone();
  |         ^^^^^ method not found in `Arc<_>`
  |
  = note: `arc` is a function, perhaps you wish to call it

Meta

rustc --version --verbose:

rustc 1.52.0-nightly (8e54a2113 2021-02-13)
binary: rustc
commit-hash: 8e54a21139ae96a2aca3129100b057662e2799b9
commit-date: 2021-02-13
host: x86_64-apple-darwin
release: 1.52.0-nightly
LLVM version: 11.0.1
@kornelski kornelski added the C-bug Category: This is a bug. label Feb 20, 2021
@jonas-schievink jonas-schievink added the A-diagnostics Area: Messages for errors, warnings, and lints label Feb 20, 2021
@osa1
Copy link
Contributor

osa1 commented Feb 22, 2021

I briefly looked into this issue. I guess there could be many ways of fixing this, but something strange I discovered as I debug this is this function

https://github.com/rust-lang/rust/blob/8535ec3ccea2530c70927966450e066c7a92a3fc/compiler/rustc_typeck/src/check/method/suggest.rs#L32-L69

returns true for Arc<_>, which is represented as an ADT (TyKind::ADT). So the last line (predicate_may_hold(FnOnce)) returns true. I think this doesn't make sense, as Arc doesn't implement FnOnce. Fixing this would fix this issue.

There could be other ways of fixing this as well, however the function that generates this suggestion, report_method_errors, is 805 lines long, and have no documentation other than a few inline comments.

@notriddle
Copy link
Contributor

I think this doesn't make sense, as Arc doesn't implement FnOnce

If it autoderefs to something that impl Fn, then the suggestion would actually make sense. And it’s a free type variable, so it might.

I think the mistake here is using predicate_may_hold, which returns true on ambiguous results, instead of predicate_must_hold_modulo_regions, which should return false.

@osa1
Copy link
Contributor

osa1 commented Feb 22, 2021

Hm, you're right. For example, this works:

use std::sync::Arc;

fn f() {
    println!("f called");
}

fn main() {
    let f = Arc::new(f);
    f();
}

I agree that it shouldn't return true when in case of an ambiguity/unknown type.

@osa1
Copy link
Contributor

osa1 commented Feb 22, 2021

Confirmed that using predicate_must_hold_modulo_regions "fixes" the incorrect suggestion.

Of course this doesn't fix the nonsensical error message, just removes the invalid suggestion.

@Kestrer
Copy link
Contributor

Kestrer commented Feb 13, 2022

I encountered another variant of what seems to be this bad diagnostic recently, this time caused by a missing type parameter in an impl block:

struct Struct<T>(T);
impl Struct<T>
where
    T: Copy,
{
    fn method(v: Vec<u8>) { v.len(); }
}

Produces (as well as a helpful diagnostic) this diagnostic:

error[E0282]: type annotations needed
--> src/lib.rs:6:31
  |
6 |     fn method(v: Vec<u8>) { v.len(); }
  |                               ^^^ cannot infer type
  |
  = note: type must be known at this point

error[E0599]: no method named `len` found for struct `Vec<u8>` in the current scope
--> src/lib.rs:6:31
  |
6 |     fn method(v: Vec<u8>) { v.len(); }
  |                               ^^^ private field, not a method
  |
  = note: `v` is a function, perhaps you wish to call it

Playground here. I'm not sure whether it's worth filing a new issue for this, but if it is appropriate please do.

notriddle added a commit to notriddle/rust that referenced this issue Feb 16, 2022
matthiaskrgr added a commit to matthiaskrgr/rust that referenced this issue Feb 16, 2022
…es-a-function, r=petrochenkov

Do not suggest "is a function" for free variables

Part of rust-lang#82323
matthiaskrgr added a commit to matthiaskrgr/rust that referenced this issue Feb 17, 2022
…es-a-function, r=petrochenkov

Do not suggest "is a function" for free variables

Part of rust-lang#82323
Noratrieb added a commit to Noratrieb/rust that referenced this issue Dec 31, 2022
…r, r=estebank

Suppress errors due to TypeError not coercing with inference variables

Fixes rust-lang#75331
Fixes rust-lang#68507
Fixes rust-lang#82323

cc `@estebank`
@bors bors closed this as completed in 726bbfc Dec 31, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-diagnostics Area: Messages for errors, warnings, and lints C-bug Category: This is a bug.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants