mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
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:
@@ -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.
|
||||
|
||||
Reference in New Issue
Block a user