Skip to content

fix Issue 15862 - allocating storage in pure functions should not res…#6197

Merged
MartinNowak merged 2 commits intodlang:masterfrom
WalterBright:fix15862
Oct 23, 2016
Merged

fix Issue 15862 - allocating storage in pure functions should not res…#6197
MartinNowak merged 2 commits intodlang:masterfrom
WalterBright:fix15862

Conversation

@WalterBright
Copy link
Member

…ult in caching return values of them

@dlang-bot
Copy link
Contributor

Fix Bugzilla Description
15862 Functions that return types with mutable indirections should be weakly pure, not strongly pure

Copy link
Member

@MetaLang MetaLang left a comment

Choose a reason for hiding this comment

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

Why the weird style of assert?

int* p1 = p();
int* p2 = p();

if (p1 is p2) assert(0);
Copy link
Member

Choose a reason for hiding this comment

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

assert(p1 is p2)?

Copy link
Member

Choose a reason for hiding this comment

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

To get those asserts to be ran in release.
It's trying to solve a common problem with assert: https://forum.dlang.org/thread/ed318016-16e9-965f-4d66-c0c94dd2564c@sociomantic.com
I'd say lets revisit when we fix said issue.

Copy link
Member

Choose a reason for hiding this comment

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

Ah, I see. Thanks.

Copy link
Member

@PetarKirov PetarKirov Oct 15, 2016

Choose a reason for hiding this comment

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

@MetaLang I think you meant assert(p1 !is p2).
I would use p1 !is p2 || assert(0) (and IIRC @andralex too according to TDPL).

Copy link
Member

@PetarKirov PetarKirov left a comment

Choose a reason for hiding this comment

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

The implementation looks ok (minus one small typo), and it's a step in the right direction (fixes a bug), but I'm worried that this change implies that non-@nogc memory management schemes cannot be pure (because the result of @nogc void* allocate(size_t size) could be cached/reused) which seriously limits the usability of std.experimental.allocators in pure code.

Instead of using @nogc as a proxy for determining if the result can be cached, I thought we mostly agreed to use the mutability of the return type - immutable return type -> can cache, non-immutable -> caching is not safe (e.g. caller of an() could modify the returned array, in which case using a cached result would simply yield wrong results; N.B. it doesn't matter, that an() returns null, in general the body may not be available to the compiler, and only the function signature should be relied upon).

Pinging @klickverbot as our safe-ty and purity guru :P

src/e2ir.c Outdated
retmethod != RETstack &&
!global.params.useAssert && global.params.optimize);

/* Don't common subexpression functions that many allocate memory
Copy link
Member

Choose a reason for hiding this comment

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

many -> may

@dnadlinger
Copy link
Contributor

@ZombineDev: See the discussion on Bugzilla. It seems like the right choice is not to trigger referential transparency-based optimisations for return types with mutable indirections in general, rather than basing this on @nogc. I don't think this is something our current, imprecise laguage definition unambiguously states, though.

@WalterBright
Copy link
Member Author

This is reimplemented to be based on the mutability of the return type. The same logic is used as for the mutability of the function parameters, so I factored that out into a nested function they both call.

@WalterBright WalterBright force-pushed the fix15862 branch 3 times, most recently from 709618b to 5e66e36 Compare October 16, 2016 04:19
@codecov-io
Copy link

Current coverage is 87.35% (diff: 94.59%)

Merging #6197 into master will decrease coverage by <.01%

@@             master      #6197   diff @@
==========================================
  Files           104        104          
  Lines         57465      57474     +9   
  Methods           0          0          
  Messages          0          0          
  Branches          0          0          
==========================================
+ Hits          50202      50209     +7   
- Misses         7263       7265     +2   
  Partials          0          0          

Powered by Codecov. Last update 3ddd65b...5e66e36

@andralex
Copy link
Member

LGTM, @MartinNowak wanna take a look?


/* Should catch delegates and function pointers, and fold in their purity
case PUREconst:
purity = PUREconst;
Copy link
Member

@MartinNowak MartinNowak Oct 20, 2016

Choose a reason for hiding this comment

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

This could increase purity again, couldn't it? How about replacing the switch with purity = min(purity, purityOfType(isref, t))?

Copy link
Member Author

@WalterBright WalterBright Oct 21, 2016

Choose a reason for hiding this comment

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

This could increase purity again, couldn't it?

No, because any setting of PUREweak exits the loop.

How about replacing the switch with purity = min(purity, purityOfType(isref, t))?

Because there is no reason to continue with the loop once purity is set to PUREweak.

Copy link
Member

@MartinNowak MartinNowak Oct 23, 2016

Choose a reason for hiding this comment

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

Too clever usage of break/continue in switch nested in a loop IMO.
Hope you agree that break Lloop is better here :).

- instead of an uncommon unconditional break at the end of the loop body
@MartinNowak
Copy link
Member

Auto-merge toggled on

@MartinNowak MartinNowak merged commit ab9d712 into dlang:master Oct 23, 2016
@nordlow
Copy link
Contributor

nordlow commented Oct 23, 2016

Does this mean that we can now qualify druntime defs of C alloc functions such as

https://dlang.org/library/core/stdc/stdlib/malloc.html

and alikes as pure?

If so, I can do it!

@andralex
Copy link
Member

affirmative

@nordlow
Copy link
Contributor

nordlow commented Oct 24, 2016

And Mallocator?

@WalterBright WalterBright deleted the fix15862 branch October 24, 2016 08:32
@andralex
Copy link
Member

affirmative

@nordlow
Copy link
Contributor

nordlow commented Oct 24, 2016

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.

10 participants

Comments