{"action":"created","issue":{"url":"https://api.github.com/repos/golang/go/issues/18130","repository_url":"https://api.github.com/repos/golang/go","labels_url":"https://api.github.com/repos/golang/go/issues/18130/labels{/name}","comments_url":"https://api.github.com/repos/golang/go/issues/18130/comments","events_url":"https://api.github.com/repos/golang/go/issues/18130/events","html_url":"https://github.com/golang/go/issues/18130","id":192757828,"number":18130,"title":"proposal: support gradual code repair while moving a type between packages","user":{"login":"rsc","id":104030,"avatar_url":"https://avatars.githubusercontent.com/u/104030?v=3","gravatar_id":"","url":"https://api.github.com/users/rsc","html_url":"https://github.com/rsc","followers_url":"https://api.github.com/users/rsc/followers","following_url":"https://api.github.com/users/rsc/following{/other_user}","gists_url":"https://api.github.com/users/rsc/gists{/gist_id}","starred_url":"https://api.github.com/users/rsc/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/rsc/subscriptions","organizations_url":"https://api.github.com/users/rsc/orgs","repos_url":"https://api.github.com/users/rsc/repos","events_url":"https://api.github.com/users/rsc/events{/privacy}","received_events_url":"https://api.github.com/users/rsc/received_events","type":"User","site_admin":false},"labels":[{"id":236419512,"url":"https://api.github.com/repos/golang/go/labels/Proposal","name":"Proposal","color":"ededed","default":false}],"state":"open","locked":false,"assignee":null,"assignees":[],"milestone":{"url":"https://api.github.com/repos/golang/go/milestones/30","html_url":"https://github.com/golang/go/milestone/30","labels_url":"https://api.github.com/repos/golang/go/milestones/30/labels","id":1373555,"number":30,"title":"Proposal","description":"Proposals that are pending (not yet accepted/rejected).\r\n","creator":{"login":"rsc","id":104030,"avatar_url":"https://avatars.githubusercontent.com/u/104030?v=3","gravatar_id":"","url":"https://api.github.com/users/rsc","html_url":"https://github.com/rsc","followers_url":"https://api.github.com/users/rsc/followers","following_url":"https://api.github.com/users/rsc/following{/other_user}","gists_url":"https://api.github.com/users/rsc/gists{/gist_id}","starred_url":"https://api.github.com/users/rsc/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/rsc/subscriptions","organizations_url":"https://api.github.com/users/rsc/orgs","repos_url":"https://api.github.com/users/rsc/repos","events_url":"https://api.github.com/users/rsc/events{/privacy}","received_events_url":"https://api.github.com/users/rsc/received_events","type":"User","site_admin":false},"open_issues":33,"closed_issues":97,"state":"open","created_at":"2015-10-24T01:40:49Z","updated_at":"2016-12-20T17:41:04Z","due_on":null,"closed_at":null},"comments":145,"created_at":"2016-12-01T05:28:51Z","updated_at":"2016-12-21T17:42:06Z","closed_at":null,"body":"Go should add the ability to create alternate equivalent names for types, in order to enable gradual code repair during codebase refactoring. This was the target of the Go 1.8 alias feature, proposed in #16339 but held back from Go 1.8. Because we did not solve the problem for Go 1.8, it remains a problem, and I hope we can solve it for Go 1.9.\r\n\r\nIn the discussion of the alias proposal, there were many questions about why this ability to create alternate names for types in particular is important. As a fresh attempt to answer those questions, I wrote and posted an article, “[Codebase Refactoring (with help from Go)](https://talks.golang.org/2016/refactor.article).” Please read that article if you have questions about the motivation. (For an alternate, shorter presentation, see Robert's [Gophercon lightning talk](https://www.youtube.com/watch?v=t-w6MyI2qlU). Unfortunately, that video wasn't available online until October 9. Update, Dec 16: here's [my GothamGo talk](https://www.youtube.com/watch?v=h6Cw9iCDVcU), which was essentially the first draft of the article.)\r\n\r\nThis issue is _not_ proposing a specific solution. Instead, I want to gather feedback from the Go community about the space of possible solutions. One possible avenue is to limit aliases to types, as mentioned at the end of the article. There may be others we should consider as well.\r\n\r\nPlease post thoughts about type aliases or other solutions as comments here.\r\n\r\nThank you.\r\n\r\n**Update, Dec 16**: Design doc for type aliases [posted](https://golang.org/design/18130-type-alias).\r\n\r\n***\r\n# Discussion summary (last updated 2016-12-21)\r\n\r\n## Do we expect to need a general solution that works for all declarations?\r\n\r\nIf type aliases are 100% necessary, then var aliases are maybe 10% necessary, func aliases are 1% necessary, and const aliases are 0% necessary. Because const already has = and func could plausibly use = too, the key question is whether var aliases are important enough to plan for or implement.\r\n\r\nAs argued by @rogpeppe (https://github.com/golang/go/issues/16339#issuecomment-258771806) and @ianlancetaylor (https://github.com/golang/go/issues/16339#issuecomment-233644777) in the original alias proposal and as mentioned in the article, a mutating global var is usually a mistake. It probably doesn't make sense to complicate the solution to accommodate what is usually a bug. (In fact, if we can figure out how, it would not surprise me if in the long term Go moves toward requiring global vars to be immutable.)\r\n\r\nBecause richer var aliases are likely not important enough to plan for, it seems like the right choice here is to focus only on type aliases. Most of the comments here seem to agree. I won't list everyone.\r\n\r\n## Do we need a new syntax (= vs => vs export)?\r\n\r\nThe strongest argument for new syntax is the need to support var aliases, either now or in the future (https://github.com/golang/go/issues/18130#issuecomment-264232763 by @Merovius). It seems okay to plan not to have var aliases (see previous section).\r\n\r\nWithout var aliases, reusing = is simpler than introducing new syntax, whether => like in the alias proposal, ~ (https://github.com/golang/go/issues/18130#issuecomment-264185142 by @joegrasse), or export (https://github.com/golang/go/issues/18130#issuecomment-264152427 by @cznic).\r\n\r\nUsing = in would also exactly match the syntax of type aliases in Pascal and Rust. To the extent that other languages have the same concepts, it's nice to use the same syntax.\r\n\r\nLooking ahead, there could be a future Go in which func aliases exist too (see https://github.com/golang/go/issues/18130#issuecomment-264324306 by @nigeltao), and then all declarations would permit the same form:\r\n\r\n    const C2 = C1\r\n    func F2 = F1\r\n    type T2 = T1\r\n    var V2 = V1\r\n\r\nThe only one of these that wouldn't establish a true alias would be the var declaration, because V2 and V1 can be redefined independently as the program executes (unlike the const, func, and type declarations which are immutable). Since one main reason for variables is to allow them to vary, that exception would at least be easy to explain. If Go moves toward immutable global vars, then even that exception would disappear.\r\n\r\nTo be clear, I am not suggesting func aliases or immutable global vars here, just working through the implications of such future additions.\r\n\r\n@jimmyfrasche suggested (https://github.com/golang/go/issues/18130#issuecomment-264278398) aliases for everything except consts, so that const would be the exception instead of var:\r\n\r\n    const C2 = C1 // no => form\r\n    func F2 => F1\r\n    type T2 => T1\r\n    var V2 => V1\r\n    var V2 = V1 // different from => form\r\n\r\nHaving inconsistencies with both const and var seems more difficult to explain than having just an inconsistency for var.\r\n\r\n## Can this be a tooling- or compiler-only change instead of a language change?\r\n\r\nIt's certainly worth asking whether gradual code repair can be enabled purely by side information supplied to the compiler (for example, https://github.com/golang/go/issues/18130#issuecomment-264205929 by @btracey).\r\n\r\nOr maybe if the compiler can apply some kind of rule-based preprocessing to transform input files before compilation (for example, https://github.com/golang/go/issues/18130#issuecomment-264329924 by @tux21b).\r\n\r\nUnfortunately, no, the change really can't be confined that way. There are at least two compilers (gc and gccgo) that would need to coordinate, but so would any other tools that analyze programs, like go vet, guru, goimports, gocode (code completion), and others. \r\n\r\nAs @bcmills said (https://github.com/golang/go/issues/18130#issuecomment-264275574), “a ‘non-language-change’ mechanism which must be supported by all implementations is a de facto language change — it’s just one with poorer documentation.”\r\n\r\n## What other uses might aliases have?\r\n\r\nWe know of the following. Given that type aliases in particular were deemed important enough for inclusion in Pascal and Rust, there are likely others.\r\n\r\n1. Aliases (or just type aliases) would enable creating drop-in replacements that expand other packages. For example see https://go-review.googlesource.com/#/c/32145/, especially the explanation in the commit message.\r\n\r\n2. Aliases (or just type aliases) would enable structuring a package with a small API surface but a large implementation as a collection of packages for better internal structure but still present just one package to be imported and used by clients. There's a somewhat abstract example described at  https://github.com/golang/go/issues/16339#issuecomment-232813695.\r\n\r\n3. Protocol buffers have an \"import public\" feature whose semantics is trivial to implement in generated C++ code but impossible to implement in generated Go code. This causes frustration for authors of protocol buffer definitions shared between C++ and Go clients. Type aliases would provide a way for Go to implement this feature. In fact, the [original use case for import public was gradual code repair](https://developers.google.com/protocol-buffers/docs/proto#importing-definitions). Similar issues may arise in other kinds of code generators.\r\n\r\n4. Abbreviating long names. Local (unexported or not-package-scoped) aliases might be handy to abbreviate a long type name without introducing the overhead of a whole new type. As with all these uses, the clarity of the final code would strongly influence whether this is a suggested use.\r\n\r\n## What other issues does a proposal for type aliases need to address?\r\n\r\nListing these for reference. Not attempting to solve or discuss them in this section, although a few were discussed later and are summarized in separate sections below.\r\n\r\n1. Handling in godoc. (https://github.com/golang/go/issues/18130#issuecomment-264323137 by @nigeltao and https://github.com/golang/go/issues/18130#issuecomment-264326437 by @jimmyfrasche)\r\n\r\n2. Can methods be defined on types named by alias? (https://github.com/golang/go/issues/18130#issuecomment-265077877 by @ulikunitz)\r\n\r\n3. If aliases to aliases are allowed, how do we handle alias cycles? (https://github.com/golang/go/issues/18130#issuecomment-264494658 by @thwd)\r\n\r\n4. Should aliases be able to export unexported identifiers? (https://github.com/golang/go/issues/18130#issuecomment-264494658 by @thwd)\r\n\r\n5. What happens when you embed an alias (how do you access the embedded field)? (https://github.com/golang/go/issues/18130#issuecomment-264494658 by @thwd, also #17746)\r\n\r\n6. Are aliases available as symbols in the built program? (https://github.com/golang/go/issues/18130#issuecomment-264494658 by @thwd)\r\n\r\n7. Ldflags string injection: what if we refer to an alias? (https://github.com/golang/go/issues/18130#issuecomment-264494658 by @thwd; this only arises if there are var aliases.)\r\n\r\n## Is versioning a solution by itself?\r\n\r\n\"In that case maybe versioning is the whole answer, not type aliases.\"\r\n(https://github.com/golang/go/issues/18130#issuecomment-264573088 by @iainmerrick)\r\n\r\nAs [noted in the article](https://talks.golang.org/2016/refactor.article#TOC_5.2.), I think versioning is an complementary concern. Support for gradual code repair, such as with type aliases, gives a versioning system more flexibility in how it builds a large program, which can be difference between being able to build the program and not.\r\n\r\n## Can the larger refactoring problem be solved instead?\r\n\r\nIn https://github.com/golang/go/issues/18130#issuecomment-265052639, @niemeyer points out that there were actually two changes for moving os.Error to error: the name changed but so did the definition (the current Error method used to be a String method). \r\n\r\n@niemeyer suggests that perhaps we can find a solution to the broader refactoring problem that fixes types moving between packages as a special case but also handles things like method names changing, and he proposes a solution built around \"adapters\".\r\n\r\nThere is a fair amount of discussion in the comments that I can't easily summarize here. The discussion isn't over, but so far it is unclear whether \"adapters\" can fit into the language or be implemented in practice. It does seem clear that adapters are at least one order of magnitude more complex than type aliases.\r\n\r\nAdapters need a coherent solution to the subtyping problems noted below as well.\r\n\r\n## Can methods be declared on alias types?\r\n\r\nCertainly aliases do not allow bypassing the usual method definition restrictions: if a package defines type T1 = otherpkg.T2, it cannot define methods on T1, just as it cannot define methods directly on otherpkg.T2. That is, if type T1 = otherpkg.T2, then func (T1) M() is equivalent to func (otherpkg.T2) M(), which is invalid today and remains invalid. However, if a package defines type T1 = T2 (both in the same package), then the answer is less clear. In this case, func (T1) M() would be equivalent to func (T2) M(); since the latter is allowed, there is an argument to allow the former. The current design doc does not impose a restriction here (in keeping with the general avoidance of restrictions), so that func (T1) M() is valid in this situation.\r\n\r\nIn https://github.com/golang/go/issues/18130#issuecomment-267694112, @jimmyfrasche suggests that instead defining \"no use of aliases in method definitions\" would be a clear rule and avoid needing to know what T is defined as to know if func (T) M() is valid. In https://github.com/golang/go/issues/18130#issuecomment-267997124, @rsc points out that even today there are certain T for which func (T) M() is not valid: https://play.golang.org/p/bci2qnldej. In practice this doesn't come up because people write reasonable code. \r\n\r\nWe will keep this possible restriction in mind but wait until there is strong evidence that it is needed before introducing it.\r\n\r\n## Is there a cleaner way to handle embedding and, more generally, field renames?\r\n\r\nIn https://github.com/golang/go/issues/18130#issuecomment-267691816, @Merovius points out that an embedded type that changes its name during a package move will cause problems when that new name must eventually be adopted at the use sites. For example if user type U has an embedded io.ByteBuffer that moves to bytes.Buffer, then while U embeds io.ByteBuffer the field name is U.ByteBuffer, but when U is updated to refer to bytes.Buffer, the field name necessarily changes to U.Buffer.\r\n\r\nIn https://github.com/golang/go/issues/18130#issuecomment-267710478, @neild points out that there is at least a workaround if references to io.ByteBuffer must be excised: the package P that defines U can also define 'type ByteBuffer = bytes.Buffer' and embed that type into U. Then U still has a U.ByteBuffer, even after io.ByteBuffer is gone entirely. \r\n\r\nIn https://github.com/golang/go/issues/18130#issuecomment-267703067, @bcmills suggests the idea of field aliases, to allow a field to have multiple names during a gradual repair. Field aliases would allow defining something like `type U struct { bytes.Buffer; ByteBuffer = Buffer }` instead of having to create the top-level type alias.\r\n\r\nIn https://github.com/golang/go/issues/18130#issuecomment-268001111, @rsc raises yet another possibility: some syntax for 'embed this type with this name', so that it is possible to embed a bytes.Buffer as the field name ByteBuffer, without needing a top-level type or an alternate name. If that existed, then the type name could be updated from io.ByteBuffer to bytes.Buffer while preserving the original name (and not introducing a second, nor a clumsy exported type).\r\n\r\nThese all seem worth exploring once we have more evidence of large-scale refactorings blocked by problems with fields changing names. As @rsc wrote, \"If type aliases help us get to the point where lack of field aliases is the next big roadblock for large-scale refactorings, that will be progress!\"\r\n\r\nThere was a suggestion of restricting the use of aliases in embedded fields or changing the embedded name to use the target type's name, but those make the alias introduction break existing definitions that must then be fixed atomically, essentially preventing any gradual repair. @rsc: \"We discussed this at some length in #17746. I was originally on the side of the name of an embedded io.ByteBuffer alias being Buffer, but the above argument convinced me I was wrong. @jimmyfrasche in particular made some good arguments about the code not changing depending on the definition of the embedded thing. I don't think it's tenable to disallow embedded aliases completely.\"\r\n\r\n## What is the effect on programs using reflection?\r\n\r\nPrograms using reflection see through aliases. In https://github.com/golang/go/issues/18130#issuecomment-267903649, @atdiar points out that if a program is using reflection to, for example, find the package in which a type is defined or even the name of a type, it will observe the change when the type is moved, even if a forwarding alias is left behind. In https://github.com/golang/go/issues/18130#issuecomment-268001410, @rsc confirmed this and wrote \"Like the situation with embedding, it's not perfect. Unlike the situation with embedding, I don't have any answers except maybe code shouldn't be written using reflect to be quite that sensitive to those details.\" \r\n\r\nThe use of vendored packages today also changes package import paths seen by reflect, and we have not been made aware of significant problems caused by that ambiguity. This suggests that programs are not commonly inspecting reflect.Type.PkgPath in ways that would be broken by use of aliases. Even so, it's a potential gap, just like embedding.\r\n\r\n## What is the effect on separate compilation of programs and plugins?\r\n\r\nIn https://github.com/golang/go/issues/18130#issuecomment-268524504, @atdiar raises the question of the effect on object files and separate compilation. In https://github.com/golang/go/issues/18130#issuecomment-268560180, @rsc replies that there should be no need to make changes here: if X imports Y and Y changes and is recompiled, then X needs to be recompiled too. That's true today without aliases, and it will remain true with aliases. Separate compilation means being able to compile X and Y in distinct steps (the compiler does not have to process them in the same invocation), not that it is possible to change Y without recompiling X.\r\n\r\n## Would sum types or some kind of subtyping be an alternative solution?\r\n\r\nIn https://github.com/golang/go/issues/18130#issuecomment-264413439, @iand suggests \"substitutable types\", \"a list of types that may be substituted for the named type in function arguments, return values etc.\". In https://github.com/golang/go/issues/18130#issuecomment-268072274, @j7b suggests using algebraic types \"so we also get an empty interface equivalent with compile time type checking as a bonus\". Other names for this concept are sum types and variant types. \r\n\r\nIn general this does not suffice to allow moving types with gradual code repair. There are two ways to think about this.\r\n\r\nIn https://github.com/golang/go/issues/18130#issuecomment-268075680, @bcmills takes the concrete way, pointing out that algebraic types have a different representation than the original, which makes it not possible to treat the sum and the original as interchangeable: the latter has type tags.\r\n\r\nIn https://github.com/golang/go/issues/18130#issuecomment-268585497, @rsc takes the theoretical way, expanding on https://github.com/golang/go/issues/18130#issuecomment-265211655 by @gri pointing out that in a gradual code repair, sometimes you need T1 to be a subtype of T2 and sometimes vice versa. The only way for both to be subtypes of each other is for them to be the same type, which not concidentally is what type aliases do.\r\n\r\nAs a side tangent, in addition to not solving the gradual code repair problem, algebraic types / sum types / union types / variant types are by themselves hard to add to Go. See\r\n[the FAQ answer](https://golang.org/doc/faq#variant_types) and the [Go 1.6 AMA discussion](https://www.reddit.com/r/golang/comments/46bd5h/ama_we_are_the_go_contributors_ask_us_anything/d03t6ji/?st=iwz660vv&sh=2df884a1) for more.\r\n\r\nIn https://github.com/golang/go/issues/18130#issuecomment-265206780, @thwd suggests that since Go has a subtyping relationship between concrete types and interfaces (bytes.Buffer can be seen as a subtype of io.Reader) and between interfaces (io.ReadWriter is a subtype of io.Reader in the same way), making interfaces \"recursively covariant (according to the current variance rules) down to their method arguments\" would solve the problem provided that all future packages only use interfaces, never concrete types like structs (\"encourages good design, too\"). \r\n\r\nThere are three problems with that as a solution. First, it has the subtyping issues above, so it doesn't solve gradual code repair. Second, it doesn't apply to existing code, as @thwd noted in this suggestion. Third, forcing the use of interfaces everywhere may not actually be good design and introduces performance overheads (see for example https://github.com/golang/go/issues/18130#issuecomment-265211726 by @Merovius and https://github.com/golang/go/issues/18130#issuecomment-265224652 by @zombiezen).\r\n\r\n## Restrictions\r\n\r\nThis section collects proposed restrictions for reference, but keep in mind that restrictions add complexity. As I wrote in https://github.com/golang/go/issues/18130#issuecomment-264195616, \"we should probably only implement those restrictions after actual experience with the unrestricted, simpler design helps us understand whether the restriction would bring enough benefits to pay for its cost.\"\r\n\r\nPut another way, any restriction would need to be justified by evidence that it would prevent some serious misuse or confusion. Since we haven't implemented a solution yet, there is no such evidence. If experience did provide that evidence, these will be worth returning to.\r\n\r\n### Restriction? Aliases of standard library types can only be declared in standard library.\r\n\r\n(https://github.com/golang/go/issues/18130#issuecomment-264165833 and https://github.com/golang/go/issues/18130#issuecomment-264171370 by @iand)\r\n\r\nThe concern is \"code that has renamed standard library concepts to fit a custom naming convention\", or \"long spaghetti chains of aliases across multiple packages that end up back at the standard library\", or \"aliasing things like interface{} and error\".\r\n\r\nAs stated, the restriction would disallow the \"extension package\" case described above involving x/image/draw.\r\n\r\nIt's unclear why the standard library should be special: the problems would exist with any code. Also, neither interface{} nor error is a type from the standard library. Rephrasing the restriction as \"aliasing predefined types\" would disallow aliasing error, but the need to alias error was one of the motivating examples in the article.\r\n\r\n### Restriction? Alias target must be package-qualified identifier.\r\n\r\n(https://github.com/golang/go/issues/18130#issuecomment-264188282 by @jba)\r\n\r\nThis would make it impossible to make an alias when renaming a type within a package, which may be used widely enough to necessitate a gradual repair (https://github.com/golang/go/issues/18130#issuecomment-264274714 by @bcmills). \r\n\r\nIt would also disallow aliasing error as in the article. \r\n\r\n### Restriction? Alias target must be package-qualified identifier with same name as alias.\r\n\r\n(proposed during alias discussion in Go 1.8)\r\n\r\nIn addition to the problems of the previous section with limiting to package-qualified identifiers, forcing the name to stay the same would disallow the conversion from io.ByteBuffer to bytes.Buffer in the article.\r\n\r\n### Restriction? Aliases should be discouraged in some way.\r\n\r\n\"How about hiding aliases behind an import, just like for \"C\" and “unsafe”, to further discourage it's usage? In the same vein, I would like the aliases syntax to be verbose and stand out as a scaffold for on going refactoring.\" - https://github.com/golang/go/issues/18130#issuecomment-264289940 by @xiegeo\r\n\r\n\"Should we also automatically infer that an aliased type is legacy and should be replaced by the new type? If we enforce golint, godoc and similar tools to visualize the old type as deprecated, it would limit the abuse of type aliasing very significantly. And the final concern of aliasing feature being abused would be resolved.\" - https://github.com/golang/go/issues/18130#issuecomment-265062154 by @rakyll\r\n\r\nUntil we know that they will be used wrong, it seems premature to discourage usage. There may be good, non-temporary uses (see above). \r\n\r\nEven in the case of code repair, either the old or new type may be the alias during the transition, depending on the constraints imposed by the import graph. Being an alias does not mean the name is deprecated.\r\n\r\nThere is already a mechanism for marking certain declarations as deprecated  (see https://github.com/golang/go/issues/18130#issuecomment-265294564 by @jimmyfrasche)."},"comment":{"url":"https://api.github.com/repos/golang/go/issues/comments/268589320","html_url":"https://github.com/golang/go/issues/18130#issuecomment-268589320","issue_url":"https://api.github.com/repos/golang/go/issues/18130","id":268589320,"user":{"login":"atdiar","id":12191458,"avatar_url":"https://avatars.githubusercontent.com/u/12191458?v=3","gravatar_id":"","url":"https://api.github.com/users/atdiar","html_url":"https://github.com/atdiar","followers_url":"https://api.github.com/users/atdiar/followers","following_url":"https://api.github.com/users/atdiar/following{/other_user}","gists_url":"https://api.github.com/users/atdiar/gists{/gist_id}","starred_url":"https://api.github.com/users/atdiar/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/atdiar/subscriptions","organizations_url":"https://api.github.com/users/atdiar/orgs","repos_url":"https://api.github.com/users/atdiar/repos","events_url":"https://api.github.com/users/atdiar/events{/privacy}","received_events_url":"https://api.github.com/users/atdiar/received_events","type":"User","site_admin":false},"created_at":"2016-12-21T17:42:06Z","updated_at":"2016-12-21T17:42:06Z","body":"@rsc concerning separate compilation, it is relative to whether type definitions need to keep a list of their alias (which is not tractable at large scale, because of separate compilation) or each alias iteratively builds a list of aliases following the import graph. (and how and where to keep that information so that the runtime has access to it)."}}
{"actor":{"display_login":"atdiar"}}