Extend MemberRefExpr in a fairly substantial way: now it is ok, when applied to a

struct rvalue, to produce a struct element directly, without converting the rvalue
to an lvalue.

This means that it no longer materializes an lvalue when applied to a let declaration
or other rvalue.  For example, this testcase:

struct X { var a,b : Int} 
func g() -> X { return X(1,2) }

func f() {
  let a = g().a
}

used to sema into:

       (load_expr implicit type='Int'
          (member_ref_expr type='@inout (implicit, nonsettable)Int' decl=t.(file).X.a@t.swift:2:16
            (materialize_expr implicit type='@inout (implicit)X'
              (call_expr type='X'

and silgen into:

  %1 = function_ref @_TF1t1gFT_VS_1X : $@thin () -> X // user: %2
  %2 = apply %1() : $@thin () -> X                // user: %4
  %3 = alloc_stack $X                             // users: %7, %5, %4
  store %2 to %3#1 : $*X                          // id: %4
  %5 = struct_element_addr %3#1 : $*X, #a         // user: %6
  %6 = load %5 : $*Int64

It now sema's into:
        (member_ref_expr type='Int' decl=t.(file).X.a@t.swift:1:16
          (call_expr type='X'

and silgens into:

  %1 = function_ref @_TF1t1gFT_VS_1X : $@thin () -> X // user: %2
  %2 = apply %1() : $@thin () -> X                // user: %3
  %3 = struct_extract %2 : $X, #a

I think I'm finally starting to grok Doug's crazy typechecker magic.



Swift SVN r11599
This commit is contained in:
Chris Lattner
2013-12-23 06:24:55 +00:00
parent 4196ce0383
commit b92c57fd3e
6 changed files with 125 additions and 41 deletions

View File

@@ -867,7 +867,8 @@ ConstraintSystem::getTypeOfMemberReference(Type baseTy, ValueDecl *value,
llvm::DenseMap<CanType, TypeVariableType *> replacements;
SmallVector<GenericTypeParamType *, 4> genericParams;
SmallVector<Requirement, 4> genericRequirements;
collectContextParamsAndRequirements(dc, genericParams, genericRequirements);
collectContextParamsAndRequirements(dc, genericParams,
genericRequirements);
openGeneric(dc, genericParams, genericRequirements,
/*skipProtocolSelfConstraint=*/true,
opener,
@@ -888,15 +889,25 @@ ConstraintSystem::getTypeOfMemberReference(Type baseTy, ValueDecl *value,
} else {
selfTy = value->getDeclContext()->getDeclaredTypeOfContext();
}
// If we have a type reference, look through the metatype.
if (isTypeReference)
openedType = openedType->castTo<MetatypeType>()->getInstanceType();
// If we're not coming from something function-like, prepend the type
// for 'self' to the type.
if (!isa<AbstractFunctionDecl>(value) && !isa<EnumElementDecl>(value))
if (!isa<AbstractFunctionDecl>(value) && !isa<EnumElementDecl>(value)) {
// If self is a struct, properly qualify it based on our base
// qualification. If we have an lvalue coming in, we expect an lvalue.
// TODO: Not for @mutable methods, they don't require self to be an
// lvalue.
if (!selfTy->hasReferenceSemantics() &&
baseTy->is<LValueType>())
selfTy = LValueType::get(selfTy,
LValueType::Qual::DefaultForMemberAccess);
openedType = FunctionType::get(selfTy, openedType);
}
}
// Constrain the 'self' object type.