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

feat: generalized imports supporting pattern matching and selective field import #3076

Merged
merged 56 commits into from
Jan 28, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
56 commits
Select commit Hold shift + click to select a range
b46e72a
first shot at #2354
ggreif Jan 27, 2022
e6e9915
add test
ggreif Jan 27, 2022
67500bf
improve a bit
ggreif Jan 27, 2022
2d40582
unit grooming
ggreif Jan 27, 2022
1556274
cleaner
ggreif Jan 27, 2022
3b120ee
resolve the type error at the access site
ggreif Jan 27, 2022
bcf3fcb
resolve the module vs. field of module ambiguity
ggreif Jan 27, 2022
59efd68
thread the module note through
ggreif Jan 27, 2022
957f912
clean up
ggreif Jan 27, 2022
a1ee29c
get the module `VarE`'s type right
ggreif Jan 27, 2022
91c3708
cleanup
ggreif Jan 27, 2022
8d7fb3c
make it `'import' <pat_nullary> '='? <text>`
ggreif Jan 27, 2022
8fe6866
pointless
ggreif Jan 27, 2022
ddcef0f
also pointless
ggreif Jan 27, 2022
f581947
Update src/mo_frontend/parser.mly
ggreif Jan 27, 2022
0eff5af
capture the entire pattern
ggreif Jan 27, 2022
999d654
cleanups
ggreif Jan 27, 2022
c32448f
make `comp_unit_of_prog` linear-time
ggreif Jan 27, 2022
58c629c
Revert "pointless"
ggreif Jan 27, 2022
ad314b7
Revert "also pointless"
ggreif Jan 27, 2022
2e9df25
use modern syntax
ggreif Jan 27, 2022
7293902
fix repl tests
ggreif Jan 27, 2022
93dcc88
a few dodgy imports
ggreif Jan 28, 2022
1a0a069
accept
ggreif Jan 28, 2022
e72ce22
more failure modes
ggreif Jan 28, 2022
d43c7ab
ignore explicit imports for now
ggreif Jan 28, 2022
3669465
ocamlformat
ggreif Jan 28, 2022
6efb5f6
mention explicit imports
ggreif Jan 28, 2022
b109d6d
typo
ggreif Jan 28, 2022
4c94e00
teach IR typechecker to reject refutable import patterns
ggreif Jan 28, 2022
1eef8dc
document the new syntax for imports
ggreif Jan 28, 2022
e3ee5f1
show how specific bindings can be imported
ggreif Jan 28, 2022
968cadc
demonstrate renaming on import
ggreif Jan 28, 2022
9c911ca
it is `<pat>` now
ggreif Jan 28, 2022
2c3f4aa
Update doc/modules/language-guide/pages/overview.adoc
ggreif Jan 28, 2022
2503343
DRY
ggreif Jan 28, 2022
0e0b65a
Update src/docs/extract.ml
ggreif Jan 28, 2022
656b48c
Update doc/modules/language-guide/pages/language-manual.adoc
ggreif Jan 28, 2022
9dc287a
Update doc/modules/language-guide/pages/language-manual.adoc
ggreif Jan 28, 2022
c59e85a
Update doc/modules/language-guide/pages/language-manual.adoc
ggreif Jan 28, 2022
a2aeae4
Update src/ir_def/check_ir.ml
ggreif Jan 28, 2022
d0dff31
remove cruft
ggreif Jan 28, 2022
2d9b797
use the coverage checker to reject refutable import patterns
ggreif Jan 28, 2022
37b2838
Update doc/modules/language-guide/pages/language-manual.adoc
ggreif Jan 28, 2022
c763ff8
Update src/ir_def/check_ir.ml
ggreif Jan 28, 2022
feec77b
back
ggreif Jan 28, 2022
988c27f
forgotten
ggreif Jan 28, 2022
c98c798
add example
ggreif Jan 28, 2022
a3ac786
ooops
ggreif Jan 28, 2022
2ae3cbb
Update doc/modules/language-guide/pages/language-manual.adoc
ggreif Jan 28, 2022
3e8226c
Update language-manual.adoc
ggreif Jan 28, 2022
b5ed7d0
reindent
ggreif Jan 28, 2022
1ddcf93
tweak again
ggreif Jan 28, 2022
95a93a8
Merge branch 'master' into gabor/deconstruct-import
ggreif Jan 28, 2022
ca01c14
move an item
ggreif Jan 28, 2022
af6941a
demonstrate that actor methods cannot be imported explicitly
ggreif Jan 28, 2022
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
14 changes: 13 additions & 1 deletion Changelog.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,22 @@
# Motoko compiler changelog

