       new Call FREE, [@first]
     else if op is 'sizeof'
       new Literal @first.size
-    else if op is '&' and ty1 = @computedType.base
-      # The typechecker guarantees that `@first` is assignable, so if we're
-      # taking the address of a stack variable, `@first.unwrapAll()` must be
-      # the literal of that variable.
-      @first.unwrapAll().noStackDeref = true
-      @first
+    else if op is '&'
+      if @computedType.base instanceof StructType
+        # If we're taking the pointer of a struct, we don't need to do anything
+        # since structs are kept as pointers.
+        @first
+      else
+        # Otherwise we must be doing a dereference, so transform it now and
+        # get out the index expression, which must be the address.
+        @first.unwrapAll().transformNode(o).properties[0].index
     else if op is '*'
       # This is only called when this deref is _not_ the base of a struct
       # access, as in struct accesses, dereferencing is the same as not

    return unless lptys.length is rptys.length
    ptys = []
    for lpty, i in lptys
      ptys.push unify types, lpty, rptys[i], assign
    return new ArrowType ptys, unify(types, lty.ret, rty.ret, assign)
  if lty instanceof PointerType and rty in integral
    printWarn "conversion from `#{rty}' to pointer without cast"
    return lty

    # If we're assigning, return the left type, else return the wider primitive.
    if lty.size isnt rty.size
      printWarn "conversion from `#{rty}' to `#{lty}' may alter its value"
      return if assigning then lty else if lty.size > rty.size then lty else rty
    # Return the sign of the left type if they're the same size. This is just
    # to break the tie arbitrarily and to behave as expected for assignments.
    if lty.signed isnt rty.signed
