Skip to content

Commit

Permalink
use new entitlement set in SupportedEntitlements
Browse files Browse the repository at this point in the history
this also improves the inferrence of entitlements in the entitlement migration
  • Loading branch information
turbolent committed Apr 18, 2024
1 parent 14bc243 commit 552f09f
Show file tree
Hide file tree
Showing 13 changed files with 131 additions and 101 deletions.
2 changes: 1 addition & 1 deletion migrations/entitlements/migration.go
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ func ConvertToEntitledType(

default:
supportedEntitlements := entitlementSupportingType.SupportedEntitlements()
newAccess := sema.NewAccessFromEntitlementSet(supportedEntitlements, sema.Conjunction)
newAccess := supportedEntitlements.Access()
auth = interpreter.ConvertSemaAccessToStaticAuthorization(inter, newAccess)
returnNew = true
}
Expand Down
2 changes: 1 addition & 1 deletion migrations/entitlements/migration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -474,7 +474,7 @@ func TestConvertToEntitledType(t *testing.T) {
},
{
Input: sema.NewReferenceType(nil, sema.UnauthorizedAccess, compositeResourceWithEOrF),
Output: sema.NewReferenceType(nil, eAndFAccess, compositeResourceWithEOrF),
Output: sema.NewReferenceType(nil, eOrFAccess, compositeResourceWithEOrF),
Name: "composite E or F",
},
{
Expand Down
18 changes: 5 additions & 13 deletions runtime/interpreter/interpreter.go
Original file line number Diff line number Diff line change
Expand Up @@ -817,14 +817,8 @@ func (interpreter *Interpreter) resultValue(returnValue Value, returnType sema.T
auth := UnauthorizedAccess
// reference is authorized to the entire resource, since it is only accessible in a function where a resource value is owned
if entitlementSupportingType, ok := ty.(sema.EntitlementSupportingType); ok {
supportedEntitlements := entitlementSupportingType.SupportedEntitlements()
if supportedEntitlements != nil && supportedEntitlements.Len() > 0 {
access := sema.EntitlementSetAccess{
SetKind: sema.Conjunction,
Entitlements: supportedEntitlements,
}
auth = ConvertSemaAccessToStaticAuthorization(interpreter, access)
}
access := entitlementSupportingType.SupportedEntitlements().Access()
auth = ConvertSemaAccessToStaticAuthorization(interpreter, access)
}
return auth
}
Expand Down Expand Up @@ -1038,7 +1032,7 @@ func (interpreter *Interpreter) evaluateDefaultDestroyEvent(
panic(errors.NewUnreachableError())
}
supportedEntitlements := entitlementSupportingType.SupportedEntitlements()
access := sema.NewAccessFromEntitlementSet(supportedEntitlements, sema.Conjunction)
access := supportedEntitlements.Access()
base, self = attachmentBaseAndSelfValues(
declarationInterpreter,
access,
Expand Down Expand Up @@ -1393,10 +1387,8 @@ func (declarationInterpreter *Interpreter) declareNonEnumCompositeValue(
// Self's type in the constructor is fully entitled, since
// the constructor can only be called when in possession of the base resource

auth := ConvertSemaAccessToStaticAuthorization(
interpreter,
sema.NewAccessFromEntitlementSet(attachmentType.SupportedEntitlements(), sema.Conjunction),
)
access := attachmentType.SupportedEntitlements().Access()
auth := ConvertSemaAccessToStaticAuthorization(interpreter, access)

self = NewEphemeralReferenceValue(interpreter, auth, value, attachmentType, locationRange)

Expand Down
2 changes: 1 addition & 1 deletion runtime/interpreter/interpreter_expression.go
Original file line number Diff line number Diff line change
Expand Up @@ -1562,7 +1562,7 @@ func (interpreter *Interpreter) VisitAttachExpression(attachExpression *ast.Atta
// within the constructor, the attachment's base and self references should be fully entitled,
// as the constructor of the attachment is only callable by the owner of the base
baseType := interpreter.MustSemaTypeOfValue(base).(sema.EntitlementSupportingType)
baseAccess := sema.NewAccessFromEntitlementSet(baseType.SupportedEntitlements(), sema.Conjunction)
baseAccess := baseType.SupportedEntitlements().Access()
auth := ConvertSemaAccessToStaticAuthorization(interpreter, baseAccess)

attachmentType := interpreter.Program.Elaboration.AttachTypes(attachExpression)
Expand Down
4 changes: 2 additions & 2 deletions runtime/interpreter/value.go
Original file line number Diff line number Diff line change
Expand Up @@ -18370,10 +18370,10 @@ func (v *CompositeValue) GetTypeKey(
locationRange LocationRange,
ty sema.Type,
) Value {
var access sema.Access = sema.UnauthorizedAccess
access := sema.UnauthorizedAccess
attachmentTyp, isAttachmentType := ty.(*sema.CompositeType)
if isAttachmentType {
access = sema.NewAccessFromEntitlementSet(attachmentTyp.SupportedEntitlements(), sema.Conjunction)
access = attachmentTyp.SupportedEntitlements().Access()
}
return v.getTypeKey(interpreter, locationRange, ty, access)
}
Expand Down
2 changes: 1 addition & 1 deletion runtime/sema/access.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ func NewEntitlementSetAccess(
}
}

func NewAccessFromEntitlementSet(
func NewAccessFromEntitlementOrderedSet(
set *EntitlementOrderedSet,
setKind EntitlementSetKind,
) Access {
Expand Down
31 changes: 23 additions & 8 deletions runtime/sema/check_composite_declaration.go
Original file line number Diff line number Diff line change
Expand Up @@ -107,20 +107,35 @@ func (checker *Checker) checkAttachmentMembersAccess(attachmentType *CompositeTy
var supportedBaseEntitlements *EntitlementOrderedSet
baseType := attachmentType.GetBaseType()
if base, ok := attachmentType.GetBaseType().(EntitlementSupportingType); ok {
supportedBaseEntitlements = base.SupportedEntitlements()
// TODO:
access := base.SupportedEntitlements().Access()
if access, ok := access.(EntitlementSetAccess); ok {
supportedBaseEntitlements = access.Entitlements
}
}
if supportedBaseEntitlements == nil {
supportedBaseEntitlements = &orderedmap.OrderedMap[*EntitlementType, struct{}]{}
}

attachmentType.EffectiveInterfaceConformanceSet().ForEach(func(intf *InterfaceType) {
intf.Members.Foreach(func(_ string, member *Member) {
checker.checkAttachmentMemberAccess(attachmentType, member, baseType, supportedBaseEntitlements)
attachmentType.EffectiveInterfaceConformanceSet().
ForEach(func(interfaceType *InterfaceType) {
interfaceType.Members.Foreach(func(_ string, member *Member) {
checker.checkAttachmentMemberAccess(
attachmentType,
member,
baseType,
supportedBaseEntitlements,
)
})
})
})

attachmentType.Members.Foreach(func(_ string, member *Member) {
checker.checkAttachmentMemberAccess(attachmentType, member, baseType, supportedBaseEntitlements)
checker.checkAttachmentMemberAccess(
attachmentType,
member,
baseType,
supportedBaseEntitlements,
)
})

}
Expand Down Expand Up @@ -2081,7 +2096,7 @@ func (checker *Checker) checkDefaultDestroyEventParam(

// make `self` and `base` available when checking default arguments so the fields of the composite are available
// as this event is emitted when the resource is destroyed, these values should be fully entitled
fullyEntitledAccess := NewAccessFromEntitlementSet(containerType.SupportedEntitlements(), Conjunction)
fullyEntitledAccess := containerType.SupportedEntitlements().Access()

checker.declareSelfValue(
fullyEntitledAccess,
Expand Down Expand Up @@ -2224,7 +2239,7 @@ func (checker *Checker) checkSpecialFunction(
defer checker.leaveValueScope(specialFunction.EndPosition, checkResourceLoss)

// initializers and destructors are considered fully entitled to their container type
fnAccess := NewAccessFromEntitlementSet(containerType.SupportedEntitlements(), Conjunction)
fnAccess := containerType.SupportedEntitlements().Access()

checker.declareSelfValue(fnAccess, containerType, containerDocString)

Expand Down
2 changes: 1 addition & 1 deletion runtime/sema/check_function.go
Original file line number Diff line number Diff line change
Expand Up @@ -423,7 +423,7 @@ func (checker *Checker) visitWithPostConditions(postConditions *ast.Conditions,
// here the `result` value in the `post` block will have type `auth(E, X, Y) &R`
if entitlementSupportingType, ok := innerType.(EntitlementSupportingType); ok {
supportedEntitlements := entitlementSupportingType.SupportedEntitlements()
auth = NewAccessFromEntitlementSet(supportedEntitlements, Conjunction)
auth = supportedEntitlements.Access()
}

resultType = &ReferenceType{
Expand Down
9 changes: 3 additions & 6 deletions runtime/sema/check_member_expression.go
Original file line number Diff line number Diff line change
Expand Up @@ -521,12 +521,9 @@ func allSupportedEntitlements(typ Type, isInnerType bool) Access {
return allSupportedEntitlements(typ.ReturnTypeAnnotation.Type, true)
}
case EntitlementSupportingType:
supportedEntitlements := typ.SupportedEntitlements()
if supportedEntitlements != nil && supportedEntitlements.Len() > 0 {
return EntitlementSetAccess{
SetKind: Conjunction,
Entitlements: supportedEntitlements,
}
access := typ.SupportedEntitlements().Access()
if access != UnauthorizedAccess {
return access
}
}

Expand Down
4 changes: 4 additions & 0 deletions runtime/sema/errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -3071,6 +3071,7 @@ func (e *InvalidAccessError) SecondaryError() string {
fmt.Fprint(&sb, "reference needs all of entitlements ")
missingEntitlements.ForeachWithIndex(enumerateEntitlements(missingLen, "and"))
}

case Disjunction:
// when both `required` is a disjunction, we know `possessed` has none of the entitlements in it:
// suggest adding one of those entitlements
Expand All @@ -3079,6 +3080,9 @@ func (e *InvalidAccessError) SecondaryError() string {
requiredLen := requiredEntitlementsSet.Len()
// singleton-1 sets are always conjunctions
requiredEntitlementsSet.ForeachWithIndex(enumerateEntitlements(requiredLen, "or"))

default:
panic(errors.NewUnreachableError())
}

return sb.String()
Expand Down
Loading

0 comments on commit 552f09f

Please sign in to comment.