## 0.6.21 (2022-01-28)

* motoko (`moc`)

* Implement a limited form of explicit symbol imports (#3076)
* Fix: insert critical overflow checks preventing rare heap corruptions
in out-of-memory allocation and stable variable serialization (#3077)
* Implement support for 128-bit Cycles-API (#3042)

* motoko-base

* 128-bit Cycles-API support (#???)

## 0.6.20 (2022-01-11)

* motoko

* Fix: insert critical overflow checks preventing rare heap corruptions in out-of-memory allocation and stable variable serialization (#3077)
* Implement support for `heartbeat` system methods (thanks to ninegua) (#2971)

* motoko-base
Expand Down
2 changes: 1 addition & 1 deletion doc/modules/language-guide/examples/grammar.txt
Original file line number Diff line number Diff line change
Expand Up @@ -298,7 +298,7 @@
<obj_body>

<imp> ::=
'import' <id>? '='? <text>
'import' <pat_nullary> '='? <text>
Copy link
Contributor

Choose a reason for hiding this comment

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

Is there any reason this isn't just <pat> as for let?

Copy link
Contributor Author

@ggreif ggreif Jan 28, 2022

Choose a reason for hiding this comment

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

We don't want (?(#foo)) here, do we? <pat> just doesn't have any sensible use-case in this place.

Copy link
Contributor

Choose a reason for hiding this comment

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

Yes, but I don't think we should enforce typing properties using the grammar.
Also, it keeps the grammar closer to the informal language reference.
Plus, you might want a type annotation on the pattern without having to parenthesize it.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Can I do this tomorrow in a new PR? I am totally burnt out, sorry.

Copy link
Contributor

Choose a reason for hiding this comment

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

Of course.

Copy link
Contributor

Choose a reason for hiding this comment

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

Tomorrow is saturday. Monday!

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It doesn't work: #3076 (comment)


<prog> ::=
<list(<imp>, ';')> <list(<dec>, ';')>
Expand Down
20 changes: 13 additions & 7 deletions doc/modules/language-guide/pages/language-manual.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -397,7 +397,7 @@ The syntax of an _import_ `<imp>` is as follows:

```bnf
<imp> ::= imports
import <id>? =? <url>
import <pat> =? <url>

<url> ::=
"<filepath>" import module from relative <filepath>.mo
Expand All @@ -406,7 +406,12 @@ The syntax of an _import_ `<imp>` is as follows:
"canister:<name>" import external actor by <name>
```

An import introduces a resource named '<id>?' referring to a local source module, module from a package of modules, or canister (imported as an actor).
An import introduces a resource referring to a local source module, module from a package of modules, or canister (imported as an actor).
The contents of the resource are bound to `<pat>`.

Though typically a simple identifier, `<id>`, `<pat>` can also be any composite pattern binding selective components of the resource.

The pattern must be irrefutable.

[[syntax-libraries]]
=== Libraries
Expand Down Expand Up @@ -1198,24 +1203,24 @@ Installation is (necessarily) asynchronous.
[[imports]]
=== Imports and Urls

An import `import <id>? =? <url>` declares an optional identifier `<id>?` bound to the contents of the text literal `<url>`. (`<id>?`, when absent, defaults to some fresh identifier `<id>`.)
An import `import <pat> =? <url>` declares a pattern `<pat>` bound to the contents of the text literal `<url>`.

`<url>` is a text literal that designates some resource: a local library specified with a relative path, a named module from a named package,
or an external canister, referenced either by numeric canister id or by a named alias, and imported as a {proglang} actor.

In detail, if `<url>` is of the form:

* `"<filepath>"` then `<id>` is bound to the library module defined in file `<filepath>.mo`.
* `"<filepath>"` then `<pat>` is bound to the library module defined in file `<filepath>.mo`.
`<filepath>` is interpreted relative to the absolute location of the enclosing file.
Note the `.mo` extension is implicit and should _not_ be included in `<url>`.
For example, `import U "lib/Util"` defines `U` to reference the module in local file
`./lib/Util`.

* `"mo:<package-name>/<path>"` then `<id>` is bound to the library module defined in file `<package-path>/<path>.mo` in directory `<package-path>` referenced by package alias `<package-name>`.
* `"mo:<package-name>/<path>"` then `<pat>` is bound to the library module defined in file `<package-path>/<path>.mo` in directory `<package-path>` referenced by package alias `<package-name>`.
The mapping from `<package-name>` to `<package-path>` is determined by a compiler command-line argument `--package <package-name> <package-path>`. For example, `import L "mo:base/List"` defines `L` to reference the `List` library in
package alias `base`.

* `"ic:<canisterid>"` then `<id>` is bound to a {proglang} actor whose {proglang} type is determined by the canister's IDL interface.
* `"ic:<canisterid>"` then `<pat>` is bound to a {proglang} actor whose {proglang} type is determined by the canister's IDL interface.
The IDL interface of canister `<canisterid>` must be found in file `<actorpath>/<canisterid>.did`.
The compiler assumes that `<actorpath>` is specified by command line argument `--actor-idl <actorpath>` and that file `<actorpath>/<canisterid>.did` exists.
For example, `import C "ic:lg264-qjkae"` defines `C` to reference the actor with canister id `lg264-qjkae` and IDL file `lg264-qjkae.did`.
Expand All @@ -1229,8 +1234,9 @@ In detail, if `<url>` is of the form:
The case sensitivity of file references depends on the host operating system so it is recommended not to distinguish resources by filename casing alone.

(Remark: when building multi-canister projects with the {sdk-short-name}, {proglang} programs can typically import canisters by alias (e.g. `import C "canister:counter"`), without specifying low-level canister ids (e.g. `import C "ic:lg264-qjkae"`).
The SDK tooling takes care of supplying the appropriate command-line arguments to the {proglang} compiler).
The SDK tooling takes care of supplying the appropriate command-line arguments to the {proglang} compiler.)

(Remark: sensible choices for `<pat>` are identifiers, such as ``Array``, or object patterns like ``{ cons; nil = empty }``, which allow selective importing of individual fields, under original or other names.)

[[decl-field]]
=== Declaration fields
Expand Down
11 changes: 11 additions & 0 deletions doc/modules/language-guide/pages/modules-and-imports.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,17 @@ import Result "mo:base/Result";

Notice that the import declaration includes the `+mo:+` prefix to identify the module as a {proglang} module and that the declaration does not include the `+.mo+` file type extension.

Above example uses an identifier pattern to import modules wholesale, but you can also selectively import
a subset of symbols from a module by resorting to the object pattern syntax:

[source,motoko]
----
import { map, find, foldLeft = fold } = "mo:base/Array";
----

In this example, the functions `+map+` and `+find+` are imported unaltered, while the `+foldLeft+`
function is renamed to `+fold+`.

== Importing local files

Another common approach to writing programs in {proglang} involves splitting up the source code into different modules.
Expand Down
5 changes: 5 additions & 0 deletions doc/modules/language-guide/pages/overview.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,11 @@ Inspirations: Java, JavaScript, C#, Swift, Pony, ML, Haskell

(`import MyLib "src/MyLib"` imports a library from the local file system.)

Specific bindings can be imported from the module using object patterns
....
import { cons; nil } = "mo:base/List";
....

=== Libraries

[source, motoko]
Expand Down
12 changes: 7 additions & 5 deletions src/docs/extract.ml
Original file line number Diff line number Diff line change
Expand Up @@ -51,16 +51,18 @@ and class_doc = {

let un_prog prog =
let comp_unit = Mo_def.CompUnit.comp_unit_of_prog true prog in
let Syntax.{ imports; body } = comp_unit.it in
let open Syntax in
let { imports; body } = comp_unit.it in
let imports =
List.map
List.concat_map
(fun i ->
let alias, path, _ = i.it in
(alias.it, path))
match i.it with
| { it = VarP alias; _ }, path, _ -> [ (alias.it, path) ]
| _ -> []) (* FIXME: explicit imports #3078 *)
imports
in
match body.it with
| Syntax.ModuleU (_, decs) -> Ok (imports, decs)
| ModuleU (_, decs) -> Ok (imports, decs)
| _ -> Error "Couldn't find a module expression"

module PosTable = Trivia.PosHashtbl
Expand Down
1 change: 0 additions & 1 deletion src/ir_def/ir_utils.ml
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,3 @@ let rec is_irrefutable p = match p.it with
| AltP (pat1, _) -> is_irrefutable pat1
| WildP | VarP _ -> true
| TagP _ | LitP _ | OptP _ -> false

5 changes: 5 additions & 0 deletions src/lib/lib.ml
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,11 @@ struct
else
None

let starts_with prefix s = (* in OCaml 4.13 *)
match chop_prefix prefix s with
| Some _ -> true
| _ -> false

let chop_suffix suffix s =
let suffix_len = String.length suffix in
let s_len = String.length s in
Expand Down
1 change: 1 addition & 0 deletions src/lib/lib.mli
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,7 @@ sig
val split : string -> char -> string list
val breakup : string -> int -> string list
val find_from_opt : (char -> bool) -> string -> int -> int option
val starts_with : string -> string -> bool
val chop_prefix : string -> string -> string option
val chop_suffix : string -> string -> string option
val lightweight_escaped : string -> string
Expand Down
4 changes: 2 additions & 2 deletions src/lowering/desugar.ml
Original file line number Diff line number Diff line change
Expand Up @@ -858,7 +858,7 @@ let link_declarations imports (cu, flavor) =


let transform_import (i : S.import) : import_declaration =
let (id, f, ir) = i.it in
let (p, f, ir) = i.it in
let t = i.note in
assert (t <> T.Pre);
let rhs = match !ir with
Expand All @@ -869,7 +869,7 @@ let transform_import (i : S.import) : import_declaration =
varE (var (id_of_full_path "@prim") t)
| S.IDLPath (fp, canister_id) ->
primE (I.ActorOfIdBlob t) [blobE canister_id]
in [ letD (var id.it t) rhs ]
in [ letP (pat p) rhs ]

let transform_unit_body (u : S.comp_unit_body) : Ir.comp_unit =
match u.it with
Expand Down
2 changes: 1 addition & 1 deletion src/lowering/desugar.mli
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
open Mo_def
open Ir_def

(* These declaratoins are all internal, either from prelude (@-prefixed)
(* These declarations are all internal, either from prelude (@-prefixed)
or to bring libraries into scope *)
type import_declaration = Ir.dec list

Expand Down
13 changes: 7 additions & 6 deletions src/mo_def/compUnit.ml
Original file line number Diff line number Diff line change
Expand Up @@ -23,15 +23,16 @@ let comp_unit_of_prog as_lib (prog : prog) : comp_unit =
let open Source in
let f = prog.note in

let finish imports u = { it = { imports; body = u }; note = f; at = no_region } in
let finish imports u =
{ it = { imports = List.rev imports; body = u }; note = f; at = no_region } in
let prog_typ_note = { empty_typ_note with note_typ = Type.unit } in

let rec go imports ds : comp_unit =
match ds with
(* imports *)
| {it = LetD ({it = VarP n; _}, ({it = ImportE (url, ri); _} as e)); _} :: ds' ->
let i : import = { it = (n, url, ri); note = e.note.note_typ; at = e.at } in
go (imports @ [i]) ds'
| {it = LetD (p, ({it = ImportE (url, ri); _} as e)); _} :: ds' ->
let i : import = { it = (p, url, ri); note = e.note.note_typ; at = e.at } in
go (i :: imports) ds'

(* terminal expressions *)
| [{it = ExpD ({it = ObjBlockE ({it = Type.Module; _}, fields); _} as e); _}] when as_lib ->
Expand Down Expand Up @@ -88,9 +89,9 @@ let obj_decs obj_sort at note id_opt fields =
let decs_of_lib (cu : comp_unit) =
let open Source in
let { imports; body = cub; _ } = cu.it in
let import_decs = List.map (fun { it = (id, fp, ri); at; note} ->
let import_decs = List.map (fun { it = (pat, fp, ri); at; note} ->
{ it = LetD (
{ it = VarP id; at; note; },
pat,
{ it = ImportE (fp, ri);
at;
note = { note_typ = note; note_eff = Type.Triv} });
Expand Down
2 changes: 1 addition & 1 deletion src/mo_def/syntax.ml
Original file line number Diff line number Diff line change
Expand Up @@ -227,7 +227,7 @@ and stab_sig' = (dec list * typ_field list) (* type declarations & stable a
(* Compilation units *)

type import = (import', Type.typ) Source.annotated_phrase
and import' = id * string * resolved_import ref
and import' = pat * string * resolved_import ref

type comp_unit_body = (comp_unit_body', typ_note) Source.annotated_phrase
and comp_unit_body' =
Expand Down
5 changes: 2 additions & 3 deletions src/mo_frontend/parser.mly
Original file line number Diff line number Diff line change
Expand Up @@ -871,9 +871,8 @@ class_body :
(* Programs *)

imp :
| IMPORT xf=id_opt EQ? f=TEXT
{ let _, x = xf "import" $sloc in
let_or_exp true x (ImportE (f, ref Unresolved)) (at $sloc) }
| IMPORT p=pat_nullary EQ? f=TEXT
{ LetD(p, ImportE(f, ref Unresolved) @? at $sloc) @? at $sloc }

start : (* dummy non-terminal to satisfy ErrorReporting.ml, that requires a non-empty parse stack *)
| (* empty *) { () }
Expand Down
14 changes: 6 additions & 8 deletions src/mo_frontend/typing.ml
Original file line number Diff line number Diff line change
Expand Up @@ -2274,7 +2274,6 @@ and gather_dec env scope dec : Scope.t =
{it = VarP id; _},
({it = ObjBlockE (obj_sort, dec_fields); at; _} |
{it = AwaitE { it = AsyncE (_, {it = ObjBlockE ({ it = Type.Actor; _} as obj_sort, dec_fields); at; _}) ; _ }; _ })
(* TODO include RecE? *)
) ->
let decs = List.map (fun df -> df.it.dec) dec_fields in
let open Scope in
Expand Down Expand Up @@ -2357,7 +2356,6 @@ and infer_dec_typdecs env dec : Scope.t =
{it = VarP id; _},
( {it = ObjBlockE (obj_sort, dec_fields); at; _} |
{it = AwaitE { it = AsyncE (_, {it = ObjBlockE ({ it = Type.Actor; _} as obj_sort, dec_fields); at; _}) ; _ }; _ })
(* TODO include RecE? *)
) ->
let decs = List.map (fun {it = {vis; dec; _}; _} -> dec) dec_fields in
let scope = T.Env.find id.it env.objs in
Expand Down Expand Up @@ -2446,6 +2444,11 @@ and infer_block_valdecs env decs scope : Scope.t =
) (env, scope) decs
in scope'

and is_import d =
match d.it with
| LetD (_, {it = ImportE _; _}) -> true
| _ -> false

and infer_dec_valdecs env dec : Scope.t =
match dec.it with
| ExpD _ ->
Expand All @@ -2468,7 +2471,7 @@ and infer_dec_valdecs env dec : Scope.t =
Scope.{empty with val_env = T.Env.singleton id.it obj_typ}
| LetD (pat, exp) ->
let t = infer_exp {env with pre = true} exp in
let ve' = check_pat_exhaustive warn env t pat in
let ve' = check_pat_exhaustive (if is_import dec then local_error else warn) env t pat in
Scope.{empty with val_env = ve'}
| VarD (id, exp) ->
let t = infer_exp {env with pre = true} exp in
Expand Down Expand Up @@ -2533,11 +2536,6 @@ let is_actor_dec d =
obj_sort.it = T.Actor
| _ -> false

let is_import d =
match d.it with
| LetD ({it = VarP n; _}, {it = ImportE _; _}) -> true
| _ -> false

let check_actors scope progs : unit Diag.result =
Diag.with_message_store
(fun msgs ->
Expand Down
1 change: 1 addition & 0 deletions test/fail/empty-module.mo
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
module {}
1 change: 1 addition & 0 deletions test/fail/error-imports.mo
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
import "depri" = "text-module";
1 change: 1 addition & 0 deletions test/fail/nat-module.mo
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
module { public let why = 42 }
2 changes: 1 addition & 1 deletion test/fail/not-static.mo
Original file line number Diff line number Diff line change
@@ -1 +1 @@
import "lib/not-static"
import _ = "lib/not-static"
5 changes: 5 additions & 0 deletions test/fail/ok/error-imports.tc.ok
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
text-module.mo:0.1: warning [M0142], deprecated syntax: an imported library should be a module or named actor class
error-imports.mo:1.8-1.15: type error [M0050], literal of type
Text
does not have expected type
module {}
1 change: 1 addition & 0 deletions test/fail/ok/error-imports.tc.ret.ok
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Return code 1
4 changes: 4 additions & 0 deletions test/fail/ok/refutable-import.tc.ok
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
refutable-import.mo:1.8-1.20: type error [M0145], this pattern of type
module {why : Nat}
does not cover value
{why = 0 or 1 or _}
1 change: 1 addition & 0 deletions test/fail/ok/refutable-import.tc.ret.ok
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Return code 1
2 changes: 1 addition & 1 deletion test/fail/ok/self-import.tc.ok
Original file line number Diff line number Diff line change
@@ -1 +1 @@
self-import.mo:1.1-1.21: import error [M0003], file self-import.mo must not depend on itself
self-import.mo:1.1-1.25: import error [M0003], file self-import.mo must not depend on itself
2 changes: 2 additions & 0 deletions test/fail/ok/type-error-imports.tc.ok
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
type-error-imports.mo:4.8-4.14: type error [M0112], tuple pattern cannot consume expected type
module {}
1 change: 1 addition & 0 deletions test/fail/ok/type-error-imports.tc.ret.ok
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Return code 1
6 changes: 6 additions & 0 deletions test/fail/refutable-import.mo
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import { why = 42 } = "nat-module";

//SKIP run
//SKIP run-ir
//SKIP run-low
//SKIP comp
2 changes: 1 addition & 1 deletion test/fail/self-import.mo
Original file line number Diff line number Diff line change
@@ -1 +1 @@
import "self-import";
import _ = "self-import";
1 change: 1 addition & 0 deletions test/fail/text-module.mo
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
"depri"
4 changes: 4 additions & 0 deletions test/fail/type-error-imports.mo
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import _ "empty-module";
import {} "empty-module";

import (_, _) = "empty-module";
4 changes: 2 additions & 2 deletions test/repl/double-import.sh
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#!/usr/bin/env bash
moc -v -i <<__END__
import "lib/empty";
import "lib/empty";
import _ = "lib/empty";
import _ = "lib/empty";
__END__
4 changes: 2 additions & 2 deletions test/repl/lib/actor-import.mo
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
import "ic:em77e-bvlzu-aq";
import "canister:alias";
import _ = "ic:em77e-bvlzu-aq";
import _ = "canister:alias";
2 changes: 1 addition & 1 deletion test/repl/lib/nested.mo
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import A "nested/a";
import "nested/b";
import _ = "nested/b";

let i = A.i;
2 changes: 1 addition & 1 deletion test/repl/lib/triangle.mo
Original file line number Diff line number Diff line change
@@ -1 +1 @@
import "a"
import _ = "a"
2 changes: 1 addition & 1 deletion test/repl/nested-import.sh
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#!/usr/bin/env bash
moc -v -i <<__END__ | grep Parsing
import "lib/nested";
import _ = "lib/nested";
__END__
2 changes: 0 additions & 2 deletions test/repl/ok/double-import.stdout.ok
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,12 @@ Motoko compiler (source XXX)
-- Interpreting empty.mo:
-- Interpreting stdin:
-- Finished stdin:
let anon-import-1.1 : module {...}
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 guess these are gone, because the wildcard pattern has a side-effect-less RHS.

Copy link
Contributor

Choose a reason for hiding this comment

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

I think its gone because we don't have the optional ? production which would introduce a gensym-ed, anonymous binding (not a wildcard).


-- Parsing stdin:
> -- Checking stdin:
-- Definedness stdin:
-- Interpreting stdin:
-- Finished stdin:
let anon-import-2.1 : module {...}

-- Parsing stdin:
>
Loading