diff --git a/docs/source/history.rst b/docs/source/history.rst
index 7aca27ec..b2e04676 100644
--- a/docs/source/history.rst
+++ b/docs/source/history.rst
@@ -5,6 +5,56 @@ Release history
 
 .. towncrier release notes start
 
+trio-asyncio 0.12.0 (2021-01-07)
+--------------------------------
+
+Bugfixes
+~~~~~~~~
+
+- trio-asyncio now cancels any Trio tasks that were started inside a trio-asyncio
+  loop (using e.g. :func:`trio_as_aio`) before it allows the trio-asyncio loop
+  to close. This should resolve some cases of deadlocks and "RuntimeError: Event loop
+  is closed" when an ``async with open_loop():`` block is cancelled. (`#89 <https://github.com/python-trio/trio-asyncio/issues/89>`__)
+- :func:`asyncio.get_running_loop` will now return the trio-asyncio event loop
+  (if running), instead of failing with :exc:`RuntimeError`. (`#99 <https://github.com/python-trio/trio-asyncio/issues/99>`__)
+- On Python versions with native contextvars support (3.7+), a Trio task
+  started from asyncio context (using :func:`trio_as_aio`,
+  :meth:`~BaseTrioEventLoop.trio_as_future`, etc) will now properly
+  inherit the contextvars of its caller.  Also, if the entire
+  trio-asyncio loop is cancelled, such tasks will no longer let
+  `trio.Cancelled` exceptions leak into their asyncio caller. (`#76 <https://github.com/python-trio/trio-asyncio/issues/76>`__)
+- Previously, cancelling the context surrounding an :func:`open_loop`
+  block might cause a deadlock in some cases. The ordering of operations
+  during loop teardown has been improved, so this shouldn't happen
+  anymore. (`#81 <https://github.com/python-trio/trio-asyncio/issues/81>`__)
+
+Deprecations and Removals
+~~~~~~~~~~~~~~~~~~~~~~~~~
+
+A number of functions deprecated since 0.10.0 are now removed:
+
+================================================= =============================================
+  Removed                                           Replacement
+================================================= =============================================
+``wrap_generator(proc, *args)``                   :func:`aio_as_trio(proc(*args))<aio_as_trio>`
+``run_iterator(aiter)``                           :func:`aio_as_trio(aiter)<aio_as_trio>`
+``trio2aio``                                      :func:`aio_as_trio`
+``aio2trio``                                      :func:`trio_as_aio`
+``run_future`` ``TrioEventLoop.run_future``       :func:`run_aio_future`
+``run_coroutine`` ``TrioEventLoop.run_coroutine`` :func:`run_aio_coroutine`
+``wrap_trio_context(ctx)``                        :func:`trio_as_aio(ctx)<trio_as_aio>`
+``TrioEventLoop.run_trio(proc, *args)``           :func:`trio_as_aio(proc)(*args)<trio_as_aio>`
+``run_asyncio(proc, *args)``                      :func:`aio_as_trio(proc)(*args)<aio_as_trio>`
+================================================= =============================================
+
+Miscellaneous
+~~~~~~~~~~~~~
+
+- ``trio-asyncio`` now requires Trio 0.15. Support for Python < 3.6 has been removed. (`#82 <https://github.com/python-trio/trio-asyncio/issues/82>`__)
+
+- No more ``TrioDeprecationWarning`` about ``trio.hazmat``. (`#82 <https://github.com/python-trio/trio-asyncio/issues/82>`__)
+
+
 trio-asyncio 0.11.0 (2020-03-09)
 --------------------------------
 
diff --git a/newsfragments/76.bugfix.rst b/newsfragments/76.bugfix.rst
deleted file mode 100644
index 7494fdc4..00000000
--- a/newsfragments/76.bugfix.rst
+++ /dev/null
@@ -1,6 +0,0 @@
-On Python versions with native contextvars support (3.7+), a Trio task
-started from asyncio context (using :func:`trio_as_aio`,
-:meth:`~BaseTrioEventLoop.trio_as_future`, etc) will now properly
-inherit the contextvars of its caller.  Also, if the entire
-trio-asyncio loop is cancelled, such tasks will no longer let
-`trio.Cancelled` exceptions leak into their asyncio caller.
diff --git a/newsfragments/80.bugfix.rst b/newsfragments/80.bugfix.rst
deleted file mode 100644
index d51c7d34..00000000
--- a/newsfragments/80.bugfix.rst
+++ /dev/null
@@ -1,4 +0,0 @@
-Previously, cancelling the context surrounding an :func:`open_loop`
-block might cause a deadlock in some cases. The ordering of operations
-during loop teardown has been improved, so this shouldn't happen
-anymore.
diff --git a/newsfragments/82.misc.rst b/newsfragments/82.misc.rst
deleted file mode 100644
index bc9a04dc..00000000
--- a/newsfragments/82.misc.rst
+++ /dev/null
@@ -1,3 +0,0 @@
-``trio-asyncio`` now requires Trio 0.15.
-
-Support for Python < 3.6 has been removed.
diff --git a/newsfragments/89.bugfix.rst b/newsfragments/89.bugfix.rst
deleted file mode 100644
index 29932b7b..00000000
--- a/newsfragments/89.bugfix.rst
+++ /dev/null
@@ -1,4 +0,0 @@
-trio-asyncio now cancels any Trio tasks that were started inside a trio-asyncio
-loop (using e.g. :func:`trio_as_aio`) before it allows the trio-asyncio loop
-to close. This should resolve some cases of deadlocks and "RuntimeError: Event loop
-is closed" when an ``async with open_loop():`` block is cancelled.
diff --git a/newsfragments/99.bugfix.rst b/newsfragments/99.bugfix.rst
deleted file mode 100644
index 4a2267c2..00000000
--- a/newsfragments/99.bugfix.rst
+++ /dev/null
@@ -1,2 +0,0 @@
-:func:`asyncio.get_running_loop()` will now return the trio-asyncio event loop
-(if running), instead of failing with :exc:`RuntimeError`.
diff --git a/pyproject.toml b/pyproject.toml
index b7f95256..37bbc996 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -1,6 +1,32 @@
 [tool.towncrier]
 package = "trio_asyncio"
+title_format = "trio-asyncio {version} ({project_date})"
 filename = "docs/source/history.rst"
 directory = "newsfragments"
 underlines = ["-", "~", "^"]
 issue_format = "`#{issue} <https://github.com/python-trio/trio-asyncio/issues/{issue}>`__"
+
+[[tool.towncrier.type]]
+directory = "feature"
+name = "Features"
+showcontent = true
+
+[[tool.towncrier.type]]
+directory = "bugfix"
+name = "Bugfixes"
+showcontent = true
+
+[[tool.towncrier.type]]
+directory = "doc"
+name = "Improved documentation"
+showcontent = true
+
+[[tool.towncrier.type]]
+directory = "removal"
+name = "Deprecations and removals"
+showcontent = true
+
+[[tool.towncrier.type]]
+directory = "misc"
+name = "Miscellaneous"
+showcontent = true
diff --git a/tests/aiotest/test_callback.py b/tests/aiotest/test_callback.py
index d9419fa6..b70f4209 100644
--- a/tests/aiotest/test_callback.py
+++ b/tests/aiotest/test_callback.py
@@ -1,7 +1,6 @@
 from tests import aiotest
 import signal
 import pytest
-from .. import utils as test_utils
 
 
 class TestCallback(aiotest.TestCase):
@@ -51,10 +50,6 @@ async def test():
         func = lambda: False
         coro = test()
         try:
-            # no longer depends on the loop
-            # with pytest.raises(RuntimeError):
-            #    fut = config.asyncio.Future(loop=loop)
-            #    await loop.run_future(fut)
             with pytest.raises(RuntimeError, match='not a sync loop'):
                 loop.run_until_complete(None)
             with pytest.raises(RuntimeError):
@@ -71,9 +66,6 @@ async def test():
                 loop.run_in_executor(None, func)
             with pytest.raises(RuntimeError, match='Event loop is closed'):
                 await loop.run_aio_coroutine(coro)
