Skip to content

Conversation

@Marenz
Copy link
Contributor

@Marenz Marenz commented Feb 27, 2020

fixes #8373

@erak
Copy link
Contributor

erak commented Feb 28, 2020

Looks good already!

Copy link
Collaborator

@ekpyron ekpyron left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we warn about this, then I think we should also adjust the order in the suggestion "Function needs to specify overridden contracts [contracts].". Currently that list will ultimately just be alphabetical.

@Marenz
Copy link
Contributor Author

Marenz commented Mar 2, 2020

that's a good point @ekpyron

@chriseth suggested to use linearizedBaseContracts instead of baseContracts(), however, the following test case creates some issues with that:

for this example, the reversed linearized contracts mismatch

    contract I {
      function f() external virtual {}
    }
    contract A is I {
      function f() external virtual override {}
    }
    contract B is I {}
    contract C is A, B {
      function f() external override(A, I) {}
    }

the reversed list (filtered by the contracts specified in override) is I, A

@ekpyron
Copy link
Collaborator

ekpyron commented Mar 2, 2020

You should check in what order super.f() calls the bases in this case - that's probably the order given by linearizedBaseContracts and that's probably the order we should require the mentions to have. I.e. linearizedBaseContracts is the "correct" order...

@ekpyron
Copy link
Collaborator

ekpyron commented Mar 2, 2020

(the question how super behaves is the core of #8354 which - if I understand correctly - led to the decision to warn about this, so I'd say the required order that's not warned about should be precisely the order of super calls, right?)

@Marenz
Copy link
Contributor Author

Marenz commented Mar 2, 2020

Alright, so it was just my intuition that thought this is wrong then.

@ekpyron
Copy link
Collaborator

ekpyron commented Mar 2, 2020

Alright, so it was just my intuition that thought this is wrong then.

Better actually check what super does - I always found super to be rather weird myself, so I'd need to think about what it really does in this particular case myself :-).

@ekpyron
Copy link
Collaborator

ekpyron commented Mar 2, 2020

FYI I'm myself not actually sure about requiring any particular order for this at all :-). IIUC we still can't guarantee that super.f() will actually call the function in the first mentioned contract, if you inherit from the whole thing again in a weird way...

@Marenz
Copy link
Contributor Author

Marenz commented Mar 2, 2020

Well, one motivation for this was that people thought the order in override(a,b) implies the order of inheritance. If we just require the same as specified at least that particular misunderstanding is eliminated

@Marenz Marenz force-pushed the warn-inheritance-order branch 2 times, most recently from 086c589 to b71564d Compare March 2, 2020 13:45
@Marenz
Copy link
Contributor Author

Marenz commented Mar 2, 2020

updated to use linearizedBaseContracts

@Marenz Marenz force-pushed the warn-inheritance-order branch from 330e866 to b2b45cc Compare March 2, 2020 17:36
Copy link
Collaborator

@ekpyron ekpyron left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some suggestions.

Comment on lines +827 to +832
for (size_t i = _item.contract().annotation().linearizedBaseContracts.size() - 1; i > 0; i--)
{
auto contract = _item.contract().annotation().linearizedBaseContracts[i];
if (missingContracts.count(contract))
sortedMissingContracts.emplace_back(contract);
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
for (size_t i = _item.contract().annotation().linearizedBaseContracts.size() - 1; i > 0; i--)
{
auto contract = _item.contract().annotation().linearizedBaseContracts[i];
if (missingContracts.count(contract))
sortedMissingContracts.emplace_back(contract);
}
for (
auto const* contract: _item.contract().annotation().linearizedBaseContracts |
boost::adaptor::filter([](auto const* contract) -> bool { return missingContracts.count(contract); }
)
sortedMissingContracts.emplace_back(contract);

?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Your suggestion is no longer reversing the linearized list?

}
}
}
else if (specifiedContracts.size() > 1)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wouldn't this be much easier, if you did it after you checked that the specified contracts match the expected contracts (and only if they match)?

Then you could just do something like this, couldn't you?

auto overrideIterator = _item.overrides()->overrides().begin();
for (auto const* expected: _item.contract().annotation.linearizedBaseContracts | boost::adaptor::filter([](auto const* base) -> bool { return expectedContracts.count(base); })
  if ((overrideIterator++)->annotation().referencedDeclaration != expected)
  {
     // warn
     break;
  }

@Marenz
Copy link
Contributor Author

Marenz commented Mar 9, 2020

Closing this for now as an in-office discussion suggests we're unsure about this feature

@Marenz Marenz closed this Mar 9, 2020
@cameel cameel changed the title Warn if override specifier list oder differst from inheritance order Warn if override specifier list order differs from inheritance order Jan 27, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Warn if order in override specifier is different than in inheritance list

4 participants