ASTContext::getUInt32Decl, continuation of github pull 1534


(Jon Rafkind) #1

Pull request 1534 deals with adding the function getUInt32Decl() to ASTContext that returns the declaration for the standard UInt32 type. getUInt32Decl was meant to be similar to the other getXYZDecl() functions in ASTContext.

My use case for this is to unwrap the constructor call to a UInt32, and extract the argument expression. In general I unwrap all 'primitive' type constructors. For example,

let x = UInt32(2)

The AST will contain a constructor for UInt32.init(2), but I only care about the 2. To accomplish this, I compare the MetatypeType that is associated with the constructor with the existing NominalTypeDecl that exists for the UInt32 type.

On the pull request, Chris Lattner suggests that I can determine if the constructor is for UInt32 by looking at the DeclRefExpr associated with the constructor call. I don't see how the DeclRefExpr will tell me that it came from the UInt32 type, though.

For now I am basing my code on advice given by Jordan Rose

"""
You can do something like this to build your own metatype:

ASTContext &ctx = …
Type intTy = ctx.getIntDecl()->getDeclaredType();
auto *intMetaTy = MetatypeType::get(intTy, ctx);

And then compare types using TypeBase::isEqual (which looks through typealiases and such—it's comparing "canonical" types).

  Type unknownTy = …
    if (unknownTy->isEqual(intMetaTy)) {
    // celebrate
  }
"""

Starting from a ConstructorRefCallExpr this is how I come up with the unknownTy. (simplified and psuedo-codish)

DeclRefExpr * fn = constructor->getFn();
ValueDecl * value = fn->getDecl();
AnyFunctionType * functionType = value->getType().getPointer();
MetatypeType * unknownTy = functionType->getInput().getPointer();

(The input type to a constructor always seems to be a MetatypeType, even though in general functionType->getInput() could be almost anything.)

I am not very concerned with adding getUInt32Decl() to ASTContext, I just figured it was an omission. At first I thought getUInt32Decl would be an obvious welcome addition to ASTContext. After all, there are two dozen or so other getXYZDecl functions that all seem to get types from the standard library. Perhaps getUIntDecl() is enough -- does UInt32 inherit from UInt, and is that something I can easily check?

For now I have copied findStdlibType() from ASTContext.cpp into my own code, so I can find the UInt32 decl myself. Luckily the function that does the heavy lifting, ASTContext::lookupInSwiftModule, is public.

If there is a better way to determine that a ConstructorRefCallExpr is calling a specific type's constructor then I would be interested to hear it.

···

--