Skip to content

Commit

Permalink
Extract variants of implicitConvTo with regards to alias from mtype.d…
Browse files Browse the repository at this point in the history
… this and move them to typesem.d (#16677)
  • Loading branch information
RazvanN7 authored Jul 11, 2024
1 parent 8053445 commit 033ddcd
Show file tree
Hide file tree
Showing 2 changed files with 94 additions and 93 deletions.
93 changes: 0 additions & 93 deletions compiler/src/dmd/mtype.d
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ import dmd.aggregate;
import dmd.arraytypes;
import dmd.astenums;
import dmd.ast_node;
import dmd.dcast : implicitConvTo;
import dmd.dclass;
import dmd.declaration;
import dmd.denum;
Expand Down Expand Up @@ -3332,68 +3331,6 @@ extern (C++) final class TypeStruct : Type
return sym.hasInvariant() || sym.hasFieldWithInvariant;
}

extern (D) MATCH implicitConvToWithoutAliasThis(Type to)
{
//printf("TypeStruct::implicitConvToWithoutAliasThis(%s => %s)\n", toChars(), to.toChars());

auto tos = to.isTypeStruct();
if (!(tos && sym == tos.sym))
return MATCH.nomatch;

if (mod == to.mod)
return MATCH.exact;

if (MODimplicitConv(mod, to.mod))
return MATCH.constant;

/* Check all the fields. If they can all be converted,
* allow the conversion.
*/
MATCH m = MATCH.constant;
uint offset = ~0; // must never match a field offset
foreach (v; sym.fields[])
{
/* Why are we only looking at the first member of a union?
* The check should check for overlap of v with the previous field,
* not just starting at the same point
*/
if (!global.params.fixImmutableConv && v.offset == offset) // v is at same offset as previous field
continue; // ignore

Type tvf = v.type.addMod(mod); // from type
Type tvt = v.type.addMod(to.mod); // to type

// field match
MATCH mf = tvf.implicitConvTo(tvt);
//printf("\t%s => %s, match = %d\n", v.type.toChars(), tvt.toChars(), mf);

if (mf == MATCH.nomatch)
return MATCH.nomatch;
if (mf < m) // if field match is worse
m = mf;
offset = v.offset;
}
return m;
}

extern (D) MATCH implicitConvToThroughAliasThis(Type to)
{
auto tos = to.isTypeStruct();
if (!(tos && sym == tos.sym) &&
sym.aliasthis &&
!(att & AliasThisRec.tracing))
{
if (auto ato = aliasthisOf(this))
{
att = cast(AliasThisRec)(att | AliasThisRec.tracing);
MATCH m = ato.implicitConvTo(to);
att = cast(AliasThisRec)(att & ~AliasThisRec.tracing);
return m;
}
}
return MATCH.nomatch;
}

override MOD deduceWild(Type t, bool isRef)
{
if (ty == t.ty && sym == (cast(TypeStruct)t).sym)
Expand Down Expand Up @@ -3583,36 +3520,6 @@ extern (C++) final class TypeClass : Type
return sym;
}

extern (D) MATCH implicitConvToWithoutAliasThis(Type to)
{
ClassDeclaration cdto = to.isClassHandle();
MATCH m = constConv(this, to);
if (m > MATCH.nomatch)
return m;

if (cdto && cdto.isBaseOf(sym, null) && MODimplicitConv(mod, to.mod))
{
//printf("'to' is base\n");
return MATCH.convert;
}
return MATCH.nomatch;
}

extern (D) MATCH implicitConvToThroughAliasThis(Type to)
{
MATCH m;
if (sym.aliasthis && !(att & AliasThisRec.tracing))
{
if (auto ato = aliasthisOf(this))
{
att = cast(AliasThisRec)(att | AliasThisRec.tracing);
m = ato.implicitConvTo(to);
att = cast(AliasThisRec)(att & ~AliasThisRec.tracing);
}
}
return m;
}

override MOD deduceWild(Type t, bool isRef)
{
ClassDeclaration cd = t.isClassHandle();
Expand Down
94 changes: 94 additions & 0 deletions compiler/src/dmd/typesem.d
Original file line number Diff line number Diff line change
Expand Up @@ -7382,6 +7382,100 @@ bool isRecursiveAliasThis(ref Type att, Type t)
return false;
}

MATCH implicitConvToWithoutAliasThis(TypeStruct from, Type to)
{
//printf("TypeStruct::implicitConvToWithoutAliasThis(%s => %s)\n", toChars(), to.toChars());

auto tos = to.isTypeStruct();
if (!(tos && from.sym == tos.sym))
return MATCH.nomatch;

if (from.mod == to.mod)
return MATCH.exact;

if (MODimplicitConv(from.mod, to.mod))
return MATCH.constant;

/* Check all the fields. If they can all be converted,
* allow the conversion.
*/
MATCH m = MATCH.constant;
uint offset = ~0; // must never match a field offset
foreach (v; from.sym.fields[])
{
/* Why are we only looking at the first member of a union?
* The check should check for overlap of v with the previous field,
* not just starting at the same point
*/
if (!global.params.fixImmutableConv && v.offset == offset) // v is at same offset as previous field
continue; // ignore

Type tvf = v.type.addMod(from.mod); // from type
Type tvt = v.type.addMod(to.mod); // to type

// field match
MATCH mf = tvf.implicitConvTo(tvt);
//printf("\t%s => %s, match = %d\n", v.type.toChars(), tvt.toChars(), mf);

if (mf == MATCH.nomatch)
return MATCH.nomatch;
if (mf < m) // if field match is worse
m = mf;
offset = v.offset;
}
return m;
}

MATCH implicitConvToWithoutAliasThis(TypeClass from, Type to)
{
ClassDeclaration cdto = to.isClassHandle();
MATCH m = constConv(from, to);
if (m > MATCH.nomatch)
return m;

if (cdto && cdto.isBaseOf(from.sym, null) && MODimplicitConv(from.mod, to.mod))
{
//printf("'to' is base\n");
return MATCH.convert;
}
return MATCH.nomatch;
}

MATCH implicitConvToThroughAliasThis(TypeClass from, Type to)
{
MATCH m;
if (from.sym.aliasthis && !(from.att & AliasThisRec.tracing))
{
if (auto ato = aliasthisOf(from))
{
from.att = cast(AliasThisRec)(from.att | AliasThisRec.tracing);
m = ato.implicitConvTo(to);
from.att = cast(AliasThisRec)(from.att & ~AliasThisRec.tracing);
}
}
return m;
}

MATCH implicitConvToThroughAliasThis(TypeStruct from, Type to)
{
auto tos = to.isTypeStruct();
if (!(tos && from.sym == tos.sym) &&
from.sym.aliasthis &&
!(from.att & AliasThisRec.tracing))
{
if (auto ato = aliasthisOf(from))
{
from.att = cast(AliasThisRec)(from.att | AliasThisRec.tracing);
MATCH m = ato.implicitConvTo(to);
from.att = cast(AliasThisRec)(from.att & ~AliasThisRec.tracing);
return m;
}
}
return MATCH.nomatch;
}



/******************************* Private *****************************************/

private:
Expand Down

0 comments on commit 033ddcd

Please sign in to comment.