Skip to content

Method resolution error #81211

@RustyYato

Description

@RustyYato
Contributor

I tried this code:

https://play.rust-lang.org/?version=nightly&mode=debug&edition=2018&gist=5ce8c7b1f8fdb39762765a7bf1576cfb

#[derive(Debug)]
pub struct Foo<T>(pub T);

impl<T> Access for T {}
pub trait Access {
    fn field<N, T, Name: 'static>(&self) -> &T {
        todo!()
    }

    fn field_mut<N, T, Name: 'static>(&mut self) -> &mut T {
        todo!()
    }

    fn take_field<N, T, Name>(self) {
        todo!()
    }
}

I expected it to compile, but it doesn't because the Debug macro expands to something like foo.field("field_name", &value), which incorrectly resolves to Access::field instead of DebugTuple::field (which is an inherent method).

error message
error[E0061]: this function takes 0 arguments but 1 argument was supplied
 --> src/lib.rs:1:10
  |
1 | #[derive(Debug)]
  |          ^^^^^ expected 0 arguments
2 | pub struct Foo<T>(pub T);
  |                   ----- supplied 1 argument
  |
note: associated function defined here
 --> src/lib.rs:6:8
  |
6 |     fn field<N, T, Name: 'static>(&self) -> &T {
  |        ^^^^^                      -----
  = note: this error originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info)

error[E0277]: the size for values of type `Self` cannot be known at compilation time
  --> src/lib.rs:14:31
   |
14 |     fn take_field<N, T, Name>(self) {
   |                               ^^^^ doesn't have a size known at compile-time
   |
   = help: unsized fn params are gated as an unstable feature
help: consider further restricting `Self`
   |
14 |     fn take_field<N, T, Name>(self) where Self: Sized {
   |                                     ^^^^^^^^^^^^^^^^^
help: function arguments must have a statically known size, borrowed types always have a known size
   |
14 |     fn take_field<N, T, Name>(&self) {
   |                               ^

error: aborting due to 2 previous errors

Some errors have detailed explanations: E0061, E0277.
For more information about an error, try `rustc --explain E0061`.
error: could not compile `playground`

To learn more, run the command again with --verbose.

Activity

added
A-macrosArea: All kinds of macros (custom derive, macro_rules!, proc macros, ..)
on Jan 20, 2021
SNCPlay42

SNCPlay42 commented on Jan 20, 2021

@SNCPlay42
Contributor

This works on stable and beta (as in, it compiles without error if you add a : Sized supertrait to Access) , but not on nightly.

@rustbot label regression-from-stable-to-nightly

added
I-prioritizeIssue: Indicates that prioritization has been requested for this issue.
on Jan 20, 2021
SNCPlay42

SNCPlay42 commented on Jan 20, 2021

@SNCPlay42
Contributor

searched nightlies: from nightly-2020-12-25 to nightly-2021-01-20
regressed nightly: nightly-2021-01-18
searched commits: from 8a65184 to 4253153
regressed commit: edeb631

bisected with cargo-bisect-rustc v0.6.0

Host triple: x86_64-unknown-linux-gnu
Reproduce with:

cargo bisect-rustc --preserve --start=2020-12-25 
SNCPlay42

SNCPlay42 commented on Jan 20, 2021

@SNCPlay42
Contributor

I think part of the problem is that f.field(...) looks for methods on &DebugTuple and sees the <DebugTuple as Access>::field(&self) before it looks for methods on &mut DebugTuple and finds DebugTuple::field(&mut self, ...). This issue with autoref/autoderef interacting poorly with inherent method's precedence over trait methods has cropped up before, e.g. in #39232 (where the compiler finds <T as BorrowMut>::borrow_mut(self) before trying autoref and finding RefCell::borrow_mut(&self)). But I don't have an explanation for why this started being a problem recently.

On another note, I notice that #[derive(Debug)] appears to be the only built-in derive that ever uses . method calls instead of UFCS with fully qualified paths, is there a reason for that? This issue could be fixed by changing #[derive(Debug)] to not use . calls, but I'm concerned that the root cause might have broken something else.

SNCPlay42

SNCPlay42 commented on Jan 20, 2021

@SNCPlay42
Contributor

Looking at the rollup that this regressed in, #80765 seems like it might be the cause.

cc @petrochenkov

self-assigned this
on Jan 20, 2021
petrochenkov

petrochenkov commented on Jan 20, 2021

@petrochenkov
Contributor

Minimized:

#[derive(Debug)]
struct Foo(u8);

pub trait Access {
    fn field(&self) {}
}

impl<T> Access for T {}

derive(Debug) should certainly use UFCS instead of method calls, regardless of #80765.

If #80765 causes other issues we'll find out sooner or later, in theory it shouldn't change any behavior unless macros 2.0 (which are unstable) or built-in macros (which we can fix) are involved.

petrochenkov

petrochenkov commented on Jan 20, 2021

@petrochenkov
Contributor

(I'll leave the fix itself to someone else, unassigning myself.)

removed their assignment
on Jan 20, 2021
added
T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.
and removed
I-prioritizeIssue: Indicates that prioritization has been requested for this issue.
on Jan 21, 2021

29 remaining items

added
S-waiting-on-reviewStatus: Awaiting review from the assignee but also interested parties.
on Feb 1, 2021
added a commit that references this issue on Feb 3, 2021
Mark-Simulacrum

Mark-Simulacrum commented on Mar 19, 2021

@Mark-Simulacrum
Member

No one ended up triaging this crater run, but I think the only possible additional breakage is in hlist - https://crater-reports.s3.amazonaws.com/pr-81211/master%23edeb631ad0cd6fdf31e2e31ec90e105d1768be28/reg/typsy-0.1.0/log.txt - and I'd guess the fix would be similar there. Ultimately this is 'just' a form of inference breakage in some sense, so I think it's OK to let this slip. It seems to affect only 2 crates in the crater run, so breakage is very minor.

added
regression-from-stable-to-stablePerformance or correctness regression from one stable version to another.
and removed on Mar 19, 2021
jackh726

jackh726 commented on Feb 3, 2022

@jackh726
Member

This is fixed on current nightly. Removing priority and marking as E-needs-test.

added
E-needs-testCall for participation: An issue has been fixed and does not reproduce, but no test has been added.
and removed
P-highHigh priority
on Feb 3, 2022
pnkfelix

pnkfelix commented on Nov 23, 2022

@pnkfelix
Member

I actually added tests, I think, in #81294. Namely:

From reviewing the comment thread here, I know there were lots of various concerns noted, and ideas for enhancements to the language documentation (I've filed rust-lang/reference#1308 for the latter). But I think the issue described here is resolved and has corresponding tests.

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

Metadata

Metadata

Labels

A-macrosArea: All kinds of macros (custom derive, macro_rules!, proc macros, ..)C-bugCategory: This is a bug.E-needs-testCall for participation: An issue has been fixed and does not reproduce, but no test has been added.T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.regression-from-stable-to-stablePerformance or correctness regression from one stable version to another.

Type

No type

Projects

No projects

Relationships

None yet

    Development

    No branches or pull requests

      Participants

      @pnkfelix@jonas-schievink@pietroalbini@Mark-Simulacrum@SNCPlay42

      Issue actions

        Method resolution error · Issue #81211 · rust-lang/rust