-            with test_utils.deprecate(self):
-                with pytest.raises(RuntimeError, match='Event loop is closed'):
-                    await loop.run_coroutine(coro)
             with pytest.raises(RuntimeError, match='Event loop is closed'):
                 loop.add_signal_handler(signal.SIGTERM, func)
         finally:
diff --git a/tests/aiotest/test_coroutine.py b/tests/aiotest/test_coroutine.py
index 0ab30549..dd73fb99 100644
--- a/tests/aiotest/test_coroutine.py
+++ b/tests/aiotest/test_coroutine.py
@@ -1,13 +1,12 @@
 from tests import aiotest
 import trio_asyncio
 import pytest
-from .. import utils as test_utils
 
 
 async def hello_world(asyncio, result, delay, loop):
     result.append("Hello")
     # retrieve the event loop from the policy
-    await asyncio.sleep(delay, loop=loop)
+    await asyncio.sleep(delay)
     result.append('World')
     return "."
 
@@ -17,27 +16,13 @@ class TestCoroutine(aiotest.TestCase):
     async def test_hello_world(self, loop, config):
         result = []
         coro = hello_world(config.asyncio, result, 0.001, loop)
-        await loop.run_aio_coroutine(config.asyncio.ensure_future(coro, loop=loop))
-        assert result == ['Hello', 'World']
-
-    @pytest.mark.trio
-    async def test_hello_world_depr(self, loop, config):
-        result = []
-        coro = hello_world(config.asyncio, result, 0.001, loop)
-        with test_utils.deprecate(self):
-            await loop.run_coroutine(config.asyncio.ensure_future(coro, loop=loop))
-        assert result == ['Hello', 'World']
-
-    @pytest.mark.trio
-    async def run_hello_world(self, loop, config):
-        result = []
-        await loop.run_asyncio(hello_world, config.asyncio, result, 0.001, loop)
+        await loop.run_aio_coroutine(config.asyncio.ensure_future(coro))
         assert result == ['Hello', 'World']
 
     @pytest.mark.trio
     async def test_waiter(self, loop, config):
         async def waiter(asyncio, hello_world, result):
-            fut = asyncio.Future(loop=loop)
+            fut = asyncio.Future()
             loop.call_soon(fut.set_result, "Future")
 
             value = await fut
@@ -49,20 +34,3 @@ async def waiter(asyncio, hello_world, result):
         result = []
         await trio_asyncio.aio_as_trio(waiter)(config.asyncio, hello_world, result)
         assert result == ['Future', 'Hello', 'World', '.']
-
-    @pytest.mark.trio
-    async def test_waiter_depr(self, loop, config):
-        async def waiter(asyncio, hello_world, result):
-            fut = asyncio.Future(loop=loop)
-            loop.call_soon(fut.set_result, "Future")
-
-            value = await fut
-            result.append(value)
-
-            value = await hello_world(asyncio, result, 0.001, loop)
-            result.append(value)
-
-        result = []
-        with test_utils.deprecate(self):
-            await loop.run_asyncio(waiter, config.asyncio, hello_world, result)
-        assert result == ['Future', 'Hello', 'World', '.']
diff --git a/tests/aiotest/test_network.py b/tests/aiotest/test_network.py
index cfb87f1b..c9cfd052 100644
--- a/tests/aiotest/test_network.py
+++ b/tests/aiotest/test_network.py
@@ -79,7 +79,7 @@ async def test_tcp_hello(self, loop, config):
 
         proto = TcpEchoClientProtocol(message, loop)
         coro = loop.create_connection(lambda: proto, host, port)
-        await loop.run_coroutine(coro)
+        await loop.run_aio_coroutine(coro)
         assert proto.state != 'new'
 
         await loop.stop().wait()()
diff --git a/tests/aiotest/test_thread.py b/tests/aiotest/test_thread.py
index 7baf1e70..ef914284 100644
--- a/tests/aiotest/test_thread.py
+++ b/tests/aiotest/test_thread.py
@@ -2,7 +2,6 @@
 import pytest
 import trio
 import trio_asyncio
-from .. import utils as test_utils
 
 
 class TestThread(aiotest.TestCase):
@@ -27,28 +26,6 @@ def work():
         assert work_ident is not None
         assert work_ident != get_ident()
 
-    @pytest.mark.trio
-    async def test_ident_depr(self, loop, config):
-        threading = config.threading
-        try:
-            get_ident = threading.get_ident  # Python 3
-        except AttributeError:
-            get_ident = threading._get_ident  # Python 2
-
-        result = {'ident': None}
-
-        def work():
-            result['ident'] = get_ident()
-
-        fut = loop.run_in_executor(None, work)
-        with test_utils.deprecate(self):
-            await loop.run_coroutine(fut)
-
-        # ensure that work() was executed in a different thread
-        work_ident = result['ident']
-        assert work_ident is not None
-        assert work_ident != get_ident()
-
     @pytest.mark.trio
     async def test_run_twice(self, loop):
         result = []
@@ -65,24 +42,6 @@ def work():
         await loop.run_aio_future(fut)
         assert result == ["run", "run"]
 
-    @pytest.mark.trio
-    async def test_run_twice_depr(self, loop):
-        result = []
-
-        def work():
-            result.append("run")
-
-        fut = loop.run_in_executor(None, work)
-        with test_utils.deprecate(self):
-            await loop.run_future(fut)
-        assert result == ["run"]
-
-        # ensure that run_in_executor() can be called twice
-        fut = loop.run_in_executor(None, work)
-        with test_utils.deprecate(self):
-            await loop.run_future(fut)
-        assert result == ["run", "run"]
-
     @pytest.mark.trio
     async def test_policy(self, loop, config):
         asyncio = config.asyncio
@@ -99,23 +58,6 @@ def work():
         await loop.run_aio_future(fut)
         assert isinstance(result['loop'], (AssertionError, RuntimeError))
 
-    @pytest.mark.trio
-    async def test_policy_depr(self, loop, config):
-        asyncio = config.asyncio
-        result = {'loop': 'not set'}  # sentinel, different than None
-
-        def work():
-            try:
-                result['loop'] = asyncio.get_event_loop()
-            except Exception as exc:
-                result['loop'] = exc
-
-        # get_event_loop() must return None in a different thread
-        fut = loop.run_in_executor(None, work)
-        with test_utils.deprecate(self):
-            await loop.run_future(fut)
-        assert isinstance(result['loop'], (AssertionError, RuntimeError))
-
     @pytest.mark.trio
     async def test_run_in_thread(self, config):
         threading = config.threading
diff --git a/tests/interop/test_adapter.py b/tests/interop/test_adapter.py
index 0c8bf48b..ff10cb5f 100644
--- a/tests/interop/test_adapter.py
+++ b/tests/interop/test_adapter.py
@@ -1,6 +1,5 @@
 import pytest
 from trio_asyncio import aio_as_trio, trio_as_aio, allow_asyncio
-from trio_asyncio import aio2trio, trio2aio
 import asyncio
 import trio
 import sniffio
@@ -11,7 +10,6 @@
     from contextlib import asynccontextmanager
 except ImportError:
     from async_generator import asynccontextmanager
-from .. import utils as test_utils
 from trio_asyncio import TrioAsyncioDeprecationWarning
 
 
@@ -45,45 +43,29 @@ async def dly_trio_adapted(self):
         self.flag |= 2
         return 8
 
-    @de_deprecate_converter(aio2trio)
-    async def dly_trio_depr(self):
-        if sys.version_info >= (3, 7):
-            assert sniffio.current_async_library() == "trio"
-        await trio.sleep(0.01)
-        self.flag |= 2
-        return 8
-
-    @de_deprecate_converter(trio2aio)
-    async def dly_asyncio_depr(self):
-        if sys.version_info >= (3, 7):
-            assert sniffio.current_async_library() == "asyncio"
-        await asyncio.sleep(0.01, loop=self.loop)
-        self.flag |= 1
-        return 4
-
     @aio_as_trio
     async def dly_asyncio_adapted(self):
         if sys.version_info >= (3, 7):
             assert sniffio.current_async_library() == "asyncio"
-        await asyncio.sleep(0.01, loop=self.loop)
+        await asyncio.sleep(0.01)
         self.flag |= 1
         return 4
 
     async def dly_asyncio(self, do_test=True):
         if do_test and sys.version_info >= (3, 7):
             assert sniffio.current_async_library() == "asyncio"
-        await asyncio.sleep(0.01, loop=self.loop)
+        await asyncio.sleep(0.01)
         self.flag |= 1
         return 4
 
     async def iter_asyncio(self, do_test=True):
         if do_test and sys.version_info >= (3, 7):
             assert sniffio.current_async_library() == "asyncio"
-        await asyncio.sleep(0.01, loop=self.loop)
+        await asyncio.sleep(0.01)
         yield 1
-        await asyncio.sleep(0.01, loop=self.loop)
+        await asyncio.sleep(0.01)
         yield 2
-        await asyncio.sleep(0.01, loop=self.loop)
+        await asyncio.sleep(0.01)
         self.flag |= 1
 
     async def iter_trio(self):
@@ -98,10 +80,10 @@ async def iter_trio(self):
 
     @asynccontextmanager
     async def ctx_asyncio(self):
-        await asyncio.sleep(0.01, loop=self.loop)
+        await asyncio.sleep(0.01)
         self.flag |= 1
         yield self
-        await asyncio.sleep(0.01, loop=self.loop)
+        await asyncio.sleep(0.01)
         self.flag |= 2
 
     @asynccontextmanager
@@ -114,15 +96,6 @@ async def ctx_trio(self):
 
 
 class TestAdapt(aiotest.TestCase):
-    @pytest.mark.trio
-    async def test_asyncio_trio_depr(self, loop):
-        """Call asyncio from trio"""
-
-        sth = SomeThing(loop)
-        res = await aio_as_trio(sth.dly_trio_depr, loop=loop)()
-        assert res == 8
-        assert sth.flag == 2
-
     @pytest.mark.trio
     async def test_asyncio_trio_adapted(self, loop):
         """Call asyncio from trio"""
@@ -133,12 +106,11 @@ async def test_asyncio_trio_adapted(self, loop):
         assert sth.flag == 2
 
     @pytest.mark.trio
-    async def test_asyncio_trio_depr2(self, loop):
+    async def test_asyncio_trio_adapted_no_call(self, loop):
         """Call asyncio from trio"""
 
         sth = SomeThing(loop)
-        with test_utils.deprecate(self):
-            res = await loop.run_asyncio(sth.dly_trio_adapted)
+        res = await aio_as_trio(sth.dly_trio_adapted)
         assert res == 8
         assert sth.flag == 2
 
@@ -172,13 +144,6 @@ async def test_trio_asyncio_future(self, loop):
         assert res == 4
         assert sth.flag == 1
 
-    @pytest.mark.trio
-    async def test_trio_asyncio_depr(self, loop):
-        sth = SomeThing(loop)
-        res = await sth.dly_asyncio_depr()
-        assert res == 4
-        assert sth.flag == 1
-
     @pytest.mark.trio
     async def test_trio_asyncio_iter(self, loop):
         sth = SomeThing(loop)
@@ -232,20 +197,6 @@ async def run_asyncio_trio(self, loop):
         assert res == 8
         assert sth.flag == 2
 
-    async def run_asyncio_trio_adapted(self, loop):
-        """Call asyncio from trio"""
-        sth = SomeThing(loop)
-        res = await sth.dly_trio_adapted()
-        assert res == 8
-        assert sth.flag == 2
-
-    async def run_asyncio_trio_depr(self, loop):
-        """Call asyncio from trio"""
-        sth = SomeThing(loop)
-        res = await sth.dly_trio_depr()
-        assert res == 8
-        assert sth.flag == 2
-
     @pytest.mark.trio
     async def test_asyncio_trio(self, loop):
         await allow_asyncio(self.run_asyncio_trio, loop)
@@ -272,15 +223,32 @@ async def run_trio_asyncio_future(self, loop):
     async def test_trio_asyncio_future(self, loop):
         await allow_asyncio(self.run_trio_asyncio_future, loop)
 
-    async def run_trio_asyncio_depr(self, loop):
+    def get_asyncio_future(self, loop, sth):
+        async def set_result(future, sth):
+            await asyncio.sleep(0.01)
+            sth.flag |= 1
+            future.set_result(4)
+
+        f = loop.create_future()
+        loop.create_task(set_result(f, sth))
+        return f
+
+    @pytest.mark.trio
+    async def test_trio_asyncio_future_getter(self, loop):
+        sth = SomeThing(loop)
+        res = await allow_asyncio(self.get_asyncio_future, loop, sth)
+        assert res == 4
+        assert sth.flag == 1
+
+    async def run_trio_asyncio_adapted(self, loop):
         sth = SomeThing(loop)
-        res = await sth.dly_asyncio_depr()
+        res = await sth.dly_asyncio_adapted()
         assert res == 4
         assert sth.flag == 1
 
     @pytest.mark.trio
-    async def test_trio_asyncio_depr(self, loop):
-        await allow_asyncio(self.run_trio_asyncio_depr, loop)
+    async def test_trio_asyncio_adapted(self, loop):
+        await allow_asyncio(self.run_trio_asyncio_adapted, loop)
 
     async def run_trio_asyncio_iter(self, loop):
         sth = SomeThing(loop)
diff --git a/tests/interop/test_calls.py b/tests/interop/test_calls.py
index ef8dbfac..0e40a9f8 100644
--- a/tests/interop/test_calls.py
+++ b/tests/interop/test_calls.py
@@ -2,7 +2,7 @@
 import asyncio
 import trio
 import sniffio
-from trio_asyncio import aio_as_trio, trio_as_aio
+from trio_asyncio import aio_as_trio, trio_as_aio, run_aio_generator
 from tests import aiotest
 from functools import partial
 import sys
@@ -48,7 +48,7 @@ async def __aenter__(self):
         self.parent.did_it = 1
         if sys.version_info >= (3, 7):
             assert sniffio.current_async_library() == "asyncio"
-        await asyncio.sleep(0.01, loop=self.loop)
+        await asyncio.sleep(0.01)
         self.parent.did_it = 2
         return self
 
@@ -62,20 +62,10 @@ async def call_t_a(self, proc, *args, loop=None):
         """called from Trio"""
         return await aio_as_trio(proc, loop=loop)(*args)
 
-    async def call_t_a_depr(self, proc, *args, loop=None):
-        """called from Trio"""
-        with test_utils.deprecate(self):
-            return await loop.run_asyncio(proc, *args)
-
     async def call_a_t(self, proc, *args, loop=None):
         """call from asyncio to an async trio function"""
         return await trio_as_aio(proc, loop=loop)(*args)
 
-    async def call_a_t_depr(self, proc, *args, loop=None):
-        """call from asyncio to an async trio function"""
-        with test_utils.deprecate(self):
-            return await loop.run_trio(proc, *args)
-
     async def call_a_ts(self, proc, *args, loop=None):
         """called from asyncio to a sync trio function"""
         return proc(*args)
@@ -83,24 +73,13 @@ async def call_a_ts(self, proc, *args, loop=None):
     @pytest.mark.trio
     async def test_call_at(self, loop):
         async def delay(t):
-            done = asyncio.Event(loop=loop)
+            done = asyncio.Event()
             loop.call_at(t, done.set)
             await done.wait()
 
         t = loop.time() + 0.1
         await aio_as_trio(delay, loop=loop)(t)
 
-    @pytest.mark.trio
-    async def test_call_at_depr(self, loop):
-        async def delay(t):
-            done = asyncio.Event(loop=loop)
-            loop.call_at(t, done.set)
-            await done.wait()
-
-        t = loop.time() + 0.1
-        with test_utils.deprecate(self):
-            await loop.run_asyncio(delay, t)
-
     @pytest.mark.trio
     async def test_asyncio_trio(self, loop):
         """Call asyncio from trio"""
@@ -115,20 +94,6 @@ async def dly_trio(seen):
         assert res == 8
         assert seen.flag == 2
 
-    @pytest.mark.trio
-    async def test_asyncio_trio_depr(self, loop):
-        """Call asyncio from trio"""
-
-        async def dly_trio(seen):
-            await trio.sleep(0.01)
-            seen.flag |= 2
-            return 8
-
-        seen = Seen()
-        res = await aio_as_trio(partial(self.call_a_t_depr, loop=loop), loop=loop)(dly_trio, seen)
-        assert res == 8
-        assert seen.flag == 2
-
     @pytest.mark.trio
     async def test_call_asyncio_ctx(self, loop):
         self.did_it = 0
@@ -150,19 +115,6 @@ async def _call_trio_ctx():
 
         await aio_as_trio(_call_trio_ctx, loop=loop)()
 
-    @pytest.mark.trio
-    async def test_call_trio_ctx_depr(self, loop):
-        async def _call_trio_ctx():
-            self.did_it = 0
-            async with loop.wrap_trio_context(TrioContext(self)) as ctx:
-                assert ctx.parent is self
-                assert self.did_it == 2
-                self.did_it = 3
-            assert self.did_it == 4
-
-        with test_utils.deprecate(self):
-            await loop.run_asyncio(_call_trio_ctx)
-
     @pytest.mark.trio
     async def test_asyncio_trio_sync(self, loop):
         """Call asyncio from trio"""
@@ -176,24 +128,10 @@ def dly_trio(seen):
         assert res == 8
         assert seen.flag == 2
 
-    @pytest.mark.trio
-    async def test_asyncio_trio_sync_depr(self, loop):
-        """Call asyncio from trio"""
-
-        def dly_trio(seen):
-            seen.flag |= 2
-            return 8
-
-        seen = Seen()
-        with test_utils.deprecate(self):
-            res = await loop.run_asyncio(partial(self.call_a_ts, loop=loop), dly_trio, seen)
-        assert res == 8
-        assert seen.flag == 2
-
     @pytest.mark.trio
     async def test_trio_asyncio(self, loop):
         async def dly_asyncio(seen):
-            await asyncio.sleep(0.01, loop=loop)
+            await asyncio.sleep(0.01)
             seen.flag |= 1
             return 4
 
@@ -202,18 +140,6 @@ async def dly_asyncio(seen):
         assert res == 4
         assert seen.flag == 1
 
-    @pytest.mark.trio
-    async def test_trio_asyncio_depr(self, loop):
-        async def dly_asyncio(seen):
-            await asyncio.sleep(0.01, loop=loop)
-            seen.flag |= 1
-            return 4
-
-        seen = Seen()
-        res = await self.call_t_a_depr(dly_asyncio, seen, loop=loop)
-        assert res == 4
-        assert seen.flag == 1
-
     @pytest.mark.trio
     async def test_asyncio_trio_error(self, loop):
         async def err_trio():
@@ -224,38 +150,6 @@ async def err_trio():
             await aio_as_trio(partial(self.call_a_t, loop=loop), loop=loop)(err_trio)
         assert err.value.args[0] == "I has another owie"
 
-    @pytest.mark.trio
-    async def test_asyncio_trio_error_depr1(self, loop):
-        async def err_trio():
-            await trio.sleep(0.01)
-            raise RuntimeError("I has another owie")
-
-        with pytest.raises(RuntimeError) as err:
-            await aio_as_trio(partial(self.call_a_t_depr, loop=loop), loop=loop)(err_trio)
-        assert err.value.args[0] == "I has another owie"
-
-    @pytest.mark.trio
-    async def test_asyncio_trio_error_depr2(self, loop):
-        async def err_trio():
-            await trio.sleep(0.01)
-            raise RuntimeError("I has another owie")
-
-        with pytest.raises(RuntimeError) as err:
-            with test_utils.deprecate(self):
-                await loop.run_asyncio(partial(self.call_a_t, loop=loop), err_trio)
-        assert err.value.args[0] == "I has another owie"
-
-    @pytest.mark.trio
-    async def test_asyncio_trio_error_depr3(self, loop):
-        async def err_trio():
-            await trio.sleep(0.01)
-            raise RuntimeError("I has another owie")
-
-        with pytest.raises(RuntimeError) as err:
-            with test_utils.deprecate(self):
-                await loop.run_asyncio(partial(self.call_a_t_depr, loop=loop), err_trio)
-        assert err.value.args[0] == "I has another owie"
-
     @pytest.mark.trio
     async def test_asyncio_trio_sync_error(self, loop):
         def err_trio_sync():
@@ -266,37 +160,16 @@ def err_trio_sync():
             await aio_as_trio(partial(self.call_a_ts, loop=loop), loop=loop)(err_trio_sync)
         assert err.value.args[0] == "I has more owie"
 
-    @pytest.mark.trio
-    async def test_asyncio_trio_sync_error_depr(self, loop):
-        def err_trio_sync():
-            loop.time()  # verify that the loop is running
-            raise RuntimeError("I has more owie")
-
-        with pytest.raises(RuntimeError) as err:
-            with test_utils.deprecate(self):
-                await loop.run_asyncio(partial(self.call_a_ts, loop=loop), err_trio_sync)
-        assert err.value.args[0] == "I has more owie"
-
     @pytest.mark.trio
     async def test_trio_asyncio_error(self, loop):
         async def err_asyncio():
-            await asyncio.sleep(0.01, loop=loop)
+            await asyncio.sleep(0.01)
             raise RuntimeError("I has an owie")
 
         with pytest.raises(RuntimeError) as err:
             await self.call_t_a(err_asyncio, loop=loop)
         assert err.value.args[0] == "I has an owie"
 
-    @pytest.mark.trio
-    async def test_trio_asyncio_error_depr(self, loop):
-        async def err_asyncio():
-            await asyncio.sleep(0.01, loop=loop)
-            raise RuntimeError("I has an owie")
-
-        with pytest.raises(RuntimeError) as err:
-            await self.call_t_a_depr(err_asyncio, loop=loop)
-        assert err.value.args[0] == "I has an owie"
-
     @pytest.mark.trio
     async def test_asyncio_trio_cancel_out(self, loop):
         async def cancelled_trio(seen):
@@ -317,14 +190,14 @@ async def cancelled_trio(seen):
     async def test_trio_asyncio_cancel_out(self, loop):
         async def cancelled_asyncio(seen):
             seen.flag |= 1
-            await asyncio.sleep(0.01, loop=loop)
-            f = asyncio.Future(loop=loop)
+            await asyncio.sleep(0.01)
+            f = asyncio.Future()
             f.cancel()
             return f.result()  # raises error
 
         def cancelled_future(seen):
             seen.flag |= 1
-            f = asyncio.Future(loop=loop)
+            f = asyncio.Future()
             f.cancel()
             return f  # contains error
 
@@ -343,36 +216,6 @@ async def check_cancel(proc, seen):
         await check_cancel(cancelled_asyncio, seen)
         assert seen.flag == 1 | 4
 
-    @pytest.mark.trio
-    async def test_trio_asyncio_cancel_out_depr(self, loop):
-        async def cancelled_asyncio(seen):
-            seen.flag |= 1
-            await asyncio.sleep(0.01, loop=loop)
-            f = asyncio.Future(loop=loop)
-            f.cancel()
-            return f.result()  # raises error
-
-        def cancelled_future(seen):
-            seen.flag |= 1
-            f = asyncio.Future(loop=loop)
-            f.cancel()
-            return f  # contains error
-
-        async def check_cancel(proc, seen):
-            with trio.CancelScope() as scope:
-                with pytest.raises(asyncio.CancelledError):
-                    await self.call_t_a_depr(proc, seen, loop=loop)
-            assert not scope.cancel_called
-            seen.flag |= 4
-
-        seen = Seen()
-        await check_cancel(cancelled_future, seen)
-        assert seen.flag == 1 | 4
-
-        seen = Seen()
-        await check_cancel(cancelled_asyncio, seen)
-        assert seen.flag == 1 | 4
-
     @pytest.mark.trio
     async def test_asyncio_trio_cancel_in(self, loop):
         async def in_trio(started, seen):
@@ -387,7 +230,7 @@ async def in_trio(started, seen):
                 seen.flag |= 2
 
         async def cancel_asyncio(seen):
-            started = asyncio.Event(loop=loop)
+            started = asyncio.Event()
             f = asyncio.ensure_future(self.call_a_t(in_trio, started, seen, loop=loop))
             await started.wait()
             f.cancel()
@@ -404,7 +247,7 @@ async def test_trio_asyncio_cancel_in(self, loop):
         async def in_asyncio(started, seen):
             started.set()
             try:
-                await asyncio.sleep(9999, loop=loop)
+                await asyncio.sleep(9999)
             except asyncio.CancelledError:
                 seen.flag |= 1
             except trio.Cancelled:
@@ -426,35 +269,6 @@ async def cancel_trio(seen):
         await cancel_trio(seen)
         assert seen.flag == 1 | 2 | 8
 
-    @pytest.mark.trio
-    async def test_trio_asyncio_cancel_in_depr(self, loop):
-        async def in_asyncio(started, seen):
-            started.set()
-            try:
-                await asyncio.sleep(9999, loop=loop)
-            except asyncio.CancelledError:
-                seen.flag |= 1
-            except trio.Cancelled:
-                seen.flag |= 16
-            else:
-                seen.flag |= 4
-            finally:
-                seen.flag |= 2
-
-        async def cancel_trio(seen):
-            started = trio.Event()
-            async with trio.open_nursery() as nursery:
-                nursery.start_soon(
-                    partial(self.call_t_a_depr, loop=loop), in_asyncio, started, seen
-                )
-                await started.wait()
-                nursery.cancel_scope.cancel()
-            seen.flag |= 8
-
-        seen = Seen()
-        await cancel_trio(seen)
-        assert seen.flag == 1 | 2 | 8
-
     @pytest.mark.trio
     async def test_trio_asyncio_cancel_direct(self, loop):
         def in_asyncio(started, seen):
@@ -479,30 +293,6 @@ async def cancel_trio(seen):
             await cancel_trio(seen)
         assert seen.flag == 1 | 8
 
-    @pytest.mark.trio
-    async def test_trio_asyncio_cancel_direct_depr(self, loop):
-        def in_asyncio(started, seen):
-            # This is intentionally not async
-            seen.flag |= 1
-            raise asyncio.CancelledError()
-
-        async def cancel_trio(seen):
-            started = trio.Event()
-            try:
-                async with trio.open_nursery() as nursery:
-                    nursery.start_soon(
-                        partial(self.call_t_a_depr, loop=loop), in_asyncio, started, seen
-                    )
-                    await started.wait()
-                    nursery.cancel_scope.cancel()
-            finally:
-                seen.flag |= 8
-
-        seen = Seen()
-        with pytest.raises(asyncio.CancelledError):
-            await cancel_trio(seen)
-        assert seen.flag == 1 | 8
-
     @pytest.mark.trio
     async def test_trio_asyncio_error_direct(self, loop):
         def err_asyncio():
@@ -513,25 +303,14 @@ def err_asyncio():
             await self.call_t_a(err_asyncio, loop=loop)
         assert err.value.args[0] == "I has an owie"
 
-    @pytest.mark.trio
-    async def test_trio_asyncio_error_direct_depr(self, loop):
-        def err_asyncio():
-            # This is intentionally not async
-            raise RuntimeError("I has an owie")
-
-        with pytest.raises(RuntimeError) as err:
-            await self.call_t_a_depr(err_asyncio, loop=loop)
-        assert err.value.args[0] == "I has an owie"
-
     @pytest.mark.trio
     async def test_trio_asyncio_generator(self, loop):
         async def dly_asyncio():
             yield 1
-            await asyncio.sleep(0.01, loop=loop)
+            await asyncio.sleep(0.01)
             yield 2
 
-        with test_utils.deprecate(self):
-            res = await async_gen_to_list(loop.wrap_generator(dly_asyncio))
+        res = await async_gen_to_list(run_aio_generator(loop, dly_asyncio()))
         assert res == [1, 2]
 
     @pytest.mark.trio
@@ -541,9 +320,8 @@ async def dly_asyncio():
             raise RuntimeError("I has an owie")
             yield 2
 
-        with test_utils.deprecate(self):
-            with pytest.raises(RuntimeError) as err:
-                await async_gen_to_list(loop.wrap_generator(dly_asyncio))
+        with pytest.raises(RuntimeError) as err:
+            await async_gen_to_list(run_aio_generator(loop, dly_asyncio()))
         assert err.value.args[0] == "I has an owie"
 
     @pytest.mark.trio
@@ -557,13 +335,12 @@ async def cancel_soon(nursery):
             await trio.sleep(0.01)
             nursery.cancel_scope.cancel()
 
-        hold = asyncio.Event(loop=loop)
+        hold = asyncio.Event()
         seen = Seen()
 
-        with test_utils.deprecate(self):
-            async with trio.open_nursery() as nursery:
-                nursery.start_soon(async_gen_to_list, loop.wrap_generator(dly_asyncio, hold, seen))
-                nursery.start_soon(cancel_soon, nursery)
+        async with trio.open_nursery() as nursery:
+            nursery.start_soon(async_gen_to_list, run_aio_generator(loop, dly_asyncio(hold, seen)))
+            nursery.start_soon(cancel_soon, nursery)
         assert nursery.cancel_scope.cancel_called
         assert seen.flag == 1
 
@@ -571,7 +348,7 @@ async def cancel_soon(nursery):
     async def test_trio_asyncio_iterator(self, loop):
         async def slow_nums():
             for n in range(1, 6):
-                await asyncio.sleep(0.01, loop=loop)
+                await asyncio.sleep(0.01)
                 yield n
 
         sum = 0
@@ -583,7 +360,7 @@ async def slow_nums():
     async def test_trio_asyncio_iterator_depr(self, loop):
         async def slow_nums():
             for n in range(1, 6):
-                await asyncio.sleep(0.01, loop=loop)
+                await asyncio.sleep(0.01)
                 yield n
 
         sum = 0
diff --git a/tests/module_with_deprecations.py b/tests/module_with_deprecations.py
new file mode 100644
index 00000000..24de2588
--- /dev/null
+++ b/tests/module_with_deprecations.py
@@ -0,0 +1,21 @@
+regular = "hi"
+
+from trio_asyncio import _deprecate
+
+_deprecate.enable_attribute_deprecations(__name__)
+
+# Make sure that we don't trigger infinite recursion when accessing module
+# attributes in between calling enable_attribute_deprecations and defining
+# __deprecated_attributes__:
+import sys
+
+this_mod = sys.modules[__name__]
+assert this_mod.regular == "hi"
+assert not hasattr(this_mod, "dep1")
+
+__deprecated_attributes__ = {
+    "dep1": _deprecate.DeprecatedAttribute("value1", "1.1", issue=1),
+    "dep2": _deprecate.DeprecatedAttribute(
+        "value2", "1.2", issue=1, instead="instead-string"
+    ),
+}
diff --git a/tests/test_aio_subprocess.py b/tests/test_aio_subprocess.py
index 55ec0dfc..218d7399 100644
--- a/tests/test_aio_subprocess.py
+++ b/tests/test_aio_subprocess.py
@@ -20,12 +20,12 @@ class MySubprocessProtocol(asyncio.SubprocessProtocol):
     def __init__(self, loop):
         self.state = 'INITIAL'
         self.transport = None
-        self.connected = asyncio.Future(loop=loop)
-        self.completed = asyncio.Future(loop=loop)
-        self.disconnects = {fd: asyncio.Future(loop=loop) for fd in range(3)}
+        self.connected = asyncio.Future()
+        self.completed = asyncio.Future()
+        self.disconnects = {fd: asyncio.Future() for fd in range(3)}
         self.data = {1: b'', 2: b''}
         self.returncode = None
-        self.got_data = {1: asyncio.Event(loop=loop), 2: asyncio.Event(loop=loop)}
+        self.got_data = {1: asyncio.Event(), 2: asyncio.Event()}
 
     def connection_made(self, transport):
         self.transport = transport
diff --git a/tests/test_deprecate.py b/tests/test_deprecate.py
new file mode 100644
index 00000000..749c5901
--- /dev/null
+++ b/tests/test_deprecate.py
@@ -0,0 +1,245 @@
+# Mostly copied from trio.tests.test_deprecate.
+
+import pytest
+
+import inspect
+import warnings
+
+from trio_asyncio._deprecate import (
+    TrioAsyncioDeprecationWarning,
+    warn_deprecated,
+    deprecated,
+    deprecated_alias,
+)
+
+from . import module_with_deprecations
+
+
+@pytest.fixture
+def recwarn_always(recwarn):
+    warnings.simplefilter("always")
+    # ResourceWarnings about unclosed sockets can occur nondeterministically
+    # (during GC) which throws off the tests in this file
+    warnings.simplefilter("ignore", ResourceWarning)
+    return recwarn
+
+
+def _here():
+    info = inspect.getframeinfo(inspect.currentframe().f_back)
+    return (info.filename, info.lineno)
+
+
+def test_warn_deprecated(recwarn_always):
+    def deprecated_thing():
+        warn_deprecated("ice", "1.2", issue=1, instead="water")
+
+    deprecated_thing()
+    filename, lineno = _here()
+    assert len(recwarn_always) == 1
+    got = recwarn_always.pop(TrioAsyncioDeprecationWarning)
+    assert "ice is deprecated" in got.message.args[0]
+    assert "trio-asyncio 1.2" in got.message.args[0]
+    assert "water instead" in got.message.args[0]
+    assert "/issues/1" in got.message.args[0]
+    assert got.filename == filename
+    assert got.lineno == lineno - 1
+
+
+def test_warn_deprecated_no_instead_or_issue(recwarn_always):
+    # Explicitly no instead or issue
+    warn_deprecated("water", "1.3", issue=None, instead=None)
+    assert len(recwarn_always) == 1
+    got = recwarn_always.pop(TrioAsyncioDeprecationWarning)
+    assert "water is deprecated" in got.message.args[0]
+    assert "no replacement" in got.message.args[0]
+    assert "trio-asyncio 1.3" in got.message.args[0]
+
+
+def test_warn_deprecated_stacklevel(recwarn_always):
+    def nested1():
+        nested2()
+
+    def nested2():
+        warn_deprecated("x", "1.3", issue=7, instead="y", stacklevel=3)
+
+    filename, lineno = _here()
+    nested1()
+    got = recwarn_always.pop(TrioAsyncioDeprecationWarning)
+    assert got.filename == filename
+    assert got.lineno == lineno + 1
+
+
+def old():  # pragma: no cover
+    pass
+
+
+def new():  # pragma: no cover
+    pass
+
+
+def test_warn_deprecated_formatting(recwarn_always):
+    warn_deprecated(old, "1.0", issue=1, instead=new)
+    got = recwarn_always.pop(TrioAsyncioDeprecationWarning)
+    assert "test_deprecate.old is deprecated" in got.message.args[0]
+    assert "test_deprecate.new instead" in got.message.args[0]
+
+
+@deprecated("1.5", issue=123, instead=new)
+def deprecated_old():
+    return 3
+
+
+def test_deprecated_decorator(recwarn_always):
+    assert deprecated_old() == 3
+    got = recwarn_always.pop(TrioAsyncioDeprecationWarning)
+    assert "test_deprecate.deprecated_old is deprecated" in got.message.args[0]
+    assert "1.5" in got.message.args[0]
+    assert "test_deprecate.new" in got.message.args[0]
+    assert "issues/123" in got.message.args[0]
+
+
+class Foo:
+    @deprecated("1.0", issue=123, instead="crying")
+    def method(self):
+        return 7
+
+
+def test_deprecated_decorator_method(recwarn_always):
+    f = Foo()
+    assert f.method() == 7
+    got = recwarn_always.pop(TrioAsyncioDeprecationWarning)
+    assert "test_deprecate.Foo.method is deprecated" in got.message.args[0]
+
+
+@deprecated("1.2", thing="the thing", issue=None, instead=None)
+def deprecated_with_thing():
+    return 72
+
+
+def test_deprecated_decorator_with_explicit_thing(recwarn_always):
+    assert deprecated_with_thing() == 72
+    got = recwarn_always.pop(TrioAsyncioDeprecationWarning)
+    assert "the thing is deprecated" in got.message.args[0]
+
+
+def new_hotness():
+    return "new hotness"
+
+
+old_hotness = deprecated_alias("old_hotness", new_hotness, "1.23", issue=1)
+
+
+def test_deprecated_alias(recwarn_always):
+    assert old_hotness() == "new hotness"
+    got = recwarn_always.pop(TrioAsyncioDeprecationWarning)
+    assert "test_deprecate.old_hotness is deprecated" in got.message.args[0]
+    assert "1.23" in got.message.args[0]
+    assert "test_deprecate.new_hotness instead" in got.message.args[0]
+    assert "issues/1" in got.message.args[0]
+
+    assert ".. deprecated:: 1.23" in old_hotness.__doc__
+    assert "test_deprecate.new_hotness instead" in old_hotness.__doc__
+    assert "issues/1>`__" in old_hotness.__doc__
+
+
+class Alias:
+    def new_hotness_method(self):
+        return "new hotness method"
+
+    old_hotness_method = deprecated_alias(
+        "Alias.old_hotness_method", new_hotness_method, "3.21", issue=1
+    )
+
+
+def test_deprecated_alias_method(recwarn_always):
+    obj = Alias()
+    assert obj.old_hotness_method() == "new hotness method"
+    got = recwarn_always.pop(TrioAsyncioDeprecationWarning)
+    msg = got.message.args[0]
+    assert "test_deprecate.Alias.old_hotness_method is deprecated" in msg
+    assert "test_deprecate.Alias.new_hotness_method instead" in msg
+
+
+@deprecated("2.1", issue=1, instead="hi")
+def docstring_test1():  # pragma: no cover
+    """Hello!"""
+
+
+@deprecated("2.1", issue=None, instead="hi")
+def docstring_test2():  # pragma: no cover
+    """Hello!"""
+
+
+@deprecated("2.1", issue=1, instead=None)
+def docstring_test3():  # pragma: no cover
+    """Hello!"""
+
+
+@deprecated("2.1", issue=None, instead=None)
+def docstring_test4():  # pragma: no cover
+    """Hello!"""
+
+
+def test_deprecated_docstring_munging():
+    assert (
+        docstring_test1.__doc__
+        == """Hello!
+
+.. deprecated:: 2.1
+   Use hi instead.
+   For details, see `issue #1 <https://github.com/python-trio/trio-asyncio/issues/1>`__.
+
+"""
+    )
+
+    assert (
+        docstring_test2.__doc__
+        == """Hello!
+
+.. deprecated:: 2.1
+   Use hi instead.
+
+"""
+    )
+
+    assert (
+        docstring_test3.__doc__
+        == """Hello!
+
+.. deprecated:: 2.1
+   For details, see `issue #1 <https://github.com/python-trio/trio-asyncio/issues/1>`__.
+
+"""
+    )
+
+    assert (
+        docstring_test4.__doc__
+        == """Hello!
+
+.. deprecated:: 2.1
+
+"""
+    )
+
+
+def test_module_with_deprecations(recwarn_always):
+    assert module_with_deprecations.regular == "hi"
+    assert len(recwarn_always) == 0
+
+    filename, lineno = _here()
+    assert module_with_deprecations.dep1 == "value1"
+    got = recwarn_always.pop(TrioAsyncioDeprecationWarning)
+    assert got.filename == filename
+    assert got.lineno == lineno + 1
+
+    assert "module_with_deprecations.dep1" in got.message.args[0]
+    assert "trio-asyncio 1.1" in got.message.args[0]
+    assert "/issues/1" in got.message.args[0]
+    assert "value1 instead" in got.message.args[0]
+
+    assert module_with_deprecations.dep2 == "value2"
+    got = recwarn_always.pop(TrioAsyncioDeprecationWarning)
+    assert "instead-string instead" in got.message.args[0]
+
+    with pytest.raises(AttributeError):
+        module_with_deprecations.asdf
diff --git a/tests/test_misc.py b/tests/test_misc.py
index 7ff0c6c3..dd97f08f 100644
--- a/tests/test_misc.py
+++ b/tests/test_misc.py
@@ -3,9 +3,6 @@
 import asyncio
 import trio
 import sys
-from . import utils as test_utils
-
-# from tests import aiotest
 
 
 class Seen:
@@ -44,16 +41,6 @@ async def raise_err():
             await trio_asyncio.aio_as_trio(raise_err, loop=loop)()
         assert err.value.args[0] == "Foo"
 
-    @pytest.mark.trio
-    async def test_err1_depr(self, loop):
-        async def raise_err():
-            raise RuntimeError("Foo")
-
-        with test_utils.deprecate(self):
-            with pytest.raises(RuntimeError) as err:
-                await loop.run_asyncio(raise_err)
-        assert err.value.args[0] == "Foo"
-
     @pytest.mark.trio
     async def test_err3(self, loop):
         owch = 0
@@ -71,24 +58,6 @@ async def call_nested():
         await trio_asyncio.aio_as_trio(call_nested, loop=loop)()
         assert owch
 
-    @pytest.mark.trio
-    async def test_err3_depr(self, loop):
-        owch = 0
-
-        async def nest():
-            nonlocal owch
-            owch = 1
-            raise RuntimeError("Hello")
-
-        async def call_nested():
-            with pytest.raises(RuntimeError) as err:
-                await loop.run_trio(nest)
-            assert err.value.args[0] == "Hello"
-
-        with test_utils.deprecate(self):
-            await loop.run_asyncio(call_nested)
-        assert owch
-
     @pytest.mark.trio
     async def test_run(self, loop):
         owch = 0
@@ -104,23 +73,6 @@ async def call_nested():
         await trio_asyncio.aio_as_trio(call_nested, loop=loop)()
         assert owch
 
-    @pytest.mark.trio
-    async def test_run_depr(self, loop):
-        owch = 0
-
-        async def nest():
-            await trio.sleep(0.01)
-            nonlocal owch
-            owch = 1
-
-        async def call_nested():
-            with test_utils.deprecate(self):
-                await loop.run_trio(nest)
-
-        with test_utils.deprecate(self):
-            await loop.run_asyncio(call_nested)
-        assert owch
-
     async def _test_run(self):
         owch = 0
 
@@ -138,24 +90,6 @@ async def call_nested():
     def test_run2(self):
         trio_asyncio.run(self._test_run)
 
-    async def _test_run_depr(self):
-        owch = 0
-
-        async def nest():
-            await trio.sleep(0.01)
-            nonlocal owch
-            owch = 1
-
-        async def call_nested():
-            await trio_asyncio.run_trio(nest)
-
-        with test_utils.deprecate(self):
-            await trio_asyncio.run_asyncio(call_nested)
-        assert owch
-
-    def test_run2_depr(self):
-        trio_asyncio.run(self._test_run_depr)
-
     @pytest.mark.trio
     async def test_run_task(self):
         owch = 0
@@ -196,27 +130,6 @@ async def call_more_nested():
         await trio_asyncio.aio_as_trio(call_more_nested, loop=loop)()
         assert owch
 
-    @pytest.mark.trio
-    async def test_err2_depr(self, loop):
-        owch = 0
-
-        async def nest():
-            nonlocal owch
-            owch = 1
-            raise RuntimeError("Hello")
-
-        async def call_nested():
-            await loop.run_asyncio(nest)
-
-        async def call_more_nested():
-            with pytest.raises(RuntimeError) as err:
-                await loop.run_trio(call_nested)
-            assert err.value.args[0] == "Hello"
-
-        with test_utils.deprecate(self):
-            await loop.run_asyncio(call_more_nested)
-        assert owch
-
     @pytest.mark.trio
     async def test_run3(self, loop):
         owch = 0
@@ -234,24 +147,6 @@ async def call_more_nested():
         await trio_asyncio.aio_as_trio(call_more_nested, loop=loop)()
         assert owch
 
-    @pytest.mark.trio
-    async def test_run3_depr(self, loop):
-        owch = 0
-
-        async def nest():
-            nonlocal owch
-            owch = 1
-
-        async def call_nested():
-            await loop.run_asyncio(nest)
-
-        async def call_more_nested():
-            await loop.run_trio(call_nested)
-
-        with test_utils.deprecate(self):
-            await loop.run_asyncio(call_more_nested)
-        assert owch
-
     @pytest.mark.trio
     async def test_cancel_sleep(self, loop):
         owch = 0
@@ -259,36 +154,16 @@ async def test_cancel_sleep(self, loop):
         def do_not_run():
             nonlocal owch
             owch = 1
-            raise Exception("should not run")
 
         async def cancel_sleep():
             h = loop.call_later(0.2, do_not_run)
-            await asyncio.sleep(0.1, loop=loop)
+            await asyncio.sleep(0.01)
             h.cancel()
-            await asyncio.sleep(0.3, loop=loop)
+            await asyncio.sleep(0.3)
 
         await trio_asyncio.aio_as_trio(cancel_sleep, loop=loop)()
         assert owch == 0
 
-    @pytest.mark.trio
-    async def test_cancel_sleep_depr(self, loop):
-        owch = 0
-
-        def do_not_run():
-            nonlocal owch
-            owch = 1
-            raise Exception("should not run")
-
-        async def cancel_sleep():
-            h = loop.call_later(0.2, do_not_run)
-            await asyncio.sleep(0.1, loop=loop)
-            h.cancel()
-            await asyncio.sleep(0.3, loop=loop)
-
-        with test_utils.deprecate(self):
-            await loop.run_asyncio(cancel_sleep)
-        assert owch == 0
-
 
 @pytest.mark.trio
 async def test_wrong_context_manager_order():
@@ -352,7 +227,6 @@ async def run_asyncio_loop(nursery, *, task_status=trio.TASK_STATUS_IGNORED):
                 # Trigger KeyboardInterrupt that should propagate accross the coroutines
                 signal.pthread_kill(threading.get_ident(), signal.SIGINT)
 
-
 @pytest.mark.trio
 @pytest.mark.parametrize("throw_another", [False, True])
 async def test_cancel_loop(throw_another):
diff --git a/trio_asyncio/__init__.py b/trio_asyncio/__init__.py
index e37e8819..50526feb 100644
--- a/trio_asyncio/__init__.py
+++ b/trio_asyncio/__init__.py
@@ -27,12 +27,6 @@
     run_trio_task,
     run_trio,
     run_aio_coroutine,
-    # forwarders to deprecated event loop methods:
-    run_future,
-    run_coroutine,
-    run_asyncio,
-    wrap_generator,
-    run_iterator,
 )
 from ._adapter import (
     aio_as_trio,
@@ -40,9 +34,6 @@
     # aliases for the above:
     asyncio_as_trio,
     trio_as_asyncio,
-    # deprecated aliases for the above:
-    trio2aio,
-    aio2trio,
     # additional experimental goodie:
     allow_asyncio,
 )
diff --git a/trio_asyncio/_adapter.py b/trio_asyncio/_adapter.py
index a1145a9e..88be8349 100644
--- a/trio_asyncio/_adapter.py
+++ b/trio_asyncio/_adapter.py
@@ -2,17 +2,15 @@
 # Trio.
 
 import types
-import warnings
 
 import asyncio
 import trio_asyncio
 from contextvars import ContextVar
 
-from ._deprecate import deprecated_alias
 from ._util import run_aio_generator, run_aio_future, run_trio_generator
-from ._loop import current_loop, current_policy
+from ._loop import current_loop
 
-from functools import wraps, partial
+from functools import partial
 
 
 async def _call_defer(proc, *args, **kwargs):
@@ -56,7 +54,7 @@ async def __call__(self, *args, **kwargs):
         return await self.loop.run_aio_coroutine(f)
 
     def __await__(self):
-        """Compatibility code for "await loop.run_asyncio(coro)"
+        """Support for commonly used (but not recommended) "await aio_as_trio(proc(*args))"
         """
         f = self.proc
         if not hasattr(f, "__await__"):
@@ -236,7 +234,7 @@ def _allow_asyncio(fn, *args):
     coro = fn(*args)
     # start the coroutine
     if isinstance(coro, asyncio.Future):
-        return (yield from trio_asyncio.run_future(coro))
+        return (yield from trio_asyncio.run_aio_future(coro))
 
     p, a = coro.send, None
     while True:
@@ -271,7 +269,7 @@ async def allow_asyncio(fn, *args):
         import trio_asyncio
 
         async def hello(loop):
-            await asyncio.sleep(1, loop=loop)
+            await asyncio.sleep(1)
             print("Hello")
             await trio.sleep(1)
             print("World")
@@ -293,7 +291,3 @@ async def main():
         return await _allow_asyncio(fn, *args)
     finally:
         shim.reset(token)
-
-
-trio2aio = deprecated_alias("trio_asyncio.trio2aio", aio_as_trio, "0.10.0", issue=38)
-aio2trio = deprecated_alias("trio_asyncio.aio2trio", trio_as_aio, "0.10.0", issue=38)
diff --git a/trio_asyncio/_base.py b/trio_asyncio/_base.py
index 4329d1f8..3b64b462 100644
--- a/trio_asyncio/_base.py
+++ b/trio_asyncio/_base.py
@@ -10,9 +10,7 @@
 import concurrent.futures
 
 from ._handles import ScopedHandle, AsyncHandle
-from ._util import run_aio_future, run_aio_generator
-from ._deprecate import deprecated, deprecated_alias
-from . import _util
+from ._util import run_aio_future
 
 from selectors import _BaseSelectorImpl, EVENT_READ, EVENT_WRITE
 
@@ -415,7 +413,7 @@ async def synchronize(self):
 
         This is a Trio-flavored async function.
 
-        From asyncio, call ``await loop.run_trio(loop.synchronize)``
+        From asyncio, call ``await trio_as_aio(loop.synchronize)()``
         instead of ``await asyncio.sleep(0)`` if you need to process all
         queued callbacks.
 
@@ -788,43 +786,3 @@ def __enter__(self):
 
     def __exit__(self, *tb):
         raise RuntimeError("You need to use a sync loop, or 'async with open_loop()'.")
-
-    # Deprecated aliases #
-
-    run_future = staticmethod(
-        deprecated_alias(
-            "trio_asyncio.BaseTrioEventLoop.run_future",
-            _util.run_aio_future,
-            "0.10.0",
-            issue=38,
-        )
-    )
-
-    run_coroutine = deprecated_alias(
-        "trio_asyncio.BaseTrioEventLoop.run_coroutine",
-        run_aio_coroutine,
-        "0.10.0",
-        issue=38,
-    )
-
-    @deprecated("0.10.0", issue=38, instead="aio_as_trio(gen(*args))")
-    def wrap_generator(self, gen, *args):
-        return run_aio_generator(self, gen(*args))
-
-    @deprecated("0.10.0", issue=38, instead="aio_as_trio(aiter)")
-    def run_iterator(self, aiter):
-        return run_aio_generator(self, aiter)
-
-    @deprecated("0.10.0", issue=38, instead="aio_as_trio(proc)(*args)")
-    def run_asyncio(self, proc, *args):
-        from ._adapter import Asyncio_Trio_Wrapper
-        return Asyncio_Trio_Wrapper(proc, args=args, loop=self)
-
-    @deprecated("0.10.0", issue=38, instead="trio_as_aio(ctx)")
-    def wrap_trio_context(self, ctx):
-        from ._adapter import Trio_Asyncio_Wrapper
-        return Trio_Asyncio_Wrapper(ctx, loop=self)
-
-    @deprecated("0.10.0", issue=38, instead="trio_as_aio(proc)(*args)")
-    def run_trio(self, proc, *args):
-        return self.trio_as_future(proc, *args)
diff --git a/trio_asyncio/_loop.py b/trio_asyncio/_loop.py
index 617de191..da0019f8 100644
--- a/trio_asyncio/_loop.py
+++ b/trio_asyncio/_loop.py
@@ -4,7 +4,6 @@
 import sys
 import trio
 import asyncio
-import warnings
 import threading
 from contextvars import ContextVar
 
@@ -13,9 +12,8 @@
 except ImportError:
     from async_generator import asynccontextmanager
 
-from ._util import run_aio_future, run_aio_generator
 from ._async import TrioEventLoop
-from ._deprecate import deprecated, warn_deprecated
+from ._deprecate import warn_deprecated
 
 try:
     from trio.lowlevel import wait_for_child
@@ -346,7 +344,7 @@ async def _waitpid(self, pid, callback, *args):
 
     def add_child_handler(self, pid, callback, *args):
         """Add a callback to run when a child process terminates."""
-        h = self._loop.run_trio(self._waitpid, pid, callback, *args)
+        h = self._loop.trio_as_future(self._waitpid, pid, callback, *args)
         self._callbacks[pid] = h
 
     def remove_child_handler(self, pid):
@@ -488,43 +486,3 @@ def run_trio_task(proc, *args):
     will propagate to, and terminate, the trio-asyncio loop.
     """
     _running_loop().run_trio_task(proc, *args)
-
-
-# These are aliases for methods in BaseTrioEventLoop which are
-# themselves deprecated. If we deprecate these and call the deprecated
-# loop method, the user gets two warnings. If we just call the
-# deprecated loop method, the warning points here instead of to user
-# code. Therefore, we "chase the pointer" and inline the body of the
-# deprecated loop method into each of these functions.
-
-
-@deprecated("0.10.0", issue=38, instead="aio_as_trio(proc(*args))")
-def wrap_generator(proc, *args):
-    return run_aio_generator(_running_loop(), proc(*args))
-
-
-@deprecated("0.10.0", issue=38, instead="aio_as_trio(aiter)")
-def run_iterator(aiter):
-    return run_aio_generator(_running_loop(), aiter)
-
-
-@deprecated("0.10.0", issue=38, instead="trio_as_aio(ctx)")
-def wrap_trio_context(ctx):
-    from ._adapter import Trio_Asyncio_Wrapper
-    return Trio_Asyncio_Wrapper(ctx, loop=_running_loop())
-
-
-@deprecated("0.10.0", issue=38, instead="aio_as_trio(proc)(*args)")
-def run_asyncio(proc, *args):
-    from ._adapter import Asyncio_Trio_Wrapper
-    return Asyncio_Trio_Wrapper(proc, args=args, loop=_running_loop())
-
-
-@deprecated("0.10.0", issue=38, instead="run_aio_coroutine")
-async def run_coroutine(fut):
-    return await _running_loop().run_aio_coroutine(fut)
-
-
-@deprecated("0.10.0", issue=38, instead="run_aio_future")
-async def run_future(fut):
-    return await run_aio_future(fut)
diff --git a/trio_asyncio/_util.py b/trio_asyncio/_util.py
index cfadf56b..e27a0178 100644
--- a/trio_asyncio/_util.py
+++ b/trio_asyncio/_util.py
@@ -108,7 +108,7 @@ def abort_cb(raise_cancel_arg):
     try:
         while True:
             # Schedule in asyncio that we read the next item from the iterator
-            current_read = asyncio.ensure_future(consume_next(), loop=loop)
+            current_read = asyncio.ensure_future(consume_next())
 
             item = await trio.lowlevel.wait_task_rescheduled(abort_cb)
 
diff --git a/trio_asyncio/_version.py b/trio_asyncio/_version.py
index a65a5498..75fa6d0e 100644
--- a/trio_asyncio/_version.py
+++ b/trio_asyncio/_version.py
@@ -1,3 +1,3 @@
 # This file is imported from __init__.py and exec'd from setup.py
 
-__version__ = "0.11.0+dev"
+__version__ = "0.12.0+dev"