<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:cc="http://cyber.law.harvard.edu/rss/creativeCommonsRssModule.html">
    <channel>
        <title><![CDATA[Stories by Pyry Kontio on Medium]]></title>
        <description><![CDATA[Stories by Pyry Kontio on Medium]]></description>
        <link>https://medium.com/@GolDDranks?source=rss-c0c30d6188f1------2</link>
        <image>
            <url>https://cdn-images-1.medium.com/fit/c/150/150/1*-uL5dVoPtZ8APlwVmlk16w.jpeg</url>
            <title>Stories by Pyry Kontio on Medium</title>
            <link>https://medium.com/@GolDDranks?source=rss-c0c30d6188f1------2</link>
        </image>
        <generator>Medium</generator>
        <lastBuildDate>Sun, 31 May 2026 22:17:57 GMT</lastBuildDate>
        <atom:link href="https://medium.com/@GolDDranks/feed" rel="self" type="application/rss+xml"/>
        <webMaster><![CDATA[yourfriends@medium.com]]></webMaster>
        <atom:link href="http://medium.superfeedr.com" rel="hub"/>
        <item>
            <title><![CDATA[Rust 2019 — let us pursue composability]]></title>
            <link>https://medium.com/@GolDDranks/rust-2019-let-us-pursue-composability-70f1eb2238c3?source=rss-c0c30d6188f1------2</link>
            <guid isPermaLink="false">https://medium.com/p/70f1eb2238c3</guid>
            <category><![CDATA[rustlang]]></category>
            <category><![CDATA[rust]]></category>
            <category><![CDATA[programming]]></category>
            <dc:creator><![CDATA[Pyry Kontio]]></dc:creator>
            <pubDate>Sun, 09 Dec 2018 02:50:51 GMT</pubDate>
            <atom:updated>2018-12-11T03:38:44.116Z</atom:updated>
            <content:encoded><![CDATA[<h3>Rust 2019 — let us pursue composability</h3><blockquote>TL;DR: An edition release doesn’t mean that the work on that edition is over. In 2019, we should continue to pursue and drive home the goals set in the spirit of productivity. That being said, I’m going to argue that for the upcoming years and the next edition, we should pursue software composability as a new overarching theme and go over some thoughts on what that means in a concrete way.</blockquote><h3>On editions and themes and the following year</h3><p>First of all, let me start with an observation about the themes of the past and the current editions. The overarching theme of Rust 2015 was stability. The work towards stabilising the language started in 2014 and was publicly announced in the blog post <a href="https://blog.rust-lang.org/2014/09/15/Rust-1.0.html">Road to Rust 1.0</a>. A huge amount of work was coordinated and performed for the effort that culminated in <a href="https://blog.rust-lang.org/2015/05/15/Rust-1.0.html">releasing Rust 1.0</a> in June, 2015.</p><p>However, the release, although a culmination point, didn’t mean that the job was done. For months and even years after the big release, the community continued the effort of polishing and stabilising yet unstable parts of the standard library and the community-maintained libraries release by release. One could say that the <a href="https://blog.rust-lang.org/2017/05/05/libz-blitz.html">Libz Blitz initiative</a> in 2017 was still made in the spirit of stability!</p><p>Now, in <a href="https://blog.rust-lang.org/2017/02/06/roadmap.html">2017 roadmap</a> it was announced that productivity was going to be the theme of that year, and in <a href="https://blog.rust-lang.org/2018/03/12/roadmap.html">2018</a> it was solidified as a the overarching theme of the Rust 2018 edition. The effort finally culminated in a <a href="https://blog.rust-lang.org/2018/12/06/Rust-1.31-and-rust-2018.html">big release</a> a few days ago.</p><p>Does that mean that the work on productivity is done? I hope the reader is going to agree with me that the answer is clearly no! I think we are seeing a recurring pattern what the edition releases are about: a flurry of preparation, design and implementation work intensifying and finally building up to a release[1], followed by a phase of consolidating work and driving smaller, supporting goals into completion.</p><p>Moreover, although there are clear-cut releases, there is no hard cutover for <em>overarching themes</em>. They just express the spirit of the community and give general direction as we are moving forward with the Rust project and the ecosystem — and I think we can be sure that the theme of productivity continues to define the direction we are moving to during the following year.</p><p>This was a long-winded way of stating the first point I want to make about Rust in 2019: I think we should continue to pursue the goals we set in the spirit of productivity. To mention some specifics: I think that finishing the the support for asynchronous Rust is incredibly important. Another very important goal we should focus on is improving the compiler; the query-based compilation model and refined incremental compilation are going to be a huge boon for productivity, as they enable faster builds and better support for IDE-like use cases. Completing the refactorings of trait matching and borrow checking should also allow doing some experimental work more easily. Finally, I’d also like to see the 1.0 releases of some important community-maintained libraries such as <a href="https://crates.io/crates/log">log</a>, <a href="https://crates.io/crates/rand">rand</a>, <a href="https://crates.io/crates/tokio">tokio</a> and <a href="https://crates.io/crates/hyper">hyper</a> during the year 2019. All in all, I very much agree with <a href="https://www.reddit.com/r/rust/comments/a42ojg/the_fallow_year_my_rust2019_post/">Jonathan Turner</a> in that I’d like the year 2019 to be a “fallow year” of maturing the ecosystem.</p><p>Now, that being said, let us talk about the future of Rust on a longer timeline.</p><h3>Composability as a core value</h3><p>I think Rust should consider setting <em>composability</em> as the overarching theme for the Rust 2021 edition and possibly upgrading it to a core value of the project. Rust already has almost all the qualities to make it the most composable language in existence — all that is missing is a concentrated community effort to realise those qualities into a polished vision. We’ll see next what I mean by composability and why it is desirable by going through some examples.</p><h4>Examples from the composability zoo</h4><p><em>Software reusability</em> has always been a dream of many programmers. It’s not an easy thing to achieve; I’ve even heard some people calling it a pipe dream (usually in combination of trying to achieve it through some failed promises of object-oriented programming). However one can’t help but accept that it for sure is a desirable thing; reinventing the wheel every time certainly isn’t. I’m going to argue that composability — the ease of composing software from smaller building blocks — is a key property that makes code reuse possible. However, I don’t think there is a single feature that makes code composable. I think there is multiple excellent examples of some programming languages that are very composable in different ways; here I’m going to concentrate on C, Lua, Haskell and JavaScript.</p><p>C can be seen as the one of the most composable programming languages in existence, if you consider the vast amount of libraries written in C and the huge software stacks that consist of software written in C. There are two key features in C that make this possible: the lack of a runtime and ABI stability. The lack of a runtime means it doesn’t have much requirements for its runtime environment. This makes it possible for C to run almost anywhere — be it an embedded microcontroller, a mainframe or your smartphone. It also makes it possible to run C code in <em>presence </em>or in <em>spite</em> of a runtime, which makes C code easy to call from Python, Java, Ruby etc. The ABI stability makes also libraries written in C easy to package, distribute, wrap and reuse.</p><p>Lua is another example of being able to run almost anywhere. However, as a high-level language it has a totally different flavor; it’s an extremely simple language, and can be implemented as a C library. In this sense, it leapfrogs C’s ability to be run almost everywhere. However, there is another sense in which Lua is very composable: it is self-contained. Its runtime is a sandboxed context with a very clear, non-global state. If you want, you can easily run multiple different Lua instances and they don’t need to care about each others. Lua even makes possible running code in self-contained sandboxes inside its runtime by allowing creating “environments” to run code in. The code running inside an empty environment can’t access global state as it doesn’t have any reference to it. Lua makes it possible to run untrusted code and get away with it. This also enables the main usecase Lua is geared for: describing behaviour as scripts, and making it possible to create flexibly-behaving applications by composing the desired behaviour from those scripts.</p><p>There is a lot to love about Haskell. It has multiple features that make it extremely composable. I think the most notable one is the strict control of side-effects. It’s not a security feature and you can’t run untrusted code relying on just to the lack of side effects. However, it makes one confident that library code is self-contained and doesn’t do anything funny. All the side-effects are indicated and documented by the types in the function signatures. Another feature that makes Haskell composable is its generic polymorphism. It makes code composition flexible by not setting in stone the exact types that are needed for interacting with libraries, allowing very general and multi-purpose code to be written.</p><p>Finally, there is JavaScript. Most people wouldn’t think of JavaScript as an especially composable language, but I’d like to highlight a single feature that makes it easy to compose code in real life: a good package and dependency manager. Because of NPM, JavaScript library ecosystem is thriving.</p><p>Let’s return to our examples from a reverse perspective; there is some recent counterexamples that highlight the <em>uncomposability</em> of JavaScript. There was the <a href="https://nodesource.com/blog/a-high-level-post-mortem-of-the-eslint-scope-security-incident/">eslint-scope hijacking incident</a> and there was the <a href="https://blog.npmjs.org/post/141577284765/kik-left-pad-and-npm">left-pad incident</a>. These were both cases that erode the concept of composing software from libraries. There are some problems with other languages too: Haskell has a runtime and garbage collection which makes it not always straightforward to call from other languages. This, combined with it’s lazyness make it also hard to build embedded software in Haskell. Lua, while having very strong story in embeddability, is as a scripting language not suitable for base systems implementation. It also does not have a strong “batteries included” library story as it is aimed for very specialised, application-specific use cases where a “catch-it-all” default set of libraries wouldn’t make sense. Finally, C, while being able to run almost everywhere, is ironically not easy to get to run almost anywere. This is because of the lack of polished dependency management and complicated, non-portable build systems. C also does nothing to ensure some properties of the code. It’s up to you to verify that it does what it claims to do, and if it segfaults, good luck with debugging nightmares. That’s not encouraging for code reuse!</p><p>As we can see, composability is not a single thing, and certainly it’s not just a technical language feature. Composability just means the ease of composing software from building blocks, and everything that makes the process of code composition easier and more robust, increases composability. Everything that makes the process harder or more unreliable decreases it. We can, for example, see that having strong standards for documentation increases composability, because it makes it easier and more accessible to understand each of the building blocks. Here, I find Rust’s story already quite good with the venerable websites like <a href="https://docs.rs/">https://docs.rs/</a> and <a href="https://crates.io/">https://crates.io/</a>.</p><h4>Enter Rust</h4><p>I’d like to argue that Rust is one of the most composable language there exists, and with a concentrated community effort it’s possible to polish it to be <em>the</em> composable language that is second to none in almost every aspect. We can already see that Rust shares similar qualities with many of our examples.</p><p>The lack of runtime is similar to C, and that makes it possible to run Rust code on embeddable devices and develop libraries that are easy to re-package and wrap for other languages to call.</p><p>It doesn’t have a sandboxed model like Lua, but it supports compiling to WebAssembly; I think that in the future we’ll see software even outside web browsers that implement plugins functionality by running sandboxed WASM.</p><p>Like Haskell, Rust also has a strong culture of not relying on global state and being explicit (in documentation) about side-effects which helps to assure that libraries you use are not going to interfere with each others (or with themselves, or with your code). This is further improved by recently stabilised support for deterministic const fns that hopefully continue to improve.</p><p>Also like Haskell, Rust has very flexible generics that makes writing generic libraries possible.</p><p>I’d love to see Rust further polish these aspects. I want Rust to be a language that runs anywhere, interoperates with anything, and gives you the peace of mind that it does what you expect it to. Here’s some ideas of features and tools we could spearhead to make Rust the most composable language in existence:</p><ul><li>More embedded targets</li><li>Streamlined build process for embedded</li><li>Easier and more complete story for no_std</li><li>Complete and stabilise per-object allocators</li><li>Make the WASM story even better</li><li>Finish the work on generic associated types to allow more generic libraries and interfaces to be built</li><li>Support projects that aim to make calling Rust code from other languages easy, such as <a href="https://usehelix.com/">Helix</a></li><li>Create a strong culture for community code reviews to improve trust in the ecosystem libraries and support the development of tooling for that. <a href="https://github.com/dpc/crev">Crev</a> is an extremely promising project.</li><li>Make builds generally more robust by sandboxing the build scripts and procedural macros (how awesome an use case for WASM would that be!)</li><li>Make it easier to standardise build scripts by allowing them to depend on some community-maintained well-behaved libraries (<a href="https://github.com/rust-lang/rust/issues/49803">RFC</a>)</li><li>Make separation between private and public dependencies clearer in Cargo, and make tooling for checking it automatically. (Edit: added this item on 2018–12–10)</li><li>Support tooling for automatically detecting semver bumps; make <a href="https://github.com/rust-dev-tools/rust-semverver">Semverver</a> a more integrated first-class tool. (Edit: added this item on 2018–12–10)</li><li>Assess the problems with the orphan rules / coherence restrictions and try to solve the cental problems of “glue crates”. (Edit: added this item on 2018–12–10)</li><li>Provide a versioned, stable ABI. It doesn’t have to include everything in Rust, but it should allow using some common types such as slices and trait objects (with possibly only some subset of the all features of trait objects) for stable FFI calls.</li><li>Make lifetimes more composable through new typesystem features. I’ve highlighted some problems in my earlier post <a href="https://medium.com/@GolDDranks/things-rust-doesnt-let-you-do-draft-f596a3c740a5">Things Rust doesn’t let you do</a>. Especially the last three items 12–14 apply here.</li><li>Make it possible to reason about side effects in a generic way, introducing a polymorphic effect-handler system.</li></ul><p>I think that the most of the items are relatively uncontroversial. The last ones might raise some objections; there are some opinions about Rust being already having too much features or having already spent its complexity budget. However, I think that with good design and discretion, features such as these are only going to make code more comprehensible and easier to control.</p><p>In particular, I’d like to point out that at the moment, it’s hard to control the side effects of code that you call. In Rust the problem is generally not as bad as in some languages where there is a culture of writing very side-effect happy code. However, as const fns have been stabilised, we have already a way to restrict side-effects. While that is great, we now find ourselves on a head-on collision course with the problem of <a href="http://journal.stuffwithstuff.com/2015/02/01/what-color-is-your-function/">red and blue functions</a>. What if we want to debug log from our const function? That’s a side effect. Should we make logging and log-less versions? At some point, we want to be polymorphic over side effects, and we want our users to decide how to handle them to improve composability. I don’t think it’s realistic nor desirable to do huge changes to the type system at short time scales, but the capability of controlling side effects would make sense in the long run.</p><p>All in all, I think we should seriously consider composability as a core value and overarching theme for the upcoming years and start sketching, planning and designing accordingly — as we have seen with the async support, these things take time.</p><p>Happy Rusting, and let’s make 2019 a great year for Rust!</p><h3>Footnotes</h3><p>[1] To be sure, the release model of Rust is to release often and do small, non-feature-based releases, but when it comes to edition releases, I think we can all accept that they feel “big”.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=70f1eb2238c3" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Things Rust doesn’t let you do]]></title>
            <link>https://medium.com/@GolDDranks/things-rust-doesnt-let-you-do-draft-f596a3c740a5?source=rss-c0c30d6188f1------2</link>
            <guid isPermaLink="false">https://medium.com/p/f596a3c740a5</guid>
            <category><![CDATA[rustlang]]></category>
            <category><![CDATA[programming]]></category>
            <category><![CDATA[rust]]></category>
            <dc:creator><![CDATA[Pyry Kontio]]></dc:creator>
            <pubDate>Mon, 12 Nov 2018 01:34:25 GMT</pubDate>
            <atom:updated>2018-11-14T15:45:52.278Z</atom:updated>
            <content:encoded><![CDATA[<blockquote><strong>TL;DR:</strong> A survey of things that Rust — and especially the mutability system and the borrow checker — doesn’t let you do, while arguably safe in some circumstances. Justifications for the current behaviour are discussed and possible workarounds and future improvements are explained.</blockquote><h3>Contents:</h3><blockquote>About references and lifetimes</blockquote><blockquote>The design decisions to live by</blockquote><blockquote>The shortcomings with answers<br>1. Doing control flow aware stuff<br>2. Postponing mutability of a lifetime<br>3. Skipping trivial bounds in data types<br>4. Splitting up mutable references<br>5. Having multiple aliasing mutable references<br>6. Being able to point inside Cell types<br>7. Having self-referencing structs<br>8. Capturing only disjoint fields in closures<br>9. Having associated types that are generic over lifetimes<br>Addendum: Getting ownership over a mutable reference</blockquote><blockquote>Open problems: from here on there be dragons<br>10. Downgrading a mutable lifetime to a shared one<br>11. Calling mutable methods that don’t access overlapping fields<br>12. Hiding mutable lifetimes in data types<br>13. Using “ambient” lifetimes<br>14. Moving the owner of a heap-allocated object that has an inbound reference</blockquote><blockquote>Closing words</blockquote><p>The borrow checker is undisputedly the weirdest and most novel feature of Rust the programming language. It’s what makes Rust the what it is — a memory safe language without a garbage collector that strives for zero-overhead abstractions. Rust manages its memory using compile-time static analysis: checking for dangling pointers, ensuring mutability constraints and inserting calls for freeing memory as a part of type-checking. This analysis is not always perfect and sometimes it requires jumping through the hoops to get a Rust program to compile. Understanding the lifetime and borrow system thoroughly gets you quite far, but there are still some cases you can’t convince the compiler to accept the code, even if you can convince yourself that it is indeed safe. In this article I’ll list such cases: limitations of the borrow checker, the reasons why it doesn’t let the code pass and how the situation could possibly improve in the future. I hope that the borrow checker keeps evolving and some day this list becomes redundant.</p><h3>About references and lifetimes</h3><p>This is not meant to be a tutorial for Rust but I’ll briefly introduce the reference system a bit for starters. You can skip this part if you are already familiar with the concepts. Rust has the concept of “owned” values. Owning a value means that you have the single right and responsibility to dispose of it once you are done with it. Because there is no shared ownership built into the language, the compiler always knows when you are done with a value, so it inserts the call to the destructor automatically.</p><p>Other than using a value directly, you can take a reference to it — this is called <em>borrowing </em>in Rust parlance. References are like pointers in C, but they are checked for correctness. The lifetime system in Rust ensures that a reference can’t outlive the value it points to. You can’t also construct bogus references such as null references; you can only take a reference of an existing object. References are thus, always valid.</p><p>There are two kinds of references: shared references that look like this: &amp;MyType and mutable references that look like this &amp;mut MyType. You can have many shared references to a value, but you can’t mutate the value they point to. (There are some exceptions though, elaborated later.) If you want to mutate values through references, you can do that using a mutable reference, but you can have only one of those at a time. As long as a mutable reference to a value exists, that value can only be accessed (read or written) through that reference. No one else— including the owner — are allowed to access the value while the mutable reference exists.</p><h3>The design decisions to live by</h3><p>There are some good reasons why the Rust reference system is so restrictive. First of all, having single ownership ensures that it’s not easy to leak values and it’s impossible to “double-free” them — calling the destructor twice. Rust ensures the single ownership principle by being <em>move-by-default</em>. That means that if you pass a value somewhere, you lose the ownership over it and can’t use it anymore. This is also called <em>affine typing</em>. (Often confused with <em>linear typing</em>; see here for further discussion: <a href="https://gankro.github.io/blah/linear-rust/">https://gankro.github.io/blah/linear-rust/</a>) Rust also supports types that are <em>copy-by-default</em>; many fundamental types such as integers are defined such and you can define your own but <em>move-by-default</em> makes sense as a conservative default.</p><p>As for the mutable references, the principle of a single mutable reference may feel overly restrictive from the perspective of a C programmer who can have multiple mutable pointers to a value. However, there are valid reasons for that. For a convincing practical reason from software development perspective, see this blog post by Manish Goregaokar: <a href="https://manishearth.github.io/blog/2015/05/17/the-problem-with-shared-mutability/">https://manishearth.github.io/blog/2015/05/17/the-problem-with-shared-mutability/</a> .</p><p>Other than that, there is some additional reasons: one of them has to do with compiler optimizations around aliasing and another has to do with thread safety. To quickly explain the gist of these two: single mutability ensures that you can safely keep the value in processor register without fear that some other piece of code invalidates the version that resides in RAM — this can enable nice optimisation speedups. It also ensures that if you send a mutable reference to another thread, there aren’t any other mutable references left that could cause race conditions when writing through them in an unsynchronized manner from multiple threads. Mutable references in Rust are guaranteed to be <em>unique</em>, and it would cause undefined behaviour to somehow being able to clone one. Fortunately the type checker protects you from that.</p><p>There is still one general principle that affects the design decisions of Rust: all analysis should be local. No whole-program stuff. Rust programs must be type checkable function-by-function. The function signatures have to contain enough of lifetime and type information that the body can be checked. This also means that some situations where the borrow checker might seem stupid (“This function only mutates only field A, so why can’t I call also that function that mutates field B, they are different fields! It should allow that much!”), but the point is that it isn’t allowed to “peek into” functions other than the one it is currently checking. All it gets to know are the function signatures.</p><h3>The shortcomings with answers</h3><p>So, here is the meat of this article. I’d like to review some cases that are certainly safe, but for one reason or another, the borrow checker isn’t sophisticated enough to see that. I’ve ordered the cases by whether there exists an upcoming solution for the problem or if the problem is still unsolved. The first part consists of problems that are about to get fixed. That’s exciting, so let’s get started!</p><h4>1. Doing control flow aware stuff</h4><p>At the moment, the borrow checker thinks of the code as a bunch of hierarchically nested scopes, or blocks. The outer scopes outlive the inner ones and the borrow lifetimes behave accordingly. This is a very simple way to think of the borrows — but a rather unsophisticated one. It breaks down when the control flow doesn’t match the block structure. Here’s an example borrowed (ha!) from Niko Matsaki’s excellent introduction to the problem. (<a href="http://smallcultfollowing.com/babysteps/blog/2016/04/27/non-lexical-lifetimes-introduction/">http://smallcultfollowing.com/babysteps/blog/2016/04/27/non-lexical-lifetimes-introduction/</a>) As you can see, the borrow checker is being overly conservative; even in the branch None where value, derived from map, doesn’t exist, it considers map as borrowed:</p><pre>fn process_or_default&lt;K,V:Default&gt;(map: &amp;mut HashMap&lt;K,V&gt;,<br>                                   key: K) {<br>    match map.get_mut(&amp;key) { // -------------+ &#39;lifetime<br>        Some(value) =&gt; process(value),     // |<br>        None =&gt; {                          // |<br>            map.insert(key, V::default()); // |<br>            //  ^~~~~~ ERROR.              // |<br>        }                                  // |<br>    } // &lt;------------------------------------+<br>}</pre><p>There’s some other juicy examples too in the linked blog post; highly recommended reading!</p><p><strong>Remedy: Non-lexical lifetimes</strong></p><p>There are ongoing efforts to land improvements to the borrow checker that allow it to reason about the borrows with finer granularity. The RFC describing the proposal in detail can be found here: <a href="https://github.com/rust-lang/rfcs/blob/master/text/2094-nll.md">https://github.com/rust-lang/rfcs/blob/master/text/2094-nll.md</a>. The improved borrow checker is currently available on the beta version of the compiler and will be available stabilised on release 1.31, as a part of the new 2018 edition. Only some weeks to go! It’s not panacea, though; as mentioned before, it can only reason about things local to the current function, so however simple, no “intra-procedural analysis” is done.</p><h4>2. Postponing mutability of a lifetime</h4><p>An oft-recurring pattern:</p><pre>items.mutate_n(items.len());</pre><p>At glance, this looks fine — first the length of the container items is measured by the method len which takes a shared, immutable reference to items. After the value has returned, it is passed to the method mutate_n along with a mutable reference to items. No mutable and shared lifetimes are supposed to overlap. However, there’s a complication due to Rust’s evaluation order. Here’s a desugared version of the method calls:</p><pre>let receiver_of_mutate_n = &amp;mut items; // A mutable (unique) borrow!<br>let receiver_of_len = &amp;items; // A shared borrow!<br>let result_of_len = Collection::len(receiver_of_len);<br>let result_of_mutate_n = Collection::mutate_n(<br>    receiver_of_mutate_n,<br>    result_of_len<br>);</pre><p>As you can see, the receiver is resolved before the expressions inside the parentheses! This means that there exists shared references at the same time there exists a mutable reference, which isn’t allowed! Admittedly, if the nested call would mutate items there would be some fertile ground for nasty and hard to notice bugs, but in this case we’d want to allow this, as len is only a read-only method that can’t cause any harm.</p><p><strong>Remedy: Enabling nested method calls</strong></p><p>Granted, “postponing” the mutability of a lifetime in presence of nested method calls feels kind of a special case but it’s nice for ergonomics since it’s an often recurring pattern. There has been an approved RFC around this case (<a href="https://github.com/rust-lang/rfcs/pull/2025">https://github.com/rust-lang/rfcs/pull/2025</a>), and it too is going to land on 1.31, edition 2018!</p><h4><strong>3. Skipping trivial bounds in data types</strong></h4><p>When defining data types with generics and lifetimes, the compiler can be a bit pedantic:</p><pre>struct MyGenericDataType&lt;&#39;a, T: &#39;a&gt; {<br>    foo: &amp;&#39;a T,<br>}</pre><p>See the &lt;&#39;a, T: &#39;a&gt; part there? It’s needed. What we have here is a generic struct that holds a reference to any type T. First of all, Rust requires you to spell out the lifetime of the reference. Since it’s a data type that can be instantiated at any point of our program, there is no one and true lifetime that our struct will have — after all, it depends on the reference we store in there! That’s why the type is <em>generic</em> over lifetimes. &lt; &gt; is the Rust syntax for declaring generic types, and by specifying a lifetime annotation &#39;a there, we declare that the struct is valid for any lifetime the reference it contains is valid for. (Note that the type of field foo contains the lifetime &#39;a.) However, our struct is <em>also</em> generic over the actual type the reference points to! That’s what T refers to. It stands for “any type”.</p><p>Enter the pedantic part: we need one more annotation, T: &#39;a, which means that the type T outlives lifetime &#39;a. What does that mean? It means that the value the reference points to must live longer than the reference itself. Makes sense! If it wouldn’t, we would have a dangling pointer!</p><p>Except that this is totally <em>trivial</em>. Of course it has to live longer! Why do we have to spell that out? There’s no way that the pointer could soundly live longer than the pointee! It’s a model example of boilerplate code — it’s the only sensible choice and yet we have to spell it out.</p><p><strong>Remedy: Inferring outlives requirements on structs</strong></p><p>There is an accepted RFC (<a href="https://github.com/rust-lang/rfcs/pull/2093">https://github.com/rust-lang/rfcs/pull/2093</a>) that says that the trivial bounds such as introduced above can be elided. That would allow us to write just &lt;&#39;a, T&gt; instead of the verbose &lt;&#39;a, T: &#39;a&gt;. This feature, too, will land on 1.31, as a part of edition 2018.</p><h4>4. Splitting up mutable references</h4><p>A commonly expressed concern about Rust is that it’s hard to get from one mutable reference to many. If you have a HashMap of items you can get a mutable reference to a single item inside it, but you can’t get many! Why is that? The <a href="https://doc.rust-lang.org/std/collections/struct.HashMap.html#method.get_mut">get_mut</a> method of HashMap receives a mutable reference to the hash map itself: &amp;mut self. The method then returns a reference to an item contained in the hash map: &amp;mut Item. Because the item reference points inside the hash map, it must have the same or shorter lifetime as the &amp;mut self reference — it can’t outlive that, because that would allow us to dispose of the hash map, and the item reference would become a dangling pointer. Since we are talking about mutable references here, that also means that we can’t have many of them! We can only call get_mut again after the lifetime of the last borrow has ended!</p><p>But, you say, obviously calling get_mut multiple times should be allowed here, since the call doesn’t <em>actually</em> do anything bad! And being able to get multiple mutable references out of a hash map sounds so elementary that of course it should be allowed. However, imagine what we could do without that limitation: we’d call get_mut to get a mutable reference to item A. Then we’d call get_mut to get <em>another</em> mutable reference to item A and find ourselves from the world of undefined behaviour.</p><p>There’s a similar, but even more obviously “stupid” limitation:</p><pre>let mut array = [1, 2, 3, 4];<br><br>let ref_a = &amp;mut array[1];<br>let ref_b = &amp;mut array[2]; // This isn&#39;t allowed!<br>*ref_a = 9;<br>*ref_b = 9;</pre><p>I’ve seen people new to Rust complain about this many times. Obviously the indexes 1 and 2 do not overlap, so having a mutable references to them should be allowed. However, the compiler doesn’t have any specialised knowledge about array indexing to understand this! It just plays its game with lifetimes, borrows and mutability. The end result of having two non-overlapping mutable references is fine from this perspective, but if the means to achieve that are against the rules, the compiler is not going to give in.</p><p><strong>Remedy: Helper APIs</strong></p><p>In the Rust standard library, there is the method split_mut on slices that is the model example of helper API that improves the situation. Using split_mut we can split a mutable slice into two non-overlapping subslices. For example, we can split &amp;mut [1, 2, 3, 4] to &amp;mut [1, 2] and &amp;mut [3, 4] or to &amp;mut [1] and &amp;mut [2, 3, 4]. These subslices can be accessed separately and of course, split even further. Another example is iterators: you can mutably iterate over a vector, and as a result get a mutable reference to each of the elements.</p><p>So the borrow checker doesn’t actually need to be super smart. Using a bit of unsafe code and wrapping that behind a safe interface, helper APIs can be defined to save the day. In the future I would like to see more these kind of APIs in the standard library.</p><p>For example, HashMap could have today a method get_pair_mut that returns two mutable references to two separate items. Of course it would have to perform a run-time check that the items are actually separate, but that’s the price of a safe API. It would also be possible to have facades on top of existing containers that would keep track dynamically which items are borrowed out and which aren’t. Actually, I did a bit of experimenting with such APIs a year back: <a href="https://github.com/golddranks/multi_mut">https://github.com/golddranks/multi_mut</a></p><p>There aren’t any proposals to expand the current set of helper APIs that I know of. We need a hero that champions an RFC for that! The upcoming language features such as const generics and stack-allocated dynamically sized types are likely to help defining better helper APIs too. (I’m imagining a facade over containers that uses dynamically sized types on stack to keep track of the borrows without needing to heap allocate a buffer for that.)</p><h4>5. Having multiple aliasing mutable references</h4><p>From a semi-seasoned Rustacean, this sounds like an oxymoron. “Rust isn’t supposed to have these! They were supposed to be awful!” Yet it sometimes helps to be able to have multiple mutable pointers to the same location. Every C programmer knows that aliasing pointers is definitely possible technically, so why doesn’t Rust cut us some slack?</p><p>The aliasing restrictions of Rust have good reasons I already spelled out in the above chapter <em>The design decisions to live by.</em> On the other hand, if C gets away with mutable aliased pointers, why should we constrain ourselves to the spartan asceticism of the current borrow checker? Fortunately Rust provides us an escape hatch (other than using raw pointers and unsafe code): the Cell type. Cell is a wrapper type that can be mutated even through shared — an thus normally immutable — references. Using Cell requires the compiler to be a bit more cautious. It must be more careful with aliasing and it mustn’t allow any references to a Cell-wrapped type across threads, as that would lead to data races.</p><p>Here’s an example — from the viewpoint of a seasoned Rustacean, this might feel abhorrent; the value of fuga just changes under your feet. However, it shows that this kind of code is possible in Rust too.</p><pre>use std::cell::Cell;</pre><pre>fn borrow_add_one(val: &amp;Cell&lt;u32&gt;) -&gt; &amp;Cell&lt;u32&gt; {<br>    val.set(val.get() + 1);<br>    val<br>}</pre><pre>fn main() {<br>    let hoge = Cell::new(4);<br>    let fuga = borrow_add_one(&amp;hoge);</pre><pre>    // Prints &quot;fuga == 5&quot;<br>    println!(&quot;fuga == {:?}&quot;, fuga);</pre><pre>    hoge.set(10); // Mutating hoge but fuga changes too!</pre><pre>    // Prints &quot;hoge == 10, fuga == 10&quot;<br>    println!(&quot;hoge =={:?}, fuga == {:?}&quot;, hoge, fuga);<br>}</pre><p>Anyway, here’s the actual problem: Cell allows us to bend the curve when we need it, but it also requires us to define our types as Cell beforehands! It’s a <em>wrapper</em> <em>type</em>, after all. What if we have a huge program with established data types? If we want to use Cell, it would be awful to refactor the whole program to use this pattern if we need to.</p><p><strong>Remedy: Conversions from </strong><strong>&amp;mut T to </strong><strong>&amp;Cell&lt;T&gt;</strong></p><p>There is an accepted RFC (<a href="https://github.com/rust-lang/rfcs/pull/1789">https://github.com/rust-lang/rfcs/pull/1789</a>) that basically states that the actual byte representation of T and Cell&lt;T&gt; is the same. That means that converting between them, and even converting between references to them is a no-op procedure from runtime viewpoint. The only difference between the two is what the compile-time type system allows. It then becomes possible to convert and use &amp;mut T to &amp;Cell&lt;T&gt; even if the codebase T originates from doesn’t have any Cell types to begin with. Once you have a unique, mutable reference to some type T, you can “fan out” that reference out to multiple shared references Cell&lt;T&gt; do what you must, and then give the references up — everything’s back to normal. The conversion is currently implemented, but not stabilised yet.</p><p>There is also already existing pattern for the other direction: since the memory representations of T and Cell&lt;T&gt; were defined to be equivalent, it is possible to go from &amp;mut Cell&lt;T&gt; to &amp;mut T! The mutable reference to Cell ensures that no other references pointing to the Cell exist. That means that the compiler can safely relax a bit, and consider the inner type as a non-Cell type for the lifetime of the mutable reference. It is helpful for passing Cell-wrapped types to APIs that don’t expect Cell types. The API for that was stabilised in Rust 1.11.</p><h4>6. Being able to point inside Cell types</h4><p>Being able to convert &amp;mut T to &amp;Cell&lt;T&gt; allows for great flexibility, but it only goes so far. The greatest flaw in &amp;Cell&lt;T&gt;, besides the caveats mentioned this far, is that you can’t have any references pointing to the <em>insides</em> of it. Let’s think for a moment why.</p><p>In Rust, there are basically two kinds of data types: structs and enums. Structs are familiar to many, but enums are a rarer feature; they are not like enums in C; they are basically tagged unions: a pair that consists of a union — a memory area that can represent any one of the many declared types or <em>variants</em> — and a tag that is used to tell which one it currently is. Let’s suppose that we have the following enum:</p><pre>enum JsonValue {<br>    String(String),<br>    Number(f64),<br>    Boolean(bool),<br>    Object(Map),<br>}</pre><p>Let’s build a JsonValue that is inside a Cell: Cell::new(JsonValue::Boolean(false))Then, suppose that we take a reference to the inner boolean. Our reference of type &amp;bool points to the value false. Let’s suppose that we would change the value of our enum, using another&amp;Cell&lt;JsonValue&gt; reference, to Number(2). That would break everything! Why? Because that would make our first reference that is supposed to be a &amp;bool to point something that is definitely not a bool. We have just broken our type system! Beware of the nasal demons. (<a href="http://catb.org/jargon/html/N/nasal-demons.html">http://catb.org/jargon/html/N/nasal-demons.html</a>)</p><p>So, there’s a good reason why the Cell types prevent inner references. Especially the type of mutability that can change the memory layout of the type can easily cause UB, but as mentioned before, there are subtler reasons around aliasing and threading too. When the type is wrapped in Cell, the compiler knows to be careful, but if we could get a normal reference to the inner value, we would be able to “cheat”, having just a normal &amp;T reference that the compiler doesn’t know to be careful of. The compiler would have a false sense of security that the pointed value couldn’t possibly change, while we could actually change it through another &amp;Cell&lt;T&gt; reference. But what if we really really want to access the insides of Cell&lt;T&gt; with a finer granularity?</p><p><strong>Remedy: Conversion between </strong><strong>&amp;Cell&lt;[T]&gt; → </strong><strong>&amp;[Cell&lt;T&gt;], conversion between </strong><strong>&amp;Cell&lt;T&gt; → </strong><strong>(&amp;Cell&lt;field of T&gt;, ...).</strong></p><p>Actually, there is a pattern that allows referencing the insides of a Cell&lt;T&gt; safely: splitting it up to non-overlapping parts and having each of the constituents live behind another Cell reference. The point is to never allow “bare” references point in. References with Cell are safe to modify, because the compiler knows to be careful.</p><p>The same RFC mentioned in the last item also allows conversions between &amp;Cell&lt;[T]&gt; and &amp;[Cell&lt;T&gt;]. That basically means that you can have just a normal slice of values of type T and go from &amp;mut [T] to &amp;Cell[T] to &amp;[Cell&lt;T&gt;] and end up with a sliceful of mutably aliasable values! As said, the RFC is accepted and implemented, but not stabilised yet.</p><p>Similarly, it would be possible to convert a &amp;Cell&lt;MyStruct&gt; to a tuple that contains Cell references to the fields of that struct: (&amp;Cell&lt;type of field 1&gt;, &amp;Cell&lt;type of field 2&gt;, …) . However, there is no plausible mechanism in the language at the moment to specify a general pattern like that. There has been some design discussion circling around the topic. (<a href="https://internals.rust-lang.org/t/idea-derefpin-derefcell/7292">https://internals.rust-lang.org/t/idea-derefpin-derefcell/7292</a>) Maybe we’ll see a Cell field projection in the future? That would require, again, someone to think about the design and write an RFC.</p><h4>7. Having self-referencing structs</h4><p>Sometimes there is a need for a struct to have a reference pointing to itself. This has become especially important recently with the work on generators. Generators need to represent their suspended stack frames as first-class values. One can take a reference to a value in the same stack frame inside a generator and then suspend. This makes the the generators self-referencing.</p><p>Why self-references are a problem? Because stuff moves and references stay valid only as long as the objects they point to stay put, so allowing self-references while not forbidding moving, we are going to have dangling pointers. Rust is actually able to do some reasoning around self-referential structs:</p><pre>#[derive(Debug)]<br>struct Game&lt;&#39;p&gt; {<br>    player_a: u32,<br>    player_b: u32,<br>    current_player: Option&lt;&amp;&#39;p u32&gt;,<br>}</pre><pre>fn main() {<br>    let mut g = Game {<br>        player_a: 10,<br>        player_b: 20,<br>        current_player: None<br>    };<br>    g.current_player = Some(&amp;g.player_a);<br>    println!(&quot;{:?}&quot;, g.current_player); // prints Some(10)<br>    g.current_player = Some(&amp;g.player_b);<br>    println!(&quot;{:?}&quot;, g.current_player); // prints Some(20)<br>}</pre><p>If we try to move g, it complains that there is a reference to it. However, problems start right away with examples any more complicated than this — with mutability, to begin with. For example, if you store the struct in heap using a Box and then try to access it mutably, initialising the field current_player with a self reference, the whole lifetime of the struct gets “tainted” with the mutable borrow, because by storing a reference derived from that borrow in the struct itself, we accidentally set the lifetime of the mutable borrow equal to the lifetime of the struct itself. The struct “locks up” — we lose the ability to access it using any other reference until it’s dropped.</p><p>We would need some way to signal the borrow checker that after mutating the struct, we have “downgraded” the lifetime (see also the the item 10 about downgrading mutable lifetimes) to a shared one. But even if we would be able to do that, since the struct still contains a reference derived from a borrow of the struct itself, the struct would stay in a “borrowed mode” until it gets dropped — we could never mutate it again.</p><p>Wrapping current_player into a Cell cuts us some slack with mutability. But even then we are in troubles with lifetimes:</p><pre>use std::cell::Cell;</pre><pre>#[derive(Debug)]<br>struct Game&lt;&#39;p&gt; {<br>    player_a: u32,<br>    player_b: u32,<br>    current_player: Cell&lt;Option&lt;&amp;&#39;p u32&gt;&gt;,<br>}</pre><pre>fn init_game&lt;&#39;???&gt;() -&gt; Box&lt;Game&lt;&#39;???&gt;&gt; {<br>    let g = Box::new(Game {<br>        player_a: 10,<br>        player_b: 20,<br>        current_player: Cell::new(None)<br>    });<br>    g.current_player.set(Some(&amp;g.player_a));<br>    g // Doesn&#39;t work!<br>}</pre><pre>fn main() {<br>    let game = init_game();<br>    println!(&quot;{:?}&quot;, game);<br>}</pre><p>Note the lifetime &#39;???! There is no lifetime that we could name that fits there. The lifetime clearly isn’t something that the caller of the function can decide as a parameter, since it’s simply the lifetime of how long the heap-allocated Game happens to live — that might depend on anything, including the runtime control flow. On the other hand, the self-reference, originally borrowed from g lives only as long as the variable g does — the borrow checker doesn’t understand that the reference actually points to a heap allocation that is going to live longer than the variable g. This means that we can’t meaningfully pass the self-referential types down or up the stack, even if it would be safe in the sense that the heap allocation doesn’t move. (See the item 14 for further discussion!)</p><p>No, it seems that we have to use unsafe code and raw pointers. The borrow checker doesn’t check raw pointers, so they provide us all the flexibility we need. But then we face another problem: if nobody checks for the correctness, do we lose the ability to abstract the unsafety away, behind a safe interface? What if we release a library that uses self-referencing types, but our users shoot themselves in foot because they accidentally move the value without realising that isn’t allowed?</p><p><strong>Remedy: Pin references</strong></p><p>There was a recent RFC that addresses this problem: Pin references. (<a href="https://github.com/rust-lang/rfcs/blob/master/text/2349-pin.md">https://github.com/rust-lang/rfcs/blob/master/text/2349-pin.md</a>) Having an object behind a pin reference provides an important guarantee: either the object is safe to move or it is <em>not safe</em> but <em>will not</em> move until it’s dropped. So using pin, one is able to require the users of a type not to move it. Actually getting a mutable reference to the insides of a pin that contains a self-referencing type requires unsafe code; anybody getting a mutable reference will do so knowing that they must not move the value. Pin references are going to be in the standard library soonish—the stabilisation has been a proposed but not decided upon yet.</p><h4>8. Capturing only disjoint fields in closures</h4><p>There is a slight ergonomics problem when using closures: they tend to capture values too eagerly:</p><pre>fn update(&amp;mut self) {<br>    // borrowing self.list mutably<br>    self.list.retain(<br>        |i| self.filter.allowed(i) // can&#39;t borrow self!<br>    );<br>}</pre><p>The problem here is that although self.list and self.filter are separate fields and can normally be borrowed separately, the closure tries to borrow self as a whole! There is a simple workaround: manually borrow the field and then let the closure capture that:</p><pre>fn update(&amp;mut self) {<br>    let filter = &amp;self.filter;</pre><pre>    self.list.retain(|i| filter.allowed(i));<br>}</pre><p>Having to do this is annoying; it’s not a show stopper, but certainly it would be nice if would be a bit smarter automatically.</p><p><strong>Remedy: Capture disjoint fields</strong></p><p>There is a merged RFC that makes the closure capture smarter by default: <a href="https://github.com/rust-lang/rfcs/pull/2229">https://github.com/rust-lang/rfcs/pull/2229</a> It’s not stabilised yet though.</p><h4>9. Having associated types that are generic over lifetimes</h4><p>When processing data from a stream, it’s not uncommon to have a buffer that holds a “chunkful” of the data being processed. You can reuse the buffer when you are done with processing the current data. This helps to avoid allocations during the operation. Of course this means that references to the buffer are valid only for the lifetime of the current chunk — once we start overwriting the buffer with new data, all the references pointing the previous data in the buffer must be gone.</p><p>It would be nice to express this as an iterator pattern! Think of it: looping over the contents of the stream like we usually loop over data containers. However, there’s a problem with the iterator interface that blocks us from expressing this:</p><pre>trait Iterator {<br>    type Item;<br>    fn <a href="https://doc.rust-lang.org/std/iter/trait.Iterator.html#tymethod.next">next</a>(&amp;mut self) -&gt; <a href="https://doc.rust-lang.org/std/option/enum.Option.html">Option</a>&lt;Self::<a href="https://doc.rust-lang.org/std/iter/trait.Iterator.html#associatedtype.Item">Item</a>&gt;;<br>}</pre><p>The main workhorse of the Iterator trait is the next method that returns the items of the iterator. Item is an associated type — every implementation of the trait can decide what that iterator spits out. As we are iterating over a stream, we would like to spit out a reference to the buffer that holds the current chunk of the data. However, if we set type Item = &amp;&#39;a Chunk, we soon stumble into expressiveness problems. What is the lifetime &#39;a? It should be the same lifetime as of the &amp;mut self of the next method, but as Self::Item doesn’t have any lifetime parameters, we are unable to express that!</p><p>It turns out that iterators are able to return only &#39;static items (items that don’t contain lifetimes at all or items that contain only lifetime &#39;static) such as String or u32, or items with lifetimes that are nameable by the type that implements Iterator. Here’s an example of the latter:</p><pre>struct StrVecIter&lt;&#39;a&gt; {<br>    index: usize,<br>    inner_vec: &amp;&#39;a Vec&lt;String&gt;,<br>}</pre><pre>impl&lt;&#39;a&gt; Iterator for StrVecIter&lt;&#39;a&gt; {<br>    type Item=&amp;&#39;a str; // We can use StrVecIter&#39;s &#39;a here<br>    fn next(&amp;mut self) -&gt; Option&lt;&amp;&#39;a str&gt; {<br>        let s = self.inner_vec[self.index].as_str();<br>        self.i += 1;<br>        Some(s)<br>    }<br>}</pre><p>Turns out that Rust’s iterators don’t support so-called <em>streaming iterator</em> pattern. They can only return references that live as long as the container they refer to, lives. We want to return references with a shorter lifetime — by the next call to next the previous reference should already be gone!</p><p><strong>Remedy: generic associated types</strong></p><p>The problem was with the associated Item type — it should be generic over lifetimes so that we could use it in the next method to equate it with the lifetime of &amp;mut self <em>each</em> call. As it turns out, Rust doesn’t at the moment support generics in the associated types of traits. Fortunately that is subject to change: an RFC that enables that feature has been accepted: <a href="https://github.com/rust-lang/rfcs/blob/master/text/1598-generic_associated_types.md">https://github.com/rust-lang/rfcs/blob/master/text/1598-generic_associated_types.md</a></p><p>The implementation is not done yet and the feature is not considered high priority before 2018 edition, but I’m hopeful that we’ll hear more about it early next year and possibly see it stabilised at some point of the year. This feature doesn’t only provide added expressiveness around streaming iterators, it should enable a whole lot of other nice patterns too.</p><h4>Addendum: Getting ownership over a mutable reference</h4><p>(Added 15th September 2018. In the end of this article, I asked people to point me out cases that I didn’t think of, and the people of the <a href="https://www.reddit.com/r/rust/comments/9w9ldx/things_rust_doesnt_let_you_do/e9kt3pe/">/r/rust subreddit did</a>! Thank you.)</p><p>Because Rust differentiates between owned and borrowed values, sometimes it so happens that you have only a mutable reference whereas you need to pass owned value in a function to use some API. You might need to refactor and get an owned value instead of a reference, which may be cumbersome because then you just move the requirement for ownership around, or you might have to clone which can be expensive. Sometimes you can’t even do that; some values don’t even implement the Clone trait. (Often if they don’t, they have a good reason not to, but there can be omissions, of course.)</p><p>However, it gets irritating when the requirement for ownership is seemingly trivial: an API that takes in an owned object but <em>returns</em> an owned object of the same type. After the fact, you still have <em>an object </em>of the same type, so you haven’t lost anything, type theoretically speaking. If you could move an object out of a mutable borrow <em>for just a bit</em>, and then return it, everything would be easier. Is there a way to do it, or is it a hard limitation of the borrowing system?</p><p>Actually, Niko Matsakis started recently a blog series about the current limitations of the borrow checker, which coincides with the theme of this article almost perfectly. I’m doing to forward the further discussion about this problem and the workarounds to his blog. As basically everything Niko writes, it’s highly recommended reading! See it here: <a href="http://smallcultfollowing.com/babysteps/blog/2018/11/10/after-nll-moving-from-borrowed-data-and-the-sentinel-pattern/">http://smallcultfollowing.com/babysteps/blog/2018/11/10/after-nll-moving-from-borrowed-data-and-the-sentinel-pattern/</a></p><h3>Open problems: from here on there be dragons</h3><p>At this point, we have exhausted stuff that are agreed upon via the RFC process. For the rest of the items in this article, there are going to problems without ready-made remedies. I think each of these problems can be solved, but doing so will require a significant amount of design and consensus work.</p><h4>10. Downgrading a mutable lifetime to a shared one</h4><p>It’s not uncommon to call methods that mutate some fields but return just a shared reference:</p><pre>impl Request {<br>   fn get_header(&amp;mut self) -&gt; &amp;Header {<br>      if let Some(cached) = self.cache.retrieve() {<br>         cached<br>      } else {<br>         let parsed = self.parse_header();<br>         let cached = self.cache.store(&amp;parsed); // Needs &amp;mut self<br>         cached<br>      }<br>   }<br>}<br>...<br>let header = request.get_header();</pre><p>However, as long as we grab to our header, we aren’t allowed to call <em>any</em> other methods on request! It’s completely locked up. Why? Because we originally borrowed request with a mutable lifetime and no additional borrows are possible until that lifetime has ended.</p><p>But, you say, the returned header is only a shared reference! Surely calling other methods that take &amp;self, a shared reference, is okay. But it’s actually not. For what the borrow checker knows, get_header could have stashed a mutable reference to request somewhere. Maybe send it to another thread? Maybe store it in the local thread storage? Maybe hide it in a Cell&lt;Option&lt;&amp;mut Cache&gt;&gt; field in the returned header? There isn’t any ironclad guarantee that the mutability of the lifetime would be actually over until the end of the borrow. Here’s another great example of this: <a href="https://internals.rust-lang.org/t/blog-post-nested-method-calls-via-two-phase-borrowing/4886/33">https://internals.rust-lang.org/t/blog-post-nested-method-calls-via-two-phase-borrowing/4886/33</a></p><p>Anyway, the request “locking up” is annoying. In some cases, it’s sensible to wrap the cache field in a Cell and be done it. But wouldn’t it be nice if the API itself could declare that it really is done with mutating things?</p><p><strong>Remedy: Read-write lifetimes? Downgrade declarations?</strong></p><p>There have been some ideas around having <em>two </em>lifetimes when taking a reference: a read lifetime and a write lifetime. Strawman syntax:</p><pre>fn mut_then_share&lt;&#39;w, &#39;r: &#39;w&gt;(&amp;{&#39;w -&gt; &#39;r} mut self) -&gt; &amp;&#39;r u32</pre><p>The idea behind this is that the write lifetime is a subset of the read lifetime. The concerns are separated, so the write lifetime may be dropped earlier, leaving only the shared lifetime. Another plausible syntax would be some kind of “downgrade declaration”:</p><pre>fn mut_then_share&lt;&#39;a, &#39;b&gt;(&amp;&#39;a mut self) -&gt; &amp;&#39;b u32<br>    where &#39;b: &#39;a + const</pre><p>There seems to be some support behind these ideas, but they are effectively postponed after the work on non-lexical lifetimes has finished. There are also going to be some design issues about the conditions where downgrading can be regarded safe but I’m hopeful we’ll see this feature in some form in the future!</p><h4>11. Calling mutable methods that don’t access overlapping fields</h4><p>I remember being frustrated with this one when I started Rust:</p><pre>struct Brute {<br>    name: String,<br>    cry: String,<br>}</pre><pre>impl Brute {<br>    fn new() -&gt; Self {<br>        Self { name: &quot;Pochi&quot;.into(), cry: &quot;WOOF!&quot;.into() }<br>    }</pre><pre>    fn get_name(&amp;self) -&gt; &amp;str { &amp;self.name }</pre><pre>    fn set_cry(&amp;mut self, cry: &amp;str) -&gt; bool {<br>        self.cry = cry.to_ascii_uppercase();<br>    }<br>}</pre><pre>fn main() {<br>    let mut pochi = Brute::new();<br>    <br>    let pochis_name = pochi.get_name();<br>    <br>    pochi.set_cry(&amp;pochis_name); // Can&#39;t borrow!<br>}</pre><p>This pattern often emerges with getter/setter style accessors. The problem is that the methods take references to self as a whole and — as mentioned earlier — by design, the borrow checker can’t peek into the method bodies and see which fields are actually accessed.</p><p>If a similar access pattern is done locally, there is no problem; the borrow checker can see that the name and cry fields are non-overlapping and can be borrowed separately. That means that as a workaround with structs, you can set the fields public and access them directly, but this isn’t good if your type has invariants you want to protect. For example, here we want to ensure that cry is always uppercase!</p><p>This is especially troubling when working with traits and generic code. Traits are collections of interface methods; even if the underlying type that implements a trait has non-overlapping fields, the trait hides that as an implementation detail, so you are forced to access self without finer granularity.</p><p><strong>Remedy: Fields in traits? Read-only fields? Partial borrows?</strong></p><p>To address the problem with traits, there has been an RFC <a href="https://github.com/rust-lang/rfcs/pull/1546">(https://github.com/rust-lang/rfcs/pull/1546</a>) that allows defining field in traits that each implementer maps to the corresponding fields it has. Fields are different from setter and getter methods in the sense that the compiler can verify that they actually map to non-overlapping memory, allowing safe access. The RFC was postponed for now— but there is still demand for a feature like this and I’m quite sure it will be revisited after the 2018 edition has shipped.</p><p>Part of the design space has also got to do with mutability of fields. There are quite often patterns where you can show the contents of a field, but not allow it to be modified safely. As getters have the granularity problem described above, it would be desirable to expose the field itself publicly, while restricting the access to it to immutable only.</p><p>There has been also some ideas floating around about refining the granularity of self: methods would declare the fields they access in the function signature:</p><pre>fn get_name(self { &amp;name }) -&gt; &amp;str { &amp;self.name }</pre><pre>fn set_cry(self { &amp;mut cry }, cry: &amp;str) -&gt; bool {<br>    self.cry = cry.to_ascii_uppercase();<br>}</pre><p>This would allow the borrow checker to conclude that the method calls access non-overlapping fields without peeking into the method body.</p><p>All of these ideas have some drawbacks in the sense that they expose things that are currently thought of implementation details but we will see what comes out of them.</p><h4>12. Hiding mutable lifetimes in data types</h4><p>Some time ago there was a blog post by Aleksey Kladov (<a href="https://matklad.github.io/2018/05/04/encapsulating-lifetime-of-the-field.html">https://matklad.github.io/2018/05/04/encapsulating-lifetime-of-the-field.html</a>) that highlighted a problem with lifetime annotations in data types. The problem raises its head when nesting types with mutable lifetimes:</p><pre>struct Foo&lt;&#39;s&gt; {<br>    string: &amp;&#39;s mut String,	<br>}<br><br>struct Bar&lt;&#39;f, &#39;s: &#39;f&gt; {<br>    foo: &amp;&#39;f mut Foo&lt;&#39;s&gt;<br>}<br><br>struct Hoge&lt;&#39;b, &#39;f: &#39;b, &#39;s: &#39;f&gt; {<br>    bar: &amp;&#39;b mut Bar&lt;&#39;f, &#39;s&gt;<br>}<br><br>// As you see, the declarations are getting longer and longer!<br>struct Piyo&lt;&#39;p, &#39;b: &#39;p, &#39;f: &#39;b, &#39;s: &#39;f&gt; {<br>    hoge: &amp;&#39;p mut Hoge&lt;&#39;b, &#39;f, &#39;s&gt;<br>}</pre><p>The lifetime annotations don’t compose well! This isn’t a problem with shared lifetimes, which stay clean:</p><pre>struct Foo&lt;&#39;s&gt; {<br>    string: &amp;&#39;s String,	<br>}<br><br>struct Bar&lt;&#39;f&gt; {<br>    foo: &amp;&#39;f Foo&lt;&#39;f&gt;<br>}<br><br>struct Hoge&lt;&#39;b&gt; {<br>    bar: &amp;&#39;b Bar&lt;&#39;b&gt;<br>}</pre><pre>struct Piyo&lt;&#39;p&gt; {<br>    hoge: &amp;&#39;p Hoge&lt;&#39;p&gt;<br>}</pre><p>The difference here is that shared lifetimes — due to their restrictions with mutation — can be subtypes of other shared lifetimes. Mutable lifetimes, on the other hand don’t “mix and match”. This is a quite fundamental difference between the two kinds, and it must be respected to avoid soundness issues. However, the proliferating lifetime annotations get icky rather quick.</p><p><strong>Remedy: Hiding mutable lifetimes from type signature?</strong></p><p>Inspired by Aleksey’s blog post and the trick explained there that lifetimes can be hidden with trait objects, I started thinking about reifying this hiding mechanism as a language feature. I started writing an RFC, but it’s essentially just a draft at the moment: <a href="https://internals.rust-lang.org/t/pre-rfc-encapsulating-private-lifetimes/7500">https://internals.rust-lang.org/t/pre-rfc-encapsulating-private-lifetimes/7500</a> Getting busy with other things in life, I haven’t been polishing it, but hopefully I’ll manage to return into it some day.</p><h4>13. Using “ambient” lifetimes</h4><p>One of the important concerns for library code is modularity. A big part of application programming is composing available libraries to achieve higher-level goals, but if the libraries don’t play nicely together, this gets troublesome. Libraries should be either as simple or as generic as possible; or preferably if there exists a way to be simple <em>and</em> generic, do that. Especially requirements of specific “ambient” features in the runtime environment limit the generality of libraries. A great example of this is that the libraries with no_std capabilities have greater composability because they don’t depend on the standard library.</p><p>This is why I often think of&#39;static lifetime bounds as undesirable things in APIs. It limits what the user can pass in. If possible, it’s always better to be generic with regards to lifetimes to allow the user pass values with lifetimes that suit themselves.</p><p>What makes “forced” &#39;static even worse is the fact that statics are so hard to initialise. The crate <a href="https://github.com/rust-lang-nursery/lazy-static.rs">lazy_static</a> helps and there is also <a href="https://doc.rust-lang.org/std/boxed/struct.Box.html#method.leak">pattern where you can “forget” a heap-allocated value</a> to protect it from deallocation for the rest of the program lifetime and turn it into a reference to &#39;static. But these are essentially hacks: if you are unable to clean up after finishing your business with a library, that library can’t be said to be composable. Rust doesn’t have “life before main”, which is a great design decision—besides the other problems it prevents, it also reifies the fact that one should avoid “hard-coding” lifetimes. But requiring ‘static is essentially that: hard-coding lifetimes.</p><p>However, there’s an understandable reason why one would like to use the &#39;static lifetime for things: it’s the only globally nameable lifetime. An ambient lifetime, so to say. Because it’s a concrete lifetime that’s available everywhere, it doesn’t proliferate in the type declarations like generic lifetimes do. It’s more ergonomic to use and easier to understand.</p><p>Is there any way we could prevent the hard-coding problem and still have the ease of using &#39;static?</p><p><strong>Remedy: ambient lifetimes/module-level lifetimes</strong></p><p>Imagine if there would be a lifetime like &#39;static in the sense that you don’t have to write it into the signature of your types? A lifetime that would say: I live longer than this struct could ever possibly live, so you don’t have to care what I am.</p><pre>mod library&lt;&#39;ambient&gt; {<br>    struct StringRefs {<br>        ref_a: &amp;&#39;ambient str,<br>        ref_b: &amp;&#39;ambient str,<br>    }</pre><pre>fn take_refs(refs: StringRefs) {<br>        println!(&quot;{}&quot;, refs.ref_a);<br>    }<br>}</pre><p>Here, &#39;ambient would live longer than <em>any type </em>defined in module library. It’s like a local version of &#39;static! Then, repurposing the use import statement a bit:</p><pre>fn main() {<br>    let string_a = String::from(&quot;No life&quot;);<br>    let string_b = String::from(&quot;Before main!&quot;);</pre><pre>    use library as lib { // &#39;ambient gets assigned to this scope<br>        let r = lib::StringRefs {<br>            ref_a: string_a.as_ref(),<br>            ref_b: string_b.as_ref(),<br>        };<br>        lib::take_refs(r);<br>    }<br>}</pre><p>Of course, the compiler would prevent any type with &#39;ambient leaving the scope. This allows initializing everything in main but after that initialization is done, the lifetime of the state that lives there can now be “freely” referred by the types, without the need to carry the lifetime information around in the type signatures.</p><p>Another interesting idea would have scopes that “repurpose” what &#39;static means for the code inside that scope: the code thinks that it has references to static things, but the caller has actually redefined it to be a narrower lifetime. I haven’t thought much about the soundness implications though; it might prove to be an outrageously unsafe idea.</p><h4>14. Moving the owner of a heap-allocated object that has an inbound reference</h4><p>I think of this problem as the granddaddy of all lifetime problems and that’s why I left it in the end. Lifetimes in Rust are essentially subject to stack discipline. An “outlives” relationship between two lifetimes means that the longer-living one originates from an outer scope or an earlier (shallower) stack frame.</p><p>A reference such as &amp;&#39;a Foo&lt;&#39;b&gt; can be thought as two values: the &amp;&#39;a part, which is essentially just a pointer, and the value being pointed at, here Foo&lt;&#39;b&gt;. The basic rule, of course, is that the value being pointed at must live longer than the pointer—but to elaborate, it must live longer <em>at the location being pointed at</em>. You see, there’s another distinction to be made: we can think of the value as pure information that we can copy and move around — or we can think of the memory slot the value resides in. That can’t move around. Pointers point at memory slots, so Rust ensures that slot stays valid by freezing the value, keeping it there.</p><p>Here the stack discipline kicks in: we can call other functions and pass the pointer deeper in the stack, while the pointed value stays put. But once we return, at some point, the memory location where the value resides must be given up. That’s the maximum extent the reference can live. (The minimum extent is of course, up to us, because we can just drop the reference anytime we want.)</p><p>This principle works wonderfully with the call stack. But it’s too restrictive with the heap. The lifetimes are not aware of the heap — there can be references to the heap, but they act as if the heap would be just a nice extension to the stack that allows dynamically sized allocations. The lifetime of a reference to a heap allocation is still constrained by the stack frame where the lifetime of the reference originated from.</p><p>That’s not how heap works though: unlike with stack, it’s possible to do a heap allocation and return that allocation from a function—so it’s unordered! And here’s the problem, hinted in the item 7 about self-referential structs: the lifetime system doesn’t understand that the lifetime of a heap-pointing reference is not constrained to the extent where the stack-allocated <em>owner </em>of the heap allocation<em> — </em>such as a Box—is located at the moment of the borrow. It’s constrained to the extent <em>the heap allocation lives</em>, and the heap allocation in many cases lives as long as the value of its owner lives. Note that here I don’t mean the <em>memory slot</em> of its owner but the actual <em>value</em>; the piece of information that can be moved around until it’s destructed.</p><p>It would be sound in principle to have a reference to a heap-allocated value and return that reference alongside of the owner of the heap allocation from a function, down the stack. Likewise, it would be sound to store them in a struct and encapsulate all the lifetimes involved. One could pass the struct along without any lifetime restrictions, because the lifetimes would be implementation details. This would be a boon for zero-copy parsers, graphics API wrappers (<a href="https://github.com/vulkano-rs/vulkano/blob/master/TROUBLES.md">https://github.com/vulkano-rs/vulkano/blob/master/TROUBLES.md</a>) and basically everyone using the crates <a href="https://crates.io/crates/rental">Rental</a> and <a href="https://crates.io/crates/owning_ref">Owning-Ref</a> at the moment.</p><p><strong>Remedy: Dependent/existential lifetimes?</strong></p><p>There is a significant challenge in designing a lifetime system that would ensure the soundness in safe code while allowing greater flexibility with references to heap allocations. Such a system must adhere to all the design principles of Rust mentioned earlier: it should be locally analysable and statically checked. It should be combatible with the current lifetime system and preferably a minimal extension. I’m not aware of any serious attempts at trying to come up with a working solution yet.</p><p>We could think of the pointer and owner of the pointed allocation as a pair that are connected by the guarantee that at no point the pointer is “lower” in the call stack or in the local scope than the pointee — either the pointer is deeper in the stack or they are being passed down together. Imagine something like this:</p><pre>// Note the for syntax!<br>fn init() -&gt; for&lt;&#39;base: &#39;ref&gt; (BorrowedBox&lt;u32, &#39;base&gt;, &amp;&#39;ref u32) {<br>    let heap_box = Box::new(10);<br>    <br>    // get_existential takes the box as a value<br>    // and returns a pair with an existential lifetime<br>    let (borrowed_box, heap_ref) = heap_box.get_existential();<br>    <br>    // The borrow checker locally checks that any value<br>    // containing &#39;ref doesn&#39;t outlive a value with &#39;base<br>    <br>    // stored in a single data type whose soundness is ensured<br>    // by the for&lt;&#39;base: &#39;ref&gt; annotation of the function signature<br>    (borrowed_box, heap_ref)<br>}</pre><p>And this:</p><pre>struct Encapsulated { // No lifetime here!<br>    for &#39;base: &#39;ref,<br>    heap_box: BorrowedBox&lt;u32, &#39;base&gt;,<br>    heap_ref: &amp;&#39;ref u32,<br>}</pre><p>I’m thinking of continuing sketching around this.</p><h3>Closing words</h3><p>Rust is marching towards the 2018 edition release and a huge amount of work has been done to stabilise some long-awaited features and polish the ergonomics story. Most improvements mentioned in items 1–9 are landing really soon, which is incredibly exciting.</p><p>However, when considering the future of Rust in the long term, I think the story around lifetimes and mutability isn’t done yet. Lifetimes are Rust’s flagship feature and they have shown the world that memory management without garbage collector is possible in a sound and a practical way.</p><p>In the future I’d like Rust to go all the way and prove to the world that not only memory management with lifetimes is <em>possible</em>, it can be also <em>ergonomic</em> and <em>expressive</em>. The items 10–14 are things that I consider problems that continue hindering users of lifetimes even well after the 2018 edition has shipped. They are also problems that I think are worth solving especially because lifetimes are such a central feature of Rust and Rust has spearheaded their use in real-life code. It frustrates me to think that the problems we still have with granularity, leaking abstractions, unpolished ergonomics and lacking expressiveness might lead some people to think that lifetimes are not worth the hassle. I want the world to see the ultimate form of lifetime-based memory management!</p><p>P.S. If you think that I’ve missed some obvious problem with the current lifetime/mutability system, please let me know!</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=f596a3c740a5" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Acquisition vs. learning in the domain of phonology]]></title>
            <link>https://medium.com/@GolDDranks/acquisition-vs-learning-in-the-domain-of-phonology-2f800a648831?source=rss-c0c30d6188f1------2</link>
            <guid isPermaLink="false">https://medium.com/p/2f800a648831</guid>
            <category><![CDATA[second-language]]></category>
            <category><![CDATA[language-learning]]></category>
            <category><![CDATA[language]]></category>
            <category><![CDATA[pronunciation]]></category>
            <category><![CDATA[linguistics]]></category>
            <dc:creator><![CDATA[Pyry Kontio]]></dc:creator>
            <pubDate>Thu, 23 Mar 2017 07:12:39 GMT</pubDate>
            <atom:updated>2017-06-21T19:41:29.876Z</atom:updated>
            <content:encoded><![CDATA[<p>I’ve been writing my master’s thesis like a madman, and in the process I have read dozens of studies about <em>learning phonetic categories</em>. The more I have read, the more I have come to question some of the assumptions most of these studies rely on. They are indeed good, scientific studies, but it seems that they are probing something that doesn’t really answer the questions that, in my mind, most direly need to be answered to serve the field of second language acquisition. See Bradlow (2008) for comprehensive overview. For the people who are not initiated in linguistics, I shall briefly introduce what this is all about, and after the introduction I will present some questions that I think are under-appreciated but very relevant for advancing the state of scientific knowledge about human language acquisition — especially with regards to acquiring pronunciation. If you are familiar with basics of phonemes and parsing, feel free to skip to “Additional remarks on the nature of phonemes”.</p><h3>A short primer on phonemes</h3><p>We, humans who wield language, use a great many parts of it unconsciously— most of the time, at least — directing our attention only on meaning we intend to communicate to our fellow language users. This is why it escapes the most of us — expect for some experts — how language actually works in detail. There’s much to be uncovered, but some basic facts are known and have been know for a long time. One such fact is that we parse the language we hear in more than one phase; when an utterance, a waveform of pressure waves in the air, reaches our ear and is processed by the auditory system, we at first process the pure sound material into something called <em>phonemes</em>.</p><p>There is an infinite amount of different sounds (spanning both frequency domain and time domain), but our brain chunks and classifies the continuous input of sound to something more tangible, into a finite amount of categories. I’m speaking about something like /p/ in the wort “part”, or /t/ in the word “tart”, or the rising tone in the word “麻” (/má/)or the “dipping” tone in the word “馬” (/mǎ/). There is a million ways to say “part” or “tart” (for sure, not once in the history of mankind have these words been pronounced <em>exactly</em> the same way, if that’s even a meaningful thing to say), but they are still only two words, depending on the consonant — the phoneme — that starts the word. To be sure, phonemes are not <em>letters</em> or anything <em>graphical</em> or anything <em>related to writing</em>, but abstract categories that form the low-level basic units of a language. (Especially spoken language.)</p><p>Phonemes are language-specific. The phonemes of English are different from the phonemes of Finnish and those are different from the phonemes of Japanese. Sure, there are sounds that would be categorised as a good example of /e/ of Finnish <em>and </em>/e/ of Japanese, but as categories, that is, some kind of delimited spaces of possible sounds, their borders are more or less different and their <em>exemplars — </em>the most /e/-like /e/ you could think of — are more or less different from each other. Heck, forget about borders and exemplars, they are just special cases anyway; the <em>distribution</em> of sounds is different.</p><p>Here’s a chart of Japanese vowels, if it helps to think about the situation. Each vowel gets its “sound” or <em>quality</em>, from the resonances of a specific posture the speaker’s mouth makes when pronouncing the vowel. These postures and resonances are similar enough between speakers that we can generalise our ability to recognise vowels even if we hear the voice of that particular speaker for the first time.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*aXJZIPyY0M6t5YqxM8WCDA.png" /><figcaption>The five Japanese vowels forming categories/clusters when presented as a scatterplot of the first two acoustic resonances (so called “formants”). (Mokhtari &amp; Tanaka 2000: A Corpus of Japanese Vowel Formant Patterns)</figcaption></figure><p>Now, Japanese uses clusters or categories like presented above for its vowels. But other languages might use entirely different categories. You can imagine that the categories between languages might overlap more or less, but that doesn’t make them the same categories.</p><p>That raises the question: when we learn another languages, how do we learn novel phonemes with their associated sound distributions? That is an empirical question, and it is studied in the field of second language acquisition research, SLA for short.</p><h3>Parsing beyond phonemes</h3><p>After parsing the limitless sea of possible sounds into a limited and categorical assortment of phonemes, we then further parse those into words. Or morphemes, linguistically speaking. To be able to do that, we have to possess some kind of a <em>mental lexicon</em>; a database in the brain that maps strings of phonemes (there may possibly be some intermediate representations that chunk phonemes together to help them form more organised patterns: moras, syllables, metrical foots etc., but you don’t need to care about those if phonology doesn’t rock your boat) into <em>formal features</em> and <em>meanings </em>(these may be associations to all kinds of sensations, feelings, memories or more abstract concepts like “going somewhere” or “having empathy towards others” or “doing something over the night without any sleep”). The formal features are like tags that are further used to understand how the morphemes relate to each other when parsing goes on. The morphemes are only basic units of meaning, and further parsing is still needed to form a bigger picture of how those units combine and interract to communicate some meaning that wouldn’t have been expressable using the basic units only.</p><p>It should be obvious that when we use language to understand meanings that are communicated to us using the language, we must parse the sounds we hear into phonemes and then parse those to morphemes and then go on parsing the bigger picture (morphology→syntax→discourse). If we want to get the meaning, we can’t skip stuff or stop after phoneme level — at least the two first processing steps — from sound to phonemes and from phonemes to morphemes — are needed to get even to the most basic form of meaning.</p><h3>Additional remarks on the nature of phonemes</h3><p>Now, I hear the voices of some sceptics. Are phonemes even real? Why do we need this kind of an “intermediate representation”? What if the words are stored directly as audio patterns in the brain? If the chart above with clear visible clusters doesn’t convince you, I have some good news: there’s been quite an amount of discussion and research about this and the evidence is in: yes, phonemes are psychologically real. Here’s some links to get you started: <a href="http://linguistics.stackexchange.com/questions/212/is-the-very-concept-of-the-phoneme-disputed">[StackExchange] Is the very concept of the phoneme disputed?</a>, a classic text by one of the founding fathers of linguistics: <a href="https://books.google.co.jp/books?id=1mqkkpbsgHYC&amp;pg=PA46&amp;lpg=PA46&amp;dq=psychological+reality+phoneme&amp;source=bl&amp;ots=chfe44axfm&amp;sig=X9dLUopdqwOcakAcO27KoivSk-c&amp;hl=en&amp;sa=X&amp;redir_esc=y#v=onepage&amp;q=psychological%20reality%20phoneme&amp;f=false">[Google Books] Sapir: The Psychological Reality of Phonemes</a>, and last but not least, actual empirical evidence: <a href="http://onlinelibrary.wiley.com/doi/10.1207/s15516709cog0000_79/full">McQueen et al. (2006) Phonological Abstraction in the Mental Lexicon</a>.</p><p>There’s one more thing you should know about phonemes to understand some of the empirical questions I’m going to present later: phonemes are categorical. Not only they are clustered into blocks like on the vowel chart above, but there’s something called “categorical perception”. Speakers of Japanese, for example, are lousy at distinguishing two vowels whose formant F1 differs by 50 Hz, if both of the vowels are good examples of /a/. They just don’t hear the difference. But you bet they’ll hear the difference even if F1 differs only by 30 Hz, if another vowel happens to reside in the distribution of /i/ and the other in the distribution of /e/. (Check the chart; /i/ and /e/ are actually quite close!) In other words, people are insensitive of sounds within the phoneme categories, but very sensitive <em>at</em> or <em>over</em> the borders of phoneme categories. Since the borders of the categories are different in every language and this sensitivity has been empirically shown to exist in the speakers of different languages, it’s clear that the sensitivity at specific zones is an acquired or learned phenomenon. How that learning happens? That — again—is an empirical question.</p><h3>Studies on phoneme learning</h3><p>As interested I am in second language acquisition — that is, how we acquire languages after our mother tongue — I must admit that there’s still quite lot of mysteries to solve about the learning process of phonemes and categorical perception. It’s a well-known fact that even though individuals learning a second language can become quite good at it, provided that there is enough time, enough input and interaction in that language and enough motivation, they tend to retain audible “foreign” accents. (Note that there is a huge amount of individual variability and a lots of factors affecting this. Nothing is simple in SLA.) It seems that acquiring novel phoneme categories is very hard for adult learners, and even if the linguistic system of the learner has reached highly advanced levels, pronunciation often lags behind or is at standstill (Tsukada &amp; Birdsong 2005).</p><p>There is empirical evidence that pronunciation of second language hinges on the perception of the phonetic categories; unless you are able to perceive and distinguish the phonetic categories more or less like a native speaker would, you will have little hope of pronouncing sounds in those categories right, except by chance. (To be sure, I’m talking about pronouncing while paying attention only to meaning in a communicative setting. That means letting the automatised processes in the internal linguistic system to manage the details of the linguistic processing such as forming sounds. I think many people are able to learn quickly to “imitate” native-like accents for short words and phrases when they have a model to listen to and specifically pay attention to that, but that’s different from acquiring a language.)</p><p>In hindsight this seems obvious and it is analogious to the whole process how language acquisition works in general: if you don’t have sufficient exposure to input data, your internal model of the language won’t have had developed (we are talking, again, about unconscious processes here) enough to be accurate and complete. Based on inaccurate or underdeveloped internal model, it’s no wonder that the production of sound is inaccurate too. Succintly said: output depends on input.</p><p>Not surprisingly, there has been multiple attempts to teach people to perceive the phonemic categories of the target language and to try and overcome the seemingly difficult task of re-adjusting the phonetic system. After Logan and Lively (1991), there has been a flurry of studies on a training paradigm called high variability training. These studies have successfully demonstrated perception of novel perceptual categories. They have also demonstrated that this learned categorical knowledge can transfer from perception to pronunciation. So… huzzah, our foreign accent problem is solved! Just have the learners do these high variability shenanigans, and the funny accents of Arnold Schwarzenegger and Slavoj Žižek (not to even mention Finnish rally drivers) are a thing of the past.</p><p>Alas, things are never so simple. After reading a study after study, it has become painfully clear to me, that while the results they sport may be indeed true, their application is limited in the process of actual language acquisition. (Oh, and by the way, getting rid of the funny accents was a joke. We are talking about acquiring phoneme contrasts here, which should help with speech intelligibility, but doesn’t guarantee native-likeness, since one can still realise the sounds inside a category in a way that is quite far from the exemplar.)</p><h3>What the studies are neglecting</h3><p>Here’s a bunch of question that I think we <em>should</em> be asking, but that I seldom see the studies to ask. To understand some of the critique you should be aware that in the field of SLA, some scholars distinguish between <em>learning</em> and <em>language</em> <em>acquisition</em>. It has been empirically shown, that while people can quickly be taught to retain facts such as item-label pairs (=”learning words”), apply rules to modify symbolic structures (=”learning grammar”) and so on, this learned skill doesn’t seem to readily transfer to actual use when using language to communicate. Indeed, it appears to be that the implicit linguistic system in the brain is very resistant to external manipulation, and develops slowly in response to <em>using language to understand/parse meaning.</em> But when it develops, it seems to have this automatic quality that you don’t have to think about nouns and verbs, you don’t have to think about conjugation rules — the implicit system has got your back. (Or doesn’t, if it hasn’t acquired enough language yet.) Most of the studies that recognise the distinction, however, are done in the fields of morphology and syntax. I don’t remember seeing much of thought to be given to this difference in the pronunciation training studies. (Some recent evidence supporting that speech learning is optimally learned by implicit neural systems exists, however: Chandrasekaran et al. 2014)</p><p>So, here goes my list of questions we should be asking:</p><h4>Is “perceptual category” different from “phonemic category?”</h4><p>What I mean by these terms:</p><p><strong>perceptual category</strong> — people are able to identify an aural stimulus as a member of some category. These categories are shown to be formed with short-term high-variability training, and they allow even naive (=zero experience of L2) trainees to identify L2 sound categories when instructed to do so.</p><p><strong>phonemic category — </strong>a perceptual category that is part of the linguistic system and can be readily and automatically used as a part of the linguistic system to communicate meaning.</p><p>Being a “phonemic category” requires the category to exist and be retained not only in the aural speech processing subsystem but also in mental lexicon. For example: Chinese tones form a phonemic category for Chinese speakers (both L1 and sufficiently advanced L2); they are used to distinguish between meanings of words which may be otherwise similar. That means that Chinese speakers are not only able to distinguish aural stimuli based on these categories, but they are <em>also</em> able to retain words that are distinguished by these categories in their mental lexicon, and they are able to use these words to communicate meaning without much of a thought. But I’ve seldom seen a study on high variability training to ask, whether the perceptual categories are represented in mental lexicon. They always seem to concentrate on just “hearing” the difference. Only two studies that I know of, make a difference by focusing also on the lexical aspect: Wong &amp; Perrachione (2007) and Chandrasekaran (2010), but even they focus only on learning pseudowords, which is hardly representative of experience of actual language acquisition.</p><h4>Does peaking in discrimination sensitivity at the category border imply the category being “phonemic” and thus part of the linguistic system?</h4><p>In other words: language acquisition is known to “warp” the perceptual space, but does the warping of perceptual space always mean that a phonemic category is formed? (Is the relationship → or ↔?)</p><p>As said above, native speakers, for sure, have heightened sensitivity of the perceptual space at category border. There is evidence (Heeren 2008) that although phonetic (not meaning-based) short-term high variability training helps to form categories of sound identification, the trainees fail to develop sensitivity peaks at category borders — however, advanced second language learners (three years of majoring in the second language in college) <em>do</em> develop sensitivity peaks at category borders. This begs the question: is a heightened sensitivity at the category border a sign of an <em>acquired phonemic category</em>? (Rather than <em>learned perceptual category</em>?) Short-time explicit learning certainly helps to form perceptual categories, but is the development of <em>phonemic</em> categories due to (implicit) language acquisition?</p><p>However, there’s another possibility to keep in mind: it might be just so that the trainees need longer periods of (non-meaningful or not) training to develop sensitivity at phonemic borders. Maybe the development of sensitivity doesn’t have anything to do with language acquisition in general?</p><h4>Does the learning of “perceptual categories” help people to succeed in communicative tasks?</h4><p>If they do, that means that category learning in phonetic domain might have actual value in communicative language teaching. Maybe percieving phoneme categories better can have a facilitative effect to advance acquistion in other domains? Wong and Perrachione (2007) claim so, but their data is based only in a short-term training of an artificial language.</p><p>There is also evidence that forming of perceptual categories transfers from non-communicative input to output. By non-communicative I mean perceiving category differences and producing them in non-communicative situations, such as reading aloud a list of words. It’s relevant to ask, then: does the transfer occur also in communicative situations, when attention is directed to communicating meaning; in other words, in “spontaneous speech”? Using a category in spontaneous speech is usually considered a telltale sign of language acquisition.</p><h4>Do explicitly learned perceptual categories transfer to phonemic categories? Or do phonemic categories develop independently?</h4><p>This question resembles the question about the “<a href="https://en.wikipedia.org/wiki/Interface_position">interface position</a>” in SLA.</p><h4>Can meaning-based structured input activities (as pioneered by VanPatten &amp; Cadierno 1993) help forming “phonemic” categories?</h4><p>Most (if not all) of the research on <em>processing instruction</em> (=a treatment based on meaning-based structured input activities) has happened in the domain of morphosyntax. It is originally based on VanPatten’s model of input processing, which is in the domain of syntax, and considers only linguistic universals (instead of cross-linguistic influence). Applying similar ideas to a totally different domain such as phonology may seem odd, but the idea behind the training paradigm remain sound: focus on processing from form to meaning to overcome processing problems on the way. (Not only phonology is a different domain, but for example, L1 transfer/inference is much more apparent in phonology and phonetics than in morphology and syntax — the inference manifests as the “foreign accent”.)</p><p>It has been shown that perceptual categories can be formed with phonetic (not meaning-based) training, but none of the studies have shown that such training could help the trainees to form phonemic categories. However, it seems plausible to me that meaning-based structured input activities <em>could</em> help forming actual phonemic categories. Of course, this needs to be empirically tested, but if that’s true, it would give some tools to teaching pronunciation efficiently.</p><p>As stated above, there is evidence that language acquisition over long periods may lead to formation of phonemic categories (defined at least by usage in spontaneous speech and possibly also by the sensitivity peak at category border). There is <em>also</em> evidence that adult learners of SLA often <em>fail</em> to form these categories (Tsukada &amp; Birdsong 2005). However, when trainees are forced to parse from form to meaning, as they are in structured input activities, it seems that the category and the processing needed would need to develop not only in phonetic domain but also in the mental lexicon and other relevant linguistic domains.</p><p>There are two studies that have attempted this: Gonzales-Bueno &amp; Quintana-Lara (2011) (unfortunately with little conclusive evidence), and Hirano-Cook (2011) who reports having used processing instruction to train students to perceive Japanese pitch accents, but she seems to have misunderstood the idea of processing instruction slightly based on the description of the activities. She also tests only for pitch pattern identification, which doesn’t tell anything about language acquisition. So the field is still open for a study that probes the effects of meaning-based structured input activities for acquisition of novel phoneme contrasts.</p><p>As a summary, I think that exercising the whole chain of processing from form to meaning in a communicative setting might actually lead to acquisition. Exercising just the first part of the chain (parsing from sound to phonemes) perhaps not.</p><p>Also note that there is tangentual counter-evidence against the benefits of meaning-based activities: Guion &amp; Pederson (2007) claim that paying attention to phonetic difference (instead of meaning) is more benefical for forming categories. However, they test only for perceptual categories, not for phonemic. If perceptual categories can develop into phonemic categories, paying attention to phonetic difference can pay off when starting the training. But if they can’t (no-interface position), it’s just waste of time, since phonemic categories develop independently.</p><h3>Summary: towards better questions</h3><p>All in all, I think that while much has been researched about learning pronunciation, much remains to be uncovered by future research. Already by adopting experimental design the field has moved forward. (For example: it seems that there has been quite a lot of studies on acquisition of Japanese lexical accent since the 90’s but only in the year 2011 the first study that used a control group and statistical tests emerged (Hirano-Cook 2011).)</p><p>Also, some variables have been identified that are controlled for quite universally nowadays. The main one is former exposure to languages with relevant categories. Another one is age, which contrary to expectations, hasn’t shown up as a factor in perceptual category learning. (Contrasting Tsukada &amp; Birdsong 2005 and Heeren 2010, it might be that pronunciation acquisition might be subject to a ”sensitive period” or neurological maturing, whereas perceptual category learning isn’t. This demands for investigation!) Curiously, for studies researching tonal patterns, musical training has been shown to improve performance. Also testing for unfamiliar stimuli that aren’t part of the training regime (novel phonological context, unfamiliar voices, possibly even unfamiliar but related phonological phenomena) is — and should be — commonplace today to check whether the learning generalises.</p><p>It would be immensely helpful if the studies in the future controlled for these variables:</p><ul><li>Are the trainees able to use the learned category communicatively? (For example, to understand correctly the meaning of an ambiguous sentence disambiguated only the category that’s being trained?) A gold standard for this would be demonstrating the usage of the category in spontaneous, meaning-oriented speech.</li><li>Are the learning effects shown only in identification tests or also in discrimination tests with modified stimulus? (Discrimination tests with carefully crafted stimulus tend to reveal the sensitivity peaks at category borders.)</li><li>It should be always made clear if the study is aimed to test for development of perceptual categories and not conflating that to something else, such as “language learning” or “language acquisition” without considering if the experimental design used is adequate to catch whether language acquisition is taking place.</li></ul><p>Some day, I wish to see that we’d have some solid scientific evidence of how acquiring second language pronunciation happens, and also better understanding of how to facilitate the development of pronunciation when teaching. I suspect that there might exist some training paradigms that actually improve one’s perception, accent and speech intelligibility, but I can’t help thinking that most of the training studies are missing the language part of the equation, focusing only in acoustics.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=2f800a648831" width="1" height="1" alt="">]]></content:encoded>
        </item>
    </channel>
</rss>