diff --git a/doc/ref/types.xml b/doc/ref/types.xml
index 4367548ec1..c9671fc32e 100644
--- a/doc/ref/types.xml
+++ b/doc/ref/types.xml
@@ -485,7 +485,7 @@ except if the attribute had been specially constructed as
mutable attribute.
It depends on the representation of an object (see )
-which attribute values it stores. An object in the representation
+which attribute values it stores. An immutable object in the representation
IsAttributeStoringRep stores all attribute values once they are
computed. Moreover, for an object in this representation, subsequent
calls to an attribute will return the same object; this is achieved
@@ -496,6 +496,13 @@ value. (These methods are called the system setter and the
system getter of the attribute, respectively.)system
gettersystem setter
+Mutable objects in IsAttributeStoringRep are allowed, but
+attribute values are not automatically stored in them. Such objects
+are useful because values can be stored by explicitly calling the
+relevant setter, and because they may later be made immutable using
+, at which point they will start storing
+all attribute values.
+
Note also that it is impossible to get rid of a stored attribute
value because the system may have drawn conclusions from the old
attribute value, and just removing the value might leave the data
@@ -568,7 +575,8 @@ of the object obj is known.
For an attribute attr, Setter(attr)
is called automatically when the attribute value has been
-computed for the first time.
+computed for an immutable object which does not already have a
+value stored for attr.
One can also call the setter explicitly,
for example, Setter( Size )( obj, val )
sets val as size of the
diff --git a/lib/sgpres.gi b/lib/sgpres.gi
index abd8ed4c24..caadebe932 100644
--- a/lib/sgpres.gi
+++ b/lib/sgpres.gi
@@ -1081,6 +1081,9 @@ InstallGlobalFunction( PresentationAugmentedCosetTable,
# group generators.
SetPrimaryGeneratorWords(T,aug.primaryGeneratorWords);
+ # Since T is mutable, we must set this attribite "manually"
+ SetTzOptions(T, TzOptions(T));
+
# handle relators of length 1 or 2, but do not eliminate any primary
# generators.
TzOptions(T).protected := tree[TR_PRIMARY];
diff --git a/lib/tietze.gi b/lib/tietze.gi
index 60ab54795b..9489cdf7e2 100644
--- a/lib/tietze.gi
+++ b/lib/tietze.gi
@@ -381,6 +381,9 @@ InstallGlobalFunction( PresentationFpGroup, function ( arg )
SetOne(T,Identity( F ));
T!.identity:=Identity( F );
+ # since T is mutable, we must set this attribute "manually"
+ SetTzOptions(T,TzOptions(T));
+
# initialize some Tietze options
TzOptions(T).protected := 0;
TzOptions(T).printLevel:=printlevel;
diff --git a/src/opers.c b/src/opers.c
index 299b7caa53..e392309cb3 100644
--- a/src/opers.c
+++ b/src/opers.c
@@ -2420,7 +2420,7 @@ Obj DoAttribute (
val = CopyObj( val, 0 );
/* set the value (but not for internal objects) */
- if ( ENABLED_ATTR( self ) == 1 ) {
+ if ( ENABLED_ATTR( self ) == 1 && !IS_MUTABLE_OBJ( obj ) ) {
switch ( TNUM_OBJ( obj ) ) {
case T_COMOBJ:
case T_POSOBJ:
@@ -2471,7 +2471,7 @@ static Obj DoVerboseAttribute(Obj self, Obj obj)
val = CopyObj( val, 0 );
/* set the value (but not for internal objects) */
- if ( ENABLED_ATTR( self ) == 1 ) {
+ if ( ENABLED_ATTR( self ) == 1 && !IS_MUTABLE_OBJ( obj ) ) {
switch ( TNUM_OBJ( obj ) ) {
case T_COMOBJ:
case T_POSOBJ:
@@ -2516,7 +2516,7 @@ static Obj DoMutableAttribute(Obj self, Obj obj)
val = DoOperation1Args( self, obj );
/* set the value (but not for internal objects) */
- if ( ENABLED_ATTR( self ) == 1 ) {
+ if ( ENABLED_ATTR( self ) == 1 && !IS_MUTABLE_OBJ( obj ) ) {
switch ( TNUM_OBJ( obj ) ) {
case T_COMOBJ:
case T_POSOBJ:
@@ -2561,7 +2561,7 @@ static Obj DoVerboseMutableAttribute(Obj self, Obj obj)
val = DoVerboseOperation1Args( self, obj );
/* set the value (but not for internal objects) */
- if ( ENABLED_ATTR( self ) == 1 ) {
+ if ( ENABLED_ATTR( self ) == 1 && !IS_MUTABLE_OBJ( obj ) ) {
switch ( TNUM_OBJ( obj ) ) {
case T_COMOBJ:
case T_POSOBJ:
diff --git a/tst/testinstall/attribute.tst b/tst/testinstall/attribute.tst
index bda3d76c02..bc88fd2dcf 100644
--- a/tst/testinstall/attribute.tst
+++ b/tst/testinstall/attribute.tst
@@ -44,6 +44,31 @@ gap> NewAttribute("IsBanana", IsGroup, true, 15);
gap> NewAttribute("IsBanana", IsGroup, "mutable", 15, "Hello, world");
Error, Usage: NewAttribute( , [, ][, ] )
-
-#
+gap> DeclareAttribute("FavouriteFruit", IsObject);
+gap> foo := rec();;
+gap> fam := NewFamily("FruitFamily");
+
+gap> Objectify(NewType(fam, IsMutable and IsAttributeStoringRep), foo);
+