diff --git a/compiler/src/middle_end/anf_utils.re b/compiler/src/middle_end/anf_utils.re index 521b2bc8f5..a09eeeadc8 100644 --- a/compiler/src/middle_end/anf_utils.re +++ b/compiler/src/middle_end/anf_utils.re @@ -14,6 +14,7 @@ module ClearLocationsArg: Anf_mapper.MapArgument = { | Disable_gc => Disable_gc | Unsafe => Unsafe | External_name(name) => External_name(Location.mknoloc(name.txt)) + | Elide_type_info => Elide_type_info }; Location.mknoloc(attr); }, diff --git a/compiler/src/middle_end/linearize.re b/compiler/src/middle_end/linearize.re index 520f016db2..cd23adad61 100644 --- a/compiler/src/middle_end/linearize.re +++ b/compiler/src/middle_end/linearize.re @@ -1997,99 +1997,102 @@ let rec transl_anf_statement = let rec gather_type_metadata = statements => { List.fold_left( - (metadata, {ttop_desc, ttop_env}) => { - switch (ttop_desc) { - | TTopData(decls) => - let info = - List.filter_map( - decl => { - let typath = decl.data_type.type_path; - let id = get_type_id(typath, ttop_env); - switch (decl.data_kind) { - | TDataVariant(cnstrs) => - let type_hash = get_type_hash(decl.data_type); - let descrs = - Datarepr.constructors_of_type(typath, decl.data_type); - let meta = - List.map( - ((_, cstr)) => - ( - compile_constructor_tag(cstr.cstr_tag), - cstr.cstr_name, - switch (cstr.cstr_inlined) { - | None => TupleConstructor - | Some(t) => - let label_names = - switch (t.type_kind) { - | TDataRecord(rfs) => - List.map( - rf => Ident.name(rf.Types.rf_name), - rfs, - ) - | _ => - failwith( - "Impossible: inlined record constructor with non-record underlying type", - ) - }; - RecordConstructor(label_names); - }, - ), - descrs, - ); - Some((ADTMetadata(id, meta), type_hash)); - | TDataRecord(fields) => - let type_hash = get_type_hash(decl.data_type); - Some(( - RecordMetadata( - id, - List.map(field => Ident.name(field.rf_name), fields), - ), - type_hash, - )); - | TDataAbstract => None - }; - }, - decls, - ); - List.append(info, metadata); - | TTopException(ext) => - let ty_id = get_type_id(ext.ext_type.ext_type_path, ttop_env); - let id = ext.ext_id; - let cstr = Datarepr.extension_descr(Path.PIdent(id), ext.ext_type); - [ - ( - ExceptionMetadata( - ty_id, - compile_constructor_tag(cstr.cstr_tag), - cstr.cstr_name, - switch (cstr.cstr_inlined) { - | None => TupleConstructor - | Some(t) => - let label_names = - switch (t.type_kind) { - | TDataRecord(rfs) => - List.map(rf => Ident.name(rf.Types.rf_name), rfs) - | _ => - failwith( - "Impossible: inlined exception record constructor with non-record underlying type", - ) - }; - RecordConstructor(label_names); + (metadata, {ttop_desc, ttop_env, ttop_attributes}) => + if (List.exists(attr => attr.txt == Elide_type_info, ttop_attributes)) { + metadata; + } else { + switch (ttop_desc) { + | TTopData(decls) => + let info = + List.filter_map( + decl => { + let typath = decl.data_type.type_path; + let id = get_type_id(typath, ttop_env); + switch (decl.data_kind) { + | TDataVariant(cnstrs) => + let type_hash = get_type_hash(decl.data_type); + let descrs = + Datarepr.constructors_of_type(typath, decl.data_type); + let meta = + List.map( + ((_, cstr)) => + ( + compile_constructor_tag(cstr.cstr_tag), + cstr.cstr_name, + switch (cstr.cstr_inlined) { + | None => TupleConstructor + | Some(t) => + let label_names = + switch (t.type_kind) { + | TDataRecord(rfs) => + List.map( + rf => Ident.name(rf.Types.rf_name), + rfs, + ) + | _ => + failwith( + "Impossible: inlined record constructor with non-record underlying type", + ) + }; + RecordConstructor(label_names); + }, + ), + descrs, + ); + Some((ADTMetadata(id, meta), type_hash)); + | TDataRecord(fields) => + let type_hash = get_type_hash(decl.data_type); + Some(( + RecordMetadata( + id, + List.map(field => Ident.name(field.rf_name), fields), + ), + type_hash, + )); + | TDataAbstract => None + }; }, + decls, + ); + List.append(info, metadata); + | TTopException(ext) => + let ty_id = get_type_id(ext.ext_type.ext_type_path, ttop_env); + let id = ext.ext_id; + let cstr = Datarepr.extension_descr(Path.PIdent(id), ext.ext_type); + [ + ( + ExceptionMetadata( + ty_id, + compile_constructor_tag(cstr.cstr_tag), + cstr.cstr_name, + switch (cstr.cstr_inlined) { + | None => TupleConstructor + | Some(t) => + let label_names = + switch (t.type_kind) { + | TDataRecord(rfs) => + List.map(rf => Ident.name(rf.Types.rf_name), rfs) + | _ => + failwith( + "Impossible: inlined exception record constructor with non-record underlying type", + ) + }; + RecordConstructor(label_names); + }, + ), + exception_type_hash, ), - exception_type_hash, - ), - ...metadata, - ]; - | TTopModule(decl) => - List.append(gather_type_metadata(decl.tmod_statements), metadata) - | TTopExpr(_) - | TTopInclude(_) - | TTopProvide(_) - | TTopForeign(_) - | TTopLet(_) => metadata - } - }, + ...metadata, + ]; + | TTopModule(decl) => + List.append(gather_type_metadata(decl.tmod_statements), metadata) + | TTopExpr(_) + | TTopInclude(_) + | TTopProvide(_) + | TTopForeign(_) + | TTopLet(_) => metadata + }; + }, [], statements, ); @@ -2283,7 +2286,8 @@ let construct_type_metadata_buffer = type_metadata => { }; let transl_anf_module = - ({statements, env, signature, prog_loc}: typed_program): anf_program => { + ({attributes, statements, env, signature, prog_loc}: typed_program) + : anf_program => { Path_tbl.clear(type_map); Path_tbl.clear(include_map); Path_tbl.clear(module_symbol_map); @@ -2307,7 +2311,10 @@ let transl_anf_module = specs: imports @ value_imports^, path_map: Path_tbl.copy(include_map), }; - let type_metadata_and_hashes = gather_type_metadata(statements); + let elideTypeInfo = + List.exists(attr => attr.txt == Elide_type_info, attributes); + let type_metadata_and_hashes = + elideTypeInfo ? [] : gather_type_metadata(statements); let type_metadata = List.map(((meta, _)) => meta, type_metadata_and_hashes); let metadata = construct_type_metadata_buffer(type_metadata_and_hashes); diff --git a/compiler/src/parsing/well_formedness.re b/compiler/src/parsing/well_formedness.re index 99780b4431..b32206f903 100644 --- a/compiler/src/parsing/well_formedness.re +++ b/compiler/src/parsing/well_formedness.re @@ -319,6 +319,10 @@ let disallowed_attributes = (errs, super) => { name: "externalName", arity: 1, }, + { + name: "elideTypeInfo", + arity: 0, + }, ]; let enter_expression = ({pexp_attributes: attrs} as e) => { @@ -338,6 +342,22 @@ let disallowed_attributes = (errs, super) => { ] | None => () }; + switch ( + List.find_opt( + ({Asttypes.attr_name: {txt}}) => txt == "elideTypeInfo", + attrs, + ) + ) { + | Some({Asttypes.attr_name: {txt, loc}}) => + errs := + [ + AttributeDisallowed( + "`elideTypeInfo` is only allowed on module, record, and variant declarations.", + loc, + ), + ] + | None => () + }; validate_against_known(attrs, known_expr_attributes, "expression"); super.enter_expression(e); }; @@ -395,6 +415,27 @@ let disallowed_attributes = (errs, super) => { } | None => () }; + switch ( + List.find_opt( + ({Asttypes.attr_name: {txt}}) => txt == "elideTypeInfo", + attrs, + ) + ) { + | Some({Asttypes.attr_name: {txt, loc}}) => + switch (desc) { + | PTopModule(_) + | PTopData(_) => () + | _ => + errs := + [ + AttributeDisallowed( + "`elideTypeInfo` is only allowed on module, record, and variant declarations.", + loc, + ), + ] + } + | None => () + }; validate_against_known(attrs, known_expr_attributes, "top-level"); super.enter_toplevel_stmt(top); }; @@ -413,6 +454,10 @@ let disallowed_attributes = (errs, super) => { name: "noExceptions", arity: 0, }, + { + name: "elideTypeInfo", + arity: 0, + }, ]; validate_against_known(attributes, known_module_attributes, "module"); super.enter_parsed_program(prog); diff --git a/compiler/src/typed/typedtree.re b/compiler/src/typed/typedtree.re index d363ff6516..5affae9f69 100644 --- a/compiler/src/typed/typedtree.re +++ b/compiler/src/typed/typedtree.re @@ -29,7 +29,8 @@ type attributes = list(loc(attribute)) and attribute = | Disable_gc | Unsafe - | External_name(loc(string)); + | External_name(loc(string)) + | Elide_type_info; [@deriving sexp] type partial = @@ -635,6 +636,7 @@ type comment = [@deriving sexp] type typed_program = { + attributes, module_name: loc(string), statements: list(toplevel_stmt), env: [@sexp.opaque] Env.t, diff --git a/compiler/src/typed/typedtree.rei b/compiler/src/typed/typedtree.rei index f1d9e1ad6d..6c0bbfea08 100644 --- a/compiler/src/typed/typedtree.rei +++ b/compiler/src/typed/typedtree.rei @@ -30,7 +30,8 @@ type attributes = list(loc(attribute)) and attribute = | Disable_gc | Unsafe - | External_name(loc(string)); + | External_name(loc(string)) + | Elide_type_info; type partial = | Partial @@ -595,6 +596,7 @@ type comment = [@deriving sexp] type typed_program = { + attributes, module_name: loc(string), statements: list(toplevel_stmt), env: Env.t, diff --git a/compiler/src/typed/typemod.re b/compiler/src/typed/typemod.re index 0bf726dd5a..a515430d06 100644 --- a/compiler/src/typed/typemod.re +++ b/compiler/src/typed/typemod.re @@ -1093,6 +1093,13 @@ let type_implementation = (prog: Parsetree.parsed_program) => { let signature = Env.build_signature(normalized_sig, module_name, type_metadata); { + attributes: + Typetexp.type_attributes( + List.filter( + attr => attr.attr_name.txt == "elideTypeInfo", + prog.attributes, + ), + ), module_name: prog.module_name, statements, env: finalenv, diff --git a/compiler/src/typed/typetexp.re b/compiler/src/typed/typetexp.re index 60fbebbf7c..892cb3f1e2 100644 --- a/compiler/src/typed/typetexp.re +++ b/compiler/src/typed/typetexp.re @@ -623,6 +623,7 @@ let type_attributes = attrs => { | ("unsafe", []) => Location.mkloc(Unsafe, loc) | ("externalName", [name]) => Location.mkloc(External_name(name), loc) + | ("elideTypeInfo", []) => Location.mkloc(Elide_type_info, loc) | _ => failwith("type_attributes: impossible by well-formedness") }, attrs, diff --git a/compiler/test/suites/basic_functionality.re b/compiler/test/suites/basic_functionality.re index babefd6e10..e86260ea8d 100644 --- a/compiler/test/suites/basic_functionality.re +++ b/compiler/test/suites/basic_functionality.re @@ -485,6 +485,71 @@ describe("basic functionality", ({test, testSkip}) => { -1, ); + // @elideTypeInfo attribute + + assertRun( + "type_metadata_elided_individual", + {| + @elideTypeInfo + record NoInfoRecord { + noInfo: Number, + } + @elideTypeInfo + enum NoInfoEnum { + NoInfo, + } + record InfoRecord { + info: Number, + } + enum InfoEnum { + Info, + } + assert toString({ noInfo: 2, }: NoInfoRecord) == "" + assert toString(NoInfo: NoInfoEnum) == "" + assert toString({ info: 2, }: InfoRecord) == "{\n info: 2\n}" + assert toString(Info: InfoEnum) == "Info" + |}, + "", + ); + + assertRun( + "type_metadata_elided_submodule", + {| + record Info { + info: Number, + } + + @elideTypeInfo + module NoInfo { + provide record NoInfo { + noInfo: Number, + } + } + assert toString({ noInfo: 2, }: NoInfo.NoInfo) == "" + assert toString({ info: 2, }: Info) == "{\n info: 2\n}" + |}, + "", + ); + + assertRun( + "type_metadata_elided_inside_submodule", + {| + module SubModule { + @elideTypeInfo + provide record NoInfo { + noInfo: Number, + } + + provide record Info { + info: Number, + } + } + assert toString({ noInfo: 2, }: SubModule.NoInfo) == "" + assert toString({ info: 2, }: SubModule.Info) == "{\n info: 2\n}" + |}, + "", + ); + assertFilesize( ~config_fn=smallestFileConfig, "smallest_grain_program", diff --git a/stdlib/array.gr b/stdlib/array.gr index 16330899a5..986e2ece57 100644 --- a/stdlib/array.gr +++ b/stdlib/array.gr @@ -1287,6 +1287,7 @@ provide module Immutable { } // a helper data structure used for building an array piece by piece + @elideTypeInfo record Builder { btail: Array, nodes: List>, diff --git a/stdlib/fs.gr b/stdlib/fs.gr index 9b3aca2843..3c9d6d73c1 100644 --- a/stdlib/fs.gr +++ b/stdlib/fs.gr @@ -1,11 +1,11 @@ /** * Utilities for high-level file system interactions. Utilizes WASI Preview 1 for underlying API - * + * * @example from "fs" include Fs * @example Fs.Utf8.readFile(Path.fromString("baz.txt")) * @example Fs.Utf8.writeFile(Path.fromString("baz.txt"), "Hello World\n") * @example Fs.copy(Path.fromString("foo.txt"), Path.fromString("foocopy.txt")) - * + * * @since v0.7.0 */ module Fs @@ -247,6 +247,7 @@ provide enum WriteMode { Append, } +@elideTypeInfo enum OpenMode { Unlink, RmDir, @@ -538,16 +539,16 @@ let rec removeRecursive = (parentFd, path) => { /** * Removes a file or directory. - * + * * @param removeMode: The type of removal to perform; `RemoveFile` by default * @param baseDirPath: The path to the directory in which path resolution starts * @param path: The path of the file or directory to remove * @returns `Ok(void)` if the operation succeeds, `Err(err)` if a file system error is encountered - * + * * @example Fs.remove(Path.fromString("file.txt")) // removes a file * @example Fs.remove(removeMode=Fs.RemoveEmptyDirectory, Path.fromString("dir")) // removes an empty directory * @example Fs.remove(removeMode=Fs.RemoveRecursive, Path.fromString("dir")) // removes the directory and its contents - * + * * @since v0.7.0 */ provide let remove = (removeMode=RemoveFile, baseDirPath=None, path) => { @@ -576,11 +577,11 @@ provide let remove = (removeMode=RemoveFile, baseDirPath=None, path) => { /** * Reads the contents of a directory. - * + * * @param baseDirPath: The path to the directory in which resolution should begin * @param path: The path to the directory to read * @returns `Ok(contents)` containing the directory contents or `Err(err)` if a file system error is encountered - * + * * @since v0.7.0 */ provide let readDir = (baseDirPath=None, path) => { @@ -598,11 +599,11 @@ provide let readDir = (baseDirPath=None, path) => { /** * Creates a new empty directory at the given path. - * + * * @param baseDirPath: The path to the directory in which resolution should begin * @param path: The path to create the new directory, relative to the base directory * @returns `Ok(void)` if the operation succeeds, `Err(err)` if a file system error is encountered - * + * * @since v0.7.0 */ provide let createDir = (baseDirPath=None, path) => { @@ -616,12 +617,12 @@ provide let createDir = (baseDirPath=None, path) => { /** * Creates a new symbolic link with the given contents. - * + * * @param linkContents: The path to store into the link * @param targetBaseDirPath: The path to the directory in which the target path resolution starts * @param targetPath: The path to the target of the link * @returns `Ok(void)` if the operation succeeds, `Err(err)` if a file system error or relativization error is encountered - * + * * @since v0.7.0 */ provide let createSymlink = (linkContents, targetBaseDirPath=None, targetPath) => { @@ -643,12 +644,12 @@ provide let createSymlink = (linkContents, targetBaseDirPath=None, targetPath) = /** * Queries information about a file. - * + * * @param followSymlink: Whether to follow symlinks or not; if `true` then the stats of a valid symlink's underlying file will be returned. `true` by default * @param baseDirPath: The path to the directory in which the path resolution starts * @param path: The path of the file to query * @returns `Ok(stats)` containing metadata or `Err(err)` if a file system error is encountered - * + * * @since v0.7.0 */ provide let stats = (followSymlink=true, baseDirPath=None, path) => { @@ -675,11 +676,11 @@ provide let stats = (followSymlink=true, baseDirPath=None, path) => { /** * Polls whether or not a file or directory exists at the given path. - * + * * @param baseDirPath: The path to the directory in which the path resolution starts * @param path: The path of the file to query * @returns `true` if a file or directory exists at the path or `false` otherwise - * + * * @since v0.7.0 */ provide let exists = (baseDirPath=None, path) => { @@ -701,11 +702,11 @@ let readLinkHelper = (dirFd, path, stats: File.Filestats) => { /** * Reads the contents of a symbolic link. - * + * * @param baseDirPath: The path to the directory to begin path resolution * @param path: The path to the link to read * @returns `Ok(path)` containing the link contents or `Err(err)` if a file system error is encountered - * + * * @since v0.7.0 */ provide let readLink = (baseDirPath=None, path) => { @@ -876,7 +877,7 @@ let rec copyRecursive = ( /** * Copies a file or directory. - * + * * @param copyMode: The type of copy to perform; `CopyFile` by default * @param followSymlink: Whether to follow symlinks or not; if `true` then the stats of a valid symlink's underlying file will be returned. `true` by default * @param sourceBaseDirPath: The path to the directory in which the source path resolution starts @@ -918,13 +919,13 @@ provide let copy = ( /** * Renames a file or directory. - * + * * @param sourceBaseDirPath: The path to the directory in which the source path resolution starts * @param sourcePath: The path of the file to rename * @param targetBaseDirPath: The path to the directory in which the target path resolution starts * @param targetPath: The new path of the file * @returns `Ok(void)` if the operation succeeds, `Err(err)` if a file system error is encountered - * + * * @since v0.7.0 */ provide let rename = ( @@ -961,18 +962,18 @@ provide let rename = ( /** * Functionality for reading and writing `Bytes` to files. - * + * * @since v0.7.0 */ provide module Binary { /** * Read the contents of a file as `Bytes`. - * + * * @param sync: Whether to synchronously read; `true` by default * @param baseDirPath: The path to the directory to begin path resolution * @param path: The file path to read from * @returns `Ok(contents)` containing the bytes read if successful or `Err(err)` if a file system error is encountered - * + * * @since v0.7.0 */ provide let readFile = (sync=true, baseDirPath=None, path) => { @@ -990,14 +991,14 @@ provide module Binary { /** * Write `Bytes` to a file. - * + * * @param writeMode: The type of write operation to perform; `Truncate` by default * @param sync: Whether to synchronously write; `true` by default * @param baseDirPath: The path to the directory to begin path resolution * @param path: The file path to write to * @param data: The bytes to write to the file * @returns `Ok(void)` if the operation is successful or `Err(err)` if a file system error is encountered - * + * * @since v0.7.0 */ provide let writeFile = ( @@ -1032,18 +1033,18 @@ provide module Binary { /** * Functionality for reading and writing `String`s to files. - * + * * @since v0.7.0 */ provide module Utf8 { /** * Read the contents of a file as a `String`. - * + * * @param sync: Whether to synchronously read; `true` by default * @param baseDirPath: The path to the directory to begin path resolution * @param path: The file path to read from * @returns `Ok(contents)` containing the string read if successful or `Err(err)` if a file system error is encountered - * + * * @since v0.7.0 */ provide let readFile = (sync=true, baseDirPath=None, path) => { @@ -1053,14 +1054,14 @@ provide module Utf8 { /** * Write a `String` to a file. - * + * * @param writeMode: The type of write operation to perform; `Truncate` by default * @param sync: Whether to synchronously write; `true` by default * @param baseDirPath: The path to the directory to begin path resolution * @param path: The file path to write to * @param data: The string to write to the file * @returns `Ok(void)` if the operation is successful or `Err(err)` if a file system error is encountered - * + * * @since v0.7.0 */ provide let writeFile = ( diff --git a/stdlib/json.gr b/stdlib/json.gr index 2146c8c9ff..2be8eddfcb 100644 --- a/stdlib/json.gr +++ b/stdlib/json.gr @@ -294,6 +294,7 @@ provide enum LineEnding { /* * Allows fine-grained control of formatting in JSON output. */ +@elideTypeInfo record FormattingSettings { indentation: IndentationFormat, arrayFormat: ArrayFormat, @@ -437,6 +438,7 @@ provide enum FormattingChoices { }, } +@elideTypeInfo record JsonWriterConfig { format: FormattingSettings, buffer: Buffer.Buffer, @@ -449,6 +451,7 @@ record JsonWriterConfig { // For now this is not exposed and remains an internal implementation detail. // It may make sense in the future to expose it and let the user reuse a writer for multiple // JSON emit operations without reallocating new closures and buffers each time. +@elideTypeInfo record JsonWriter { emit: Json => Option, } @@ -1289,6 +1292,7 @@ provide enum JsonParseError { /* * Internal data structure used during parsing. */ +@elideTypeInfo record JsonParserState { string: String, bufferParse: Buffer.Buffer, diff --git a/stdlib/path.gr b/stdlib/path.gr index 9973e9615c..5300f10a02 100644 --- a/stdlib/path.gr +++ b/stdlib/path.gr @@ -53,7 +53,7 @@ from "char" include Char // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE // SOFTWARE. - +@elideTypeInfo enum Token { Slash, Dot, @@ -61,12 +61,12 @@ enum Token { DriveTok(Char), Text(String), } - +@elideTypeInfo enum DirsUp { Zero, Positive, } - +@elideTypeInfo enum FileType { File, Dir, @@ -74,6 +74,7 @@ enum FileType { // hack to be able to concretely distinguish TypedPath from PathInfo and // enforce TypedPath's type parameters +@elideTypeInfo record TFileType { fileType: FileType, } diff --git a/stdlib/regex.gr b/stdlib/regex.gr index cc0a9a6377..51f734406b 100644 --- a/stdlib/regex.gr +++ b/stdlib/regex.gr @@ -39,7 +39,7 @@ REGEX PARSER CONFIG DEFINITIONS case-insensitive while still having the same group number and reference counter. */ - +@elideTypeInfo record RegExParserConfig { // Whether to use Perl-based regexp syntax isPerlRegExp: Bool, @@ -90,6 +90,7 @@ let configIncGroupNumber = (config: RegExParserConfig) => { config } +@elideTypeInfo record RegExBuf { input: String, inputExploded: Array, @@ -341,12 +342,14 @@ REGEX AST DEFINITIONS */ +@elideTypeInfo enum RepeatQuantifier { ZeroOrMore, OnceOrMore, ZeroOrOne, } +@elideTypeInfo enum GroupModeFlag { GMFCaseSensitive, GMFCaseInsensitive, @@ -354,6 +357,7 @@ enum GroupModeFlag { GMFMulti, } +@elideTypeInfo enum LookMode { LMMatches, LMDoesntMatch, @@ -361,12 +365,14 @@ enum LookMode { LMDoesntMatchPreceding, } +@elideTypeInfo enum PCEMode { PCEOnce, PCELongest, PCEShortest, } +@elideTypeInfo enum UnicodeCategory { LetterLowercase, LetterUppercase, @@ -400,6 +406,7 @@ enum UnicodeCategory { OtherPrivateUse, } +@elideTypeInfo enum rec ParsedRegularExpression { RENever, REEmpty, @@ -461,6 +468,7 @@ let makeRERange = (rng: CharRange, limitC) => { } } +@elideTypeInfo enum MergeMode { MMChar, } @@ -2000,6 +2008,7 @@ let rec startRange = re => { // validate: +@elideTypeInfo enum ValidateError { MightBeEmpty, DoesNotMatchBounded, @@ -2163,6 +2172,7 @@ REGEX MATCHER COMPILATION */ +@elideTypeInfo record MatchBuf { matchInput: String, matchInputExploded: Array, @@ -2184,6 +2194,7 @@ let matchBufChar = (buf: MatchBuf, pos: Number) => { } } +@elideTypeInfo enum StackElt { SEPositionProducer(Number => Option), SESavedGroup(Number, Option<(Number, Number)>), diff --git a/stdlib/uri.gr b/stdlib/uri.gr index cac6a15710..2795086f88 100644 --- a/stdlib/uri.gr +++ b/stdlib/uri.gr @@ -902,6 +902,7 @@ provide let make = ( return Ok({ scheme, userinfo, host, port, path, query, fragment }) } +@elideTypeInfo enum UpdateAction { KeepOriginal, UpdateTo(a),