From facba98b68fcc6fb5b9a930fe15893a853fcf708 Mon Sep 17 00:00:00 2001 From: Walter Bright Date: Fri, 27 Dec 2024 16:52:20 -0800 Subject: [PATCH] fix #20610 aliasing for fields does not work --- compiler/src/dmd/declaration.d | 11 ++++---- compiler/src/dmd/dsymbolsem.d | 2 +- compiler/src/dmd/expressionsem.d | 8 +++--- compiler/src/dmd/printast.d | 6 ++++ compiler/src/dmd/typesem.d | 42 ++++++++++++++++++++++++++-- compiler/test/runnable/aliasassign.d | 32 +++++++++++++++++++-- 6 files changed, 85 insertions(+), 16 deletions(-) diff --git a/compiler/src/dmd/declaration.d b/compiler/src/dmd/declaration.d index 67cddfa4cb43..e6fb1ed65cd9 100644 --- a/compiler/src/dmd/declaration.d +++ b/compiler/src/dmd/declaration.d @@ -30,6 +30,7 @@ import dmd.func; import dmd.funcsem : overloadApply, getLevelAndCheck; import dmd.globals; import dmd.gluelayer; +import dmd.hdrgen; import dmd.id; import dmd.identifier; import dmd.init; @@ -442,8 +443,7 @@ extern (C++) final class AliasDeclaration : Declaration extern (D) this(const ref Loc loc, Identifier ident, Type type) @safe { super(loc, ident); - //printf("AliasDeclaration(id = '%s', type = %p)\n", ident.toChars(), type); - //printf("type = '%s'\n", type.toChars()); + //debug printf("AliasDeclaration(id = '%s', type = `%s`, %p)\n", ident.toChars(), dmd.hdrgen.toChars(type), type.isTypeIdentifier()); this.type = type; assert(type); } @@ -451,7 +451,7 @@ extern (C++) final class AliasDeclaration : Declaration extern (D) this(const ref Loc loc, Identifier ident, Dsymbol s) @safe { super(loc, ident); - //printf("AliasDeclaration(id = '%s', s = %p)\n", ident.toChars(), s); + //debug printf("AliasDeclaration(id = '%s', s = `%s`)\n", ident.toChars(), s.toChars()); assert(s != this); this.aliassym = s; assert(s); @@ -612,8 +612,9 @@ extern (C++) final class AliasDeclaration : Declaration override Dsymbol toAlias() { - //printf("[%s] AliasDeclaration::toAlias('%s', this = %p, aliassym = %p, kind = '%s', inuse = %d)\n", - // loc.toChars(), toChars(), this, aliassym, aliassym ? aliassym.kind() : "", inuse); + static if (0) + printf("[%s] AliasDeclaration::toAlias('%s', this = %p, aliassym: %s, kind: '%s', inuse = %d)\n", + loc.toChars(), toChars(), this, aliassym ? aliassym.toChars() : "", aliassym ? aliassym.kind() : "", inuse); assert(this != aliassym); //static int count; if (++count == 10) *(char*)0=0; diff --git a/compiler/src/dmd/dsymbolsem.d b/compiler/src/dmd/dsymbolsem.d index 606d2f1a8249..7e9843617c92 100644 --- a/compiler/src/dmd/dsymbolsem.d +++ b/compiler/src/dmd/dsymbolsem.d @@ -5243,7 +5243,7 @@ void aliasInstanceSemantic(TemplateInstance tempinst, Scope* sc, TemplateDeclara // function used to perform semantic on AliasDeclaration void aliasSemantic(AliasDeclaration ds, Scope* sc) { - //printf("AliasDeclaration::semantic() %s\n", ds.toChars()); + //printf("AliasDeclaration::semantic() %s %p\n", ds.toChars(), ds.aliassym); // as DsymbolSemanticVisitor::visit(AliasDeclaration), in case we're called first. // see https://issues.dlang.org/show_bug.cgi?id=21001 diff --git a/compiler/src/dmd/expressionsem.d b/compiler/src/dmd/expressionsem.d index ce9cb75b75b1..8dd3ac6bdbce 100644 --- a/compiler/src/dmd/expressionsem.d +++ b/compiler/src/dmd/expressionsem.d @@ -8138,7 +8138,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor static if (LOGSEMANTIC) { printf("DotIdExp::semantic(this = %p, '%s')\n", exp, exp.toChars()); - //printf("e1.op = %d, '%s'\n", e1.op, Token.toChars(e1.op)); + printAST(exp); } if (sc.inCfile) @@ -14037,7 +14037,7 @@ Expression expressionSemantic(Expression e, Scope* sc) private Expression dotIdSemanticPropX(DotIdExp exp, Scope* sc) { - //printf("DotIdExp::semanticX(this = %p, '%s')\n", this, toChars()); + //printf("dotIdSemanticPropX() %s\n", toChars(exp)); if (Expression ex = unaSemantic(exp, sc)) return ex; @@ -14165,7 +14165,7 @@ private Expression dotIdSemanticPropX(DotIdExp exp, Scope* sc) */ Expression dotIdSemanticProp(DotIdExp exp, Scope* sc, bool gag) { - //printf("DotIdExp::semanticY(this = %p, '%s')\n", exp, exp.toChars()); + //printf("dotIdSemanticProp('%s')\n", exp.toChars()); //{ static int z; fflush(stdout); if (++z == 10) *(char*)0=0; } @@ -14503,7 +14503,7 @@ Expression dotIdSemanticProp(DotIdExp exp, Scope* sc, bool gag) const flag = cast(DotExpFlag) (exp.noderef * DotExpFlag.noDeref | gag * DotExpFlag.gag); - Expression e = exp.e1.type.dotExp(sc, exp.e1, exp.ident, flag); + Expression e = dotExp(exp.e1.type, sc, exp.e1, exp.ident, flag); if (e) { e = e.expressionSemantic(sc); diff --git a/compiler/src/dmd/printast.d b/compiler/src/dmd/printast.d index 02dc65390b03..26d27707c169 100644 --- a/compiler/src/dmd/printast.d +++ b/compiler/src/dmd/printast.d @@ -51,6 +51,12 @@ extern (C++) final class PrintASTVisitor : Visitor printf("%.*s %s\n", cast(int)s.length, s.ptr, e.type ? e.type.toChars() : ""); } + override void visit(IdentifierExp e) + { + printIndent(indent); + printf("Identifier `%s` %s\n", e.ident.toChars(), e.type ? e.type.toChars() : ""); + } + override void visit(IntegerExp e) { printIndent(indent); diff --git a/compiler/src/dmd/typesem.d b/compiler/src/dmd/typesem.d index 6d2d9212e9ec..2ec88f2363a0 100644 --- a/compiler/src/dmd/typesem.d +++ b/compiler/src/dmd/typesem.d @@ -4462,6 +4462,10 @@ void resolve(Type mt, const ref Loc loc, Scope* sc, out Expression pe, out Type */ Expression dotExp(Type mt, Scope* sc, Expression e, Identifier ident, DotExpFlag flag) { + enum LOGDOTEXP = false; + if (LOGDOTEXP) + printf("dotExp()\n"); + Expression visitType(Type mt) { VarDeclaration v = null; @@ -5082,8 +5086,41 @@ Expression dotExp(Type mt, Scope* sc, Expression e, Identifier ident, DotExpFlag return noMember(mt, sc, e, ident, flag); } // check before alias resolution; the alias itself might be deprecated! - if (s.isAliasDeclaration) + if (auto ad = s.isAliasDeclaration) + { s.checkDeprecated(e.loc, sc); + + // Fix for https://github.com/dlang/dmd/issues/20610 + if (ad.originalType) + { + if (auto tid = ad.originalType.isTypeIdentifier()) + { + if (tid.idents.length) + { + static if (0) + { + printf("TypeStruct::dotExp(e = '%s', ident = '%s')\n", e.toChars(), ident.toChars()); + printf("AliasDeclaration: %s\n", ad.toChars()); + if (ad.aliassym) + printf("aliassym: %s\n", ad.aliassym.toChars()); + printf("tid type: %s\n", toChars(tid)); + } + /* Rewrite e.s as e.(tid.ident).(tid.idents) + */ + Expression die = new DotIdExp(e.loc, e, tid.ident); + foreach (id; tid.idents) // maybe use typeToExpressionHelper() + die = new DotIdExp(e.loc, die, cast(Identifier)id); + /* Ambiguous syntax, only way to disambiguate it to try it + */ + die = dmd.expressionsem.trySemantic(die, sc); + if (die && die.isDotVarExp()) // shrink wrap around DotVarExp() + { + return die; + } + } + } + } + } s = s.toAlias(); if (auto em = s.isEnumMember()) @@ -6074,7 +6111,7 @@ Dsymbol toDsymbol(Type type, Scope* sc) Dsymbol visitIdentifier(TypeIdentifier type) { - //printf("TypeIdentifier::toDsymbol('%s')\n", toChars()); + //printf("TypeIdentifier::toDsymbol('%s')\n", toChars(type)); if (!sc) return null; @@ -6086,7 +6123,6 @@ Dsymbol toDsymbol(Type type, Scope* sc) s = t.toDsymbol(sc); if (e) s = getDsymbol(e); - return s; } diff --git a/compiler/test/runnable/aliasassign.d b/compiler/test/runnable/aliasassign.d index 986cccc4db89..4f61e3787e32 100644 --- a/compiler/test/runnable/aliasassign.d +++ b/compiler/test/runnable/aliasassign.d @@ -15,7 +15,7 @@ template Qual(alias T) alias Qual = T; } -void test() +void test1() { int x = 3; int y = 4; @@ -25,7 +25,33 @@ void test() assert(XY[1] == 4); } -void main() +/**********************************************/ + +struct T +{ + int k,i = 2; +} + +struct S +{ + int x; + T t; + alias ti = t.i; +} + +void test2() +{ + T t = T(1, 2); + S s; + assert(s.ti == 2); +} + +/**********************************************/ + +int main() { - test(); + test1(); + test2(); + + return 0; }