Skip to content

Conversation

@dan-zheng
Copy link
Contributor

  • Add adjoint access level check to @differentiable attribute.
    • If the original function is "exported" (public or @_versioned), then the
      adjoint must also be exported.
  • Generalize lookupFuncDecl function and add it as a method to TypeChecker
    so that it can be used for type-checking #adjoint expression in a later
    commit.

…` method.

- Add adjoint access level check to @differentiable attribute.
  - If the original function is "exported" (public or @_versioned), then the
    adjoint must also be exported.
- Generalize `lookupFuncDecl` function and add it as a method to `TypeChecker`
  so that it can be used for type-checking #adjoint expression in a later
  commit.
@dan-zheng dan-zheng requested a review from rxwei June 15, 2018 17:38
}
// If function declaration could not be resolved, emit the appropriate
// diagnostic.
if (!resolvedFuncDecl) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Flip this and early return?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

std::function<void()> primalInvalidTypeContextDiagnostic = [&]() {
TC.diagnose(primalNameLoc,
diag::differentiable_attr_function_not_same_type_context,
primalSpecifier.Name);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you need a setInvalid here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think setInvalid is handled by the block below:

primal = TC.lookupFuncDecl(...)
if (!primal) {
  attr->setInvalid();
  return;
}

If any diagnostic is emitted, primal will be nullptr and attr->setInvalid() will execute.

notAFuncDecl = true;
continue;
}
if (hasValidTypeCtx.hasValue()) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if (hasValidTypeCtx && !(*hasValidTypeCtx)(funcDecl)) {
  wrongTypeContext = true;
  continue;
}

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

// If function declaration could not be resolved, emit the appropriate
// diagnostic.
if (!resolvedFuncDecl) {
if (results.empty()) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of these if-elses, I would suggest

if (results.empty()) {
  diagnose(...)
  return;
}

if (ambiguousFuncDecl) {
  ambiguousDiagnostic();
  return;
}

...

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

// the type context.
// This works around the fact that operators cannot be specified with a
// qualified name (i.e. only `(+)` works, `Float.(+)` doesn't).
if (funcName.isOperator() && lookupContext->isTypeContext()) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How about

if (funcName.isOperator() && lookupContext->isTypeContext())
  if (auto tmp = lookupMember(lookupContext, lookupContext->getSelfTypeInContext(), funcName))
    results = tmp;

Before writing any empty() checks, I'd usually check whether tmp has operator bool() first. In this case LookupResult does have one.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the tip! Done.

Addresses comments from @rxwei.
Copy link
Contributor Author

@dan-zheng dan-zheng left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks! I'll add tests for @differentiable access control before merging.

std::function<void()> primalInvalidTypeContextDiagnostic = [&]() {
TC.diagnose(primalNameLoc,
diag::differentiable_attr_function_not_same_type_context,
primalSpecifier.Name);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think setInvalid is handled by the block below:

primal = TC.lookupFuncDecl(...)
if (!primal) {
  attr->setInvalid();
  return;
}

If any diagnostic is emitted, primal will be nullptr and attr->setInvalid() will execute.

// the type context.
// This works around the fact that operators cannot be specified with a
// qualified name (i.e. only `(+)` works, `Float.(+)` doesn't).
if (funcName.isOperator() && lookupContext->isTypeContext()) {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the tip! Done.

notAFuncDecl = true;
continue;
}
if (hasValidTypeCtx.hasValue()) {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

}
// If function declaration could not be resolved, emit the appropriate
// diagnostic.
if (!resolvedFuncDecl) {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

// If function declaration could not be resolved, emit the appropriate
// diagnostic.
if (!resolvedFuncDecl) {
if (results.empty()) {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

- Add @differentiable access control check to primal as well as adjoint.
- Add @differentiable access control test.
- Add diagnostic for differentiating void functions.
@dan-zheng
Copy link
Contributor Author

@rxwei
Could you please re-review? I made some slightly non-trivial changes in 47f49f6.

@rxwei
Copy link
Contributor

rxwei commented Jun 15, 2018

LGTM

@dan-zheng
Copy link
Contributor Author

Good idea about renaming @_versioned to @usableFromInline, done.

@dan-zheng
Copy link
Contributor Author

@swift-ci Please test tensorflow

@rxwei rxwei self-assigned this Jun 15, 2018
@rxwei rxwei merged commit 7bea477 into swiftlang:tensorflow Jun 15, 2018
@dan-zheng dan-zheng added the tensorflow This is for "tensorflow" branch PRs. label Jun 15, 2018
marcrasi pushed a commit that referenced this pull request Jun 18, 2018
…` method. (#17246)

* [AutoDiff] Update @differentiable attribute, refactor `lookupFuncDecl` method.

- Add adjoint access level check to @differentiable attribute.
  - If the original function is "exported" (public or @_versioned), then the
    adjoint must also be exported.
- Generalize `lookupFuncDecl` function and add it as a method to `TypeChecker`
  so that it can be used for type-checking #adjoint expression in a later
  commit.

* Refactoring/clean up.

Addresses comments from @rxwei.

* Add/fix @differentiable attribute diagnostics, clean up.

- Add @differentiable access control check to primal as well as adjoint.
- Add @differentiable access control test.
- Add diagnostic for differentiating void functions.

* Preemptively rename @_versioned to @usableFromInline.
marcrasi pushed a commit that referenced this pull request Jun 22, 2018
…` method. (#17246)

* [AutoDiff] Update @differentiable attribute, refactor `lookupFuncDecl` method.

- Add adjoint access level check to @differentiable attribute.
  - If the original function is "exported" (public or @_versioned), then the
    adjoint must also be exported.
- Generalize `lookupFuncDecl` function and add it as a method to `TypeChecker`
  so that it can be used for type-checking #adjoint expression in a later
  commit.

* Refactoring/clean up.

Addresses comments from @rxwei.

* Add/fix @differentiable attribute diagnostics, clean up.

- Add @differentiable access control check to primal as well as adjoint.
- Add @differentiable access control test.
- Add diagnostic for differentiating void functions.

* Preemptively rename @_versioned to @usableFromInline.
marcrasi pushed a commit that referenced this pull request Jun 28, 2018
…` method. (#17246)

* [AutoDiff] Update @differentiable attribute, refactor `lookupFuncDecl` method.

- Add adjoint access level check to @differentiable attribute.
  - If the original function is "exported" (public or @_versioned), then the
    adjoint must also be exported.
- Generalize `lookupFuncDecl` function and add it as a method to `TypeChecker`
  so that it can be used for type-checking #adjoint expression in a later
  commit.

* Refactoring/clean up.

Addresses comments from @rxwei.

* Add/fix @differentiable attribute diagnostics, clean up.

- Add @differentiable access control check to primal as well as adjoint.
- Add @differentiable access control test.
- Add diagnostic for differentiating void functions.

* Preemptively rename @_versioned to @usableFromInline.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

tensorflow This is for "tensorflow" branch PRs.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants