Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Atom constructors can be private #9692

Merged
merged 74 commits into from
Apr 29, 2024
Merged
Show file tree
Hide file tree
Changes from 72 commits
Commits
Show all changes
74 commits
Select commit Hold shift + click to select a range
a762f17
Add some parse tests
Akirathan Apr 12, 2024
e0eed43
Fix docs
Akirathan Apr 12, 2024
9750ef8
Parser supports private constructor definitions
Akirathan Apr 16, 2024
4b79760
TreeToIr handles private constructor
Akirathan Apr 16, 2024
957ac75
Add some ErrorCompilerTest
Akirathan Apr 16, 2024
9c07f84
Add PrivateConstructorAnalysis compiler pass
Akirathan Apr 17, 2024
0366e68
Add some rust tests
Akirathan Apr 17, 2024
c881214
fmt
Akirathan Apr 17, 2024
421dd6e
Add some tests for the runtime access check.
Akirathan Apr 17, 2024
dd5f590
Refactor FunctionSchema ctor to builder pattern.
Akirathan Apr 18, 2024
1228174
Add Private_Access builtin error
Akirathan Apr 18, 2024
04d0f5e
Add projectPrivate field to FunctionSchema and IR-related types
Akirathan Apr 18, 2024
ab617f1
If type has one project-private ctor, all ctors are project-private
Akirathan Apr 18, 2024
770de5f
AtomConstructor generates Functions with optional projectPrivate field
Akirathan Apr 18, 2024
4275440
fix typos in docs
Akirathan Apr 18, 2024
2140e36
InvokeFunctionNode checks private access
Akirathan Apr 18, 2024
c0266ca
fmt
Akirathan Apr 18, 2024
09d3e2f
GetFieldNode is EnsoRootNode
Akirathan Apr 18, 2024
eefc514
fix test build
Akirathan Apr 18, 2024
25089ee
InvokeFunctionNode also checks private constructor access
Akirathan Apr 18, 2024
c8c0bb1
Merge branch 'refs/heads/develop' into wip/akirathan/8836-private-ctors
Akirathan Apr 18, 2024
1cc1262
QualifiedAccessorNode extends EnsoRootNode
Akirathan Apr 18, 2024
6f64272
fmt
Akirathan Apr 18, 2024
aef6e55
Fix PassesTest
Akirathan Apr 19, 2024
ead434d
EnsoRootNode.moduleScope may be null
Akirathan Apr 19, 2024
a53a2d1
Update changelog
Akirathan Apr 19, 2024
85dca02
Improve error message
Akirathan Apr 19, 2024
f739013
fmt
Akirathan Apr 19, 2024
52fdf52
Move some tests from runtime-integration-tests to Base_Tests
Akirathan Apr 19, 2024
e007668
Private fields and constructors are not exposed to interop
Akirathan Apr 19, 2024
16f6bc9
Remove unused private field
Akirathan Apr 19, 2024
1cc47f1
Update encalpsulation docs with polyglot access section
Akirathan Apr 19, 2024
d0b99cb
JS code does not throw panic when private field is accessed
Akirathan Apr 19, 2024
8210fc3
fmt
Akirathan Apr 19, 2024
07a5504
Remove unused method from TestBase
Akirathan Apr 22, 2024
24e7eaf
Update engine/runtime-parser/src/main/scala/org/enso/compiler/core/ir…
Akirathan Apr 22, 2024
2e02d01
Remove private type from docs
Akirathan Apr 22, 2024
500a5e2
Add comment to test.
Akirathan Apr 22, 2024
640665b
Only Type has isProjectPrivate field, not AtomConstructor.
Akirathan Apr 22, 2024
47da50e
IsInSameProject check uses == on Package<TruffleFile>.
Akirathan Apr 22, 2024
11e1707
Ensure that Private_Spec tests are run as part of Base_Tests
Akirathan Apr 22, 2024
03b5199
Fix a private access test in an unnamed module
Akirathan Apr 22, 2024
eaeb44c
Atom.hasMembers is false if it is project-private
Akirathan Apr 22, 2024
f273570
Use more convenient array initializer for empty array in Java.
Akirathan Apr 22, 2024
ff86608
Use Test.expect_panic
Akirathan Apr 22, 2024
256e7ac
Update engine/runtime-parser/src/main/scala/org/enso/compiler/core/ir…
Akirathan Apr 22, 2024
74dd95c
Better error message in compiler
Akirathan Apr 22, 2024
7b0b10a
fmt
Akirathan Apr 22, 2024
19092a9
Type.isProjectPrivate field is final
Akirathan Apr 22, 2024
b56dc0e
Add more tests
Akirathan Apr 22, 2024
0401e07
IRDumper skips documentation comment metadata
Akirathan Apr 22, 2024
492f309
Pattern matching on private constructors is checked during compilation
Akirathan Apr 23, 2024
e6061a6
Update engine/runtime/src/main/java/org/enso/interpreter/runtime/data…
Akirathan Apr 23, 2024
371ed63
Revert: no priv cons check in Patterns compiler pass
Akirathan Apr 23, 2024
fa25337
Merge remote-tracking branch 'origin/wip/akirathan/8836-private-ctors…
Akirathan Apr 23, 2024
52b4b48
Fix typo after merge
Akirathan Apr 23, 2024
cbdaf85
PrivateConstructorAnalysis pass handles also patterns
Akirathan Apr 23, 2024
c2540b2
Add test for pattern matching on private constructor from same project
Akirathan Apr 23, 2024
4f6f8db
Revert PrivateConstructorAnalysis pass.
Akirathan Apr 24, 2024
c983c7f
PrivateConstructor error is a Resolution error, not Pattern error.
Akirathan Apr 24, 2024
4ba8b53
Add PrivateSymbolAnalysis pass
Akirathan Apr 25, 2024
6ac8d8a
Fix project-private type recognition in RuntimeStubsGenerator
Akirathan Apr 25, 2024
395544f
Add a failing test on private constructor to parser
Akirathan Apr 25, 2024
7c91a0b
Merge branch 'refs/heads/develop' into wip/akirathan/8836-private-ctors
Akirathan Apr 25, 2024
fcf2db5
[WIP] to_body_statement deals with Invalid(Private(_))
Akirathan Apr 26, 2024
4a11104
Fix
kazcw Apr 29, 2024
fe93ffa
Merge branch 'refs/heads/develop' into wip/akirathan/8836-private-ctors
Akirathan Apr 29, 2024
656124a
fmt
Akirathan Apr 29, 2024
e70dba7
InvokeFunctionNode.makePrivateAccessPanic is behind TruffleBoundary
Akirathan Apr 29, 2024
d0ab649
Fix the polyglot contract for private members
Akirathan Apr 29, 2024
fc0b0db
Fix improved method name in Auto_Constructor_Instrumentation_Spec.enso
Akirathan Apr 29, 2024
70ee2b3
Private_Access error has qualified project names
Akirathan Apr 29, 2024
85e851b
Add TruffleBoundary to fix native-image build
Akirathan Apr 29, 2024
c0125a0
Run prettier on markdown
Akirathan Apr 29, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -1127,6 +1127,7 @@
- [Autoscoped constructors][9190]
- [Allow Oracle GraalVM JDK][9322]
- [`Table.join` can access its `right` argument][9410]
- [Atom constructors can be project-private][9692]

[3227]: https://github.com/enso-org/enso/pull/3227
[3248]: https://github.com/enso-org/enso/pull/3248
Expand Down Expand Up @@ -1287,6 +1288,7 @@
[8867]: https://github.com/enso-org/enso/pull/8867
[9190]: https://github.com/enso-org/enso/pull/9190
[9322]: https://github.com/enso-org/enso/pull/9322
[9692]: https://github.com/enso-org/enso/pull/9692
[9410]: https://github.com/enso-org/enso/pull/9410

# Enso 2.0.0-alpha.18 (2021-10-12)
Expand Down
26 changes: 26 additions & 0 deletions distribution/lib/Standard/Base/0.0.0-dev/src/Errors/Common.enso
Original file line number Diff line number Diff line change
Expand Up @@ -307,6 +307,32 @@ type Not_Invokable
to_display_text : Text
to_display_text self = "Type error: expected a function, but got "+self.target.to_display_text+"."

@Builtin_Type
type Private_Access
## PRIVATE
Akirathan marked this conversation as resolved.
Show resolved Hide resolved
An error that occurs when a private (project-private) method is called from a different
project.

Arguments:
- this_project_name: Optional qualified name of the current (caller) project.
- target_project_name: Optional qualified name name of the project of callee.
- target_method_name: The name of the target method call that is project-private and thus cannot be called.
Error (this_project_name : (Text | Nothing)) (target_project_name : (Text | Nothing)) (target_method_name : Text)

## PRIVATE
Convert the Private_Access error to a human-readable format.
to_display_text : Text
to_display_text self =
this_proj = if self.this_project_name.is_nothing then "unknown project" else "project '"+self.this_project_name+"'"
target_proj = if self.target_project_name.is_nothing then "unknown project" else "project '"+self.target_project_name+"'"
"Private access error: The project-private method '"
+ self.target_method_name
+ "' in "
+ target_proj
+ " cannot be accessed from "
+ this_proj
+ "."

@Builtin_Type
type Unsupported_Argument_Types
## PRIVATE
Expand Down
15 changes: 5 additions & 10 deletions docs/semantics/encapsulation.md
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,10 @@ Methods on types (or on modules) can be specified private. To check whether a
private method is accessed only from within the same project, a runtime check
must be performed, as this cannot be checked during the compilation.

### Polyglot access
No polyglot foreign code can access private entities. For all the foreign code,
private entities are not visible.

## Example

Lib/src/Pub_Type.enso:
Expand All @@ -87,8 +91,6 @@ type Pub_Type
Constructor field
private priv_method self = ...
pub_method self = self.field.to_text

private type Priv_Type
```

Lib/src/Methods.enso:
Expand All @@ -104,26 +106,21 @@ Lib/src/Internal/Helpers.enso:
# Mark the whole module as private
private

# OK to import private types in the same project
import project.Pub_Type.Priv_Type
```

Lib/src/Main.enso:

```
import project.Pub_Type.Pub_Type
export project.Pub_Type.Pub_Type

import project.Pub_Type.Priv_Type # OK - we can import private types in the same project.
export project.Pub_Type.Priv_Type # Failes at compile time - re-exporting private types is forbidden.
```

tmp.enso:

```
from Lib import Pub_Type
import Lib.Pub_Type.Priv_Type # Fails during compilation
import Lib.Methods
import Lib.Internal.Helpers # Fails during compilation - cannot import private module

main =
# This constructor is not private, we can use it here.
Expand All @@ -133,8 +130,6 @@ main =
Pub_Type.priv_method self=obj # Runtime failure
obj.pub_method # OK

Lib.Pub_Type.Priv_Type # Fails at runtime - accessing private types via FQN is forbidden

Methods.pub_stat_method 1 2 # OK
Methods.priv_stat_method # Fails at runtime
```
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@ class Function(val value: Value) {
*/
def execute(args: AnyRef*): Value = value.execute(args: _*)

/** Helper method for java that just delegates to the other execute method */
def execute(): Value = value.execute()

/** Checks function equality by checking the identity of the underlying
* objects.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
import java.util.stream.Collectors;
import org.enso.compiler.core.IR;
import org.enso.compiler.core.ir.MetadataStorage;
import org.enso.compiler.pass.IRPass.IRMetadata;
import org.enso.compiler.pass.resolve.DocumentationComments;

/**
* Represents a node in the GraphViz graph.
Expand Down Expand Up @@ -84,6 +86,9 @@ static class Builder {
private Map<String, String> additionalAttrs = new HashMap<>();
private Object object;

private static final List<Class<? extends IRMetadata>> metadataToSkip =
List.of(DocumentationComments.Doc.class);

static Builder fromObject(Object obj) {
var className = className(obj);
var id = Utils.id(obj);
Expand Down Expand Up @@ -129,8 +134,10 @@ static Builder fromIr(IR ir) {
ir.passData()
.map(
(pass, metadata) -> {
var metaName = metadata.metadataName();
bldr.addLabelLine(" - " + metaName);
if (!metadataToSkip.contains(metadata.getClass())) {
var metaName = metadata.metadataName();
bldr.addLabelLine(" - " + metaName);
}
return null;
});
} else {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
package org.enso.compiler.pass.analyse;

import java.util.List;
import java.util.UUID;
import org.enso.compiler.context.InlineContext;
import org.enso.compiler.context.ModuleContext;
import org.enso.compiler.core.IR;
import org.enso.compiler.core.ir.Expression;
import org.enso.compiler.core.ir.Module;
import org.enso.compiler.core.ir.expression.errors.Syntax;
import org.enso.compiler.core.ir.expression.errors.Syntax.InconsistentConstructorVisibility$;
import org.enso.compiler.core.ir.module.scope.Definition;
import org.enso.compiler.pass.IRPass;
import scala.collection.immutable.Seq;
import scala.jdk.javaapi.CollectionConverters;

/**
* Ensures that all type definitions have either all constructors public, or all constructors
* private.
*/
public final class PrivateConstructorAnalysis implements IRPass {
Akirathan marked this conversation as resolved.
Show resolved Hide resolved
public static final PrivateConstructorAnalysis INSTANCE = new PrivateConstructorAnalysis();

private UUID uuid;

private PrivateConstructorAnalysis() {}

@Override
public void org$enso$compiler$pass$IRPass$_setter_$key_$eq(UUID v) {
this.uuid = v;
}

@Override
public UUID key() {
return uuid;
}

@Override
public Seq<IRPass> precursorPasses() {
List<IRPass> passes = List.of(PrivateModuleAnalysis.INSTANCE);
return CollectionConverters.asScala(passes).toList();
}

@Override
public Seq<IRPass> invalidatedPasses() {
Object obj = scala.collection.immutable.Nil$.MODULE$;
return (scala.collection.immutable.List<IRPass>) obj;
}

@Override
public Module runModule(Module ir, ModuleContext moduleContext) {
var newBindings =
ir.bindings()
.map(
binding -> {
if (binding instanceof Definition.Type type) {
var privateCtorsCnt = type.members().filter(ctor -> ctor.isPrivate()).size();
var publicCtorsCnt = type.members().filter(ctor -> !ctor.isPrivate()).size();
var ctorsCnt = type.members().size();
if (!(privateCtorsCnt == ctorsCnt || publicCtorsCnt == ctorsCnt)) {
assert type.location().isDefined();
return Syntax.apply(
type.location().get(),
InconsistentConstructorVisibility$.MODULE$,
type.passData(),
type.diagnostics());
}
}
return binding;
});
return ir.copy(
ir.imports(),
ir.exports(),
newBindings,
ir.location(),
ir.passData(),
ir.diagnostics(),
ir.id());
}

/** Not supported on a single expression. */
@Override
public Expression runExpression(Expression ir, InlineContext inlineContext) {
return ir;
}

@Override
public <T extends IR> T updateMetadataInDuplicate(T sourceIr, T copyOfIr) {
return IRPass.super.updateMetadataInDuplicate(sourceIr, copyOfIr);
}
}
Loading
Loading