D issues are now tracked on GitHub. This Bugzilla instance remains as a read-only archive.
Issue 13710 - Invariants not enforced on methods from alias this
Summary: Invariants not enforced on methods from alias this
Status: RESOLVED INVALID
Alias: None
Product: D
Classification: Unclassified
Component: dmd (show other issues)
Version: D2
Hardware: All All
: P1 normal
Assignee: No Owner
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2014-11-11 07:20 UTC by Mark Isaacson
Modified: 2014-11-11 14:29 UTC (History)
1 user (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this issue.
Description Mark Isaacson 2014-11-11 07:20:20 UTC
When you do "alias this" and have an invariant, any 
methods that are forwarded to the aliased member do not invoke 
your invariant methods.

This prevents me from writing a really sleek 10-liner to the tune 
of:

struct ValueRestrictedInteger(int lowerBound, int upperBound) {
  int value;
  alias value this;

  this (int rhs) { value = rhs; }

  invariant() {
    assert (value >= lowerBound && value <= upperBound);
  }

  void forDemonstrationOnly() {}
}

unittest {
  ValueRestrictedInteger!(0, 100) x = 0;
  x += 10;
  x -= 100; //This works, but I don't think it should
  x.forDemonstrationOnly(); //This causes the assertion to fire

  ValueRestrictedInteger!(0, 100) y = -100; //This also would hit 
the assertion
}


Forum post on same topic: http://forum.dlang.org/thread/ijoqlxqlacccwmqnwpdn@forum.dlang.org
Comment 1 Steven Schveighoffer 2014-11-11 13:10:46 UTC
I think from angel's comment that discussion, this bug is invalid. There is no method to call, so it cannot hook the invariant, x -= 100 translates directly to machine instructions.

What I would suggest is instead of using alias this, use opDispatch and opBinary to implement inlined functions that forward to the member. Then your invariant will be called. Instead of using alias this for inheritance, use composition.
Comment 2 Don 2014-11-11 14:16:33 UTC
I think there is still a problem. Does it actually make sense to have a class invariant, when you have an alias this?

It seems as though having an 'alias this' is like exposing a public member variable: once you do this, the class invariant cannot be trusted to be true at all times.
I feel uneasy about this; it suggests that 'alias this' is bad practice.

It may be worth adding to the documentation at
http://dlang.org/contracts.

That states:
"Invariants are used to specify characteristics of a class or struct that always must be true (except while executing a member function)."

I think that section should explicitly state that direct modification of members in a way which violates the invariant, will not be detected until a member function is called.
Comment 3 Steven Schveighoffer 2014-11-11 14:29:27 UTC
It's not just with alias this. Any modification of a member variable outside using the methods can result in breaking the invariant.

I think it's not a bad idea to mention the pitfalls, but I don't think alias this is special in that regard.