Skip to content

Better std.algorithm.comparison.equal error messages - #8745

Closed
burner wants to merge 1 commit into
dlang:masterfrom
burner:equal_static_assert_message
Closed

Better std.algorithm.comparison.equal error messages#8745
burner wants to merge 1 commit into
dlang:masterfrom
burner:equal_static_assert_message

Conversation

@burner

@burner burner commented May 5, 2023

Copy link
Copy Markdown
Member

No description provided.

@dlang-bot

Copy link
Copy Markdown

Thanks for your pull request, @burner!

Bugzilla references

Your PR doesn't reference any Bugzilla issue.

If your PR contains non-trivial changes, please reference a Bugzilla issue or create a manual changelog.

Testing this PR locally

If you don't have a local development environment setup, you can use Digger to test this PR:

dub run digger -- build "master + phobos#8745"

@thewilsonator thewilsonator left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I don't think this needs a changelog, but w/e.

@PetarKirov

Copy link
Copy Markdown
Member

@CyberShadow with this change building Dustmite now fails with the following error message:

../dmd/generated/linux/release/64/dmd -I../dmd/druntime/import -I../phobos -L-L../phobos/generated/linux/release/64 -m64 -fPIC -preview=dip1000 -w -de -version=Dlang_Tools DustMite/dustmite.d DustMite/splitter.d DustMite/polyhash.d -ofgenerated/linux/64/dustmite
--
  | ../phobos/std/algorithm/comparison.d(976): Error: static assert:  All passed ranges must by InputRanges
  | DustMite/dustmite.d(521):        instantiated from here: `equal!(const(Address)*, const(Address)*)`
  | DustMite/dustmite.d(541):        instantiated from here: `addDependents!(MapResult!(__lambda10, EntityRef[]))`

Any ideas?

@burner you should be able to reproduce this locally like so:

cd $DLANG
git clone https://github.com/dlang/tools
make -C tools -f posix.mak RELEASE=1 --jobs=4

@CyberShadow

Copy link
Copy Markdown
Member

Yeah, it's picking up the wrong overload now. There is an equal declaration in dustmite.d, but now the compiler picks up the one in std.algorithm, because the constraints are gone.

I don't think this is going to work :(

Didn't we have proposals to add explanations to constraints so that we can have both cakes?

Comment on lines +976 to +979
static assert(allSatisfy!(isInputRange, Ranges), "All passed ranges "
, "must by InputRanges");
static assert(!allSatisfy!(isInfinite, Ranges), "No passed range "
, "must by an InfiniteRange");

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

s/by/be/ BTW

@thewilsonator

Copy link
Copy Markdown
Contributor

Didn't we have proposals to add explanations to constraints so that we can have both cakes?

Yes it was mine. I presume it must have been a DIP because it changed grammar, I remember I had trouble trying to implement it which I think was the reason it didn't go anywhere, will have a look for it tomorrow.

@PetarKirov PetarKirov left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Any ideas?

Never mind, I figured it out. This is the culprit:

https://github.com/dlang/tools/blob/v2.104.0-beta.1/DustMite/dustmite.d#L1489-L1500

Essentially, some of the reasons for having template constraints in the language are:

  1. To document the requirements for the template parameters
  2. To fail compilation early if the one or more given template arguments doesn't meet the requirements
  3. To help with overload resolution by filtering out the list of candidates
  4. To make the documentation and error messages more difficult to parse for muggles 😄

Dustmite is relying on 3. in order to overload the equal function, which is a valid design and not an uncommon idiom. By transforming the template constraints to static asserts, it looks like the compiler can no longer discard std.algorithm.comparison.equal as a valid candidate during overload resolution and instead starts analysing the function, and then hits the static assert which aborts the whole compilation.

This is a breaking change and until it is resolved we can't merge it.

@burner My guess is that you want to solve 4. and you're not too attached to your current solution. In that case, here are some possible alternatives:

  • Add https://github.com/atilaneves/concepts (or a similar technique) to Phobos and use it here
  • Change the language, so during overload resolution static asserts act sort of like SFINAE does in C++ - they don't abort the compilation, unless none of the overload candidates match

In the longer term, considering that template constraints haven't received any improvement in the language for at least the past 10 years (AFAIK) it maybe useful to review C++20 concepts and see if there's something we can adopt to improve the status quo in D.

@CyberShadow

CyberShadow commented May 7, 2023

Copy link
Copy Markdown
Member

Why can't we just do

    if (/// More than one range is required
        rs.length > 1 &&
        /// All passed ranges must be input ranges
        allSatisfy!(isInputRange, Ranges) &&
        /// None of the passed ranges may be an `InfiniteRange`
        !allSatisfy!(isInfinite, Ranges) &&
        /// The first and second range's elements must be comparable with `binaryFun!pred`
        is(typeof(binaryFun!pred(rs[0].front, rs[1].front))) &&
        /// All successive range's elements must be comparable with`binaryFun!pred`
        (rs.length == 2 || is(typeof(equal!pred(rs[1 .. $])) == bool)))

It is syntactically unambiguous, doesn't require any language changes, and doesn't need a DIP (because it doesn't change grammar and only affects compiler output). I.e. just print any doc node attached to the expression that failed.

@burner

burner commented May 24, 2023

Copy link
Copy Markdown
Member Author
  1. To make the documentation and error messages more difficult to parse for muggles smile

That's the point of these PR's

Closing this for now

@burner burner closed this May 24, 2023
@burner

burner commented May 24, 2023

Copy link
Copy Markdown
Member Author

thank you for all the review work

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.

5 participants