From e1083ddc6c7b40c721504d27af39e661d234c97d Mon Sep 17 00:00:00 2001 From: Owen Mansel-Chan Date: Tue, 3 Nov 2026 12:45:23 +0000 Subject: [PATCH] Go: reduce intermediate tuples in embedded method resolution Materialize embedded fields and their types before joining them with methods. Keep the helper non-inline and non-magic to avoid expanding field-type lookups across all fields. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- go/ql/lib/semmle/go/Types.qll | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/go/ql/lib/semmle/go/Types.qll b/go/ql/lib/semmle/go/Types.qll index 1ea5b5c65c1d..04e0f456276c 100644 --- a/go/ql/lib/semmle/go/Types.qll +++ b/go/ql/lib/semmle/go/Types.qll @@ -517,17 +517,23 @@ class StructType extends @structtype, CompositeType { .getOwnField(name, isEmbedded) } + // Materialize the embedded fields and their types before joining them with methods. + pragma[nomagic] + private Type getEmbeddedFieldType(Field embeddedParent, int depth) { + this.hasFieldCand(_, embeddedParent, depth, true) and + result = embeddedParent.getType() + } + /** * Gets a method of `embeddedParent`, which is then embedded into this struct type. */ Method getMethodOfEmbedded(Field embeddedParent, string name, int depth) { - // embeddedParent is a field of 'this' at depth 'depth - 1' - this.hasFieldCand(_, embeddedParent, depth - 1, true) and result.getName() = name and - ( - result.getReceiverBaseType() = lookThroughPointerType(embeddedParent.getType()) + // embeddedParent is a field of 'this' at depth 'depth - 1' + exists(Type embeddedType | embeddedType = this.getEmbeddedFieldType(embeddedParent, depth - 1) | + result.getReceiverBaseType() = lookThroughPointerType(embeddedType) or - methodhosts(result, embeddedParent.getType()) + methodhosts(result, embeddedType) ) }