diff --git a/src/outcome/_impl.py b/src/outcome/_impl.py
index 004b72d..796fcf6 100644
--- a/src/outcome/_impl.py
+++ b/src/outcome/_impl.py
@@ -122,12 +122,6 @@ class Outcome(abc.ABC, Generic[ValueT]):
     hashable.
 
     """
-    _unwrapped: bool = attr.ib(default=False, eq=False, init=False)
-
-    def _set_unwrapped(self) -> None:
-        if self._unwrapped:
-            raise AlreadyUsedError
-        object.__setattr__(self, '_unwrapped', True)
 
     @abc.abstractmethod
     def unwrap(self) -> ValueT:
@@ -174,19 +168,26 @@ class Value(Outcome[ValueT], Generic[ValueT]):
     """The contained value."""
 
     def __repr__(self) -> str:
-        return f'Value({self.value!r})'
+        try:
+            return f'Value({self.value!r})'
+        except AttributeError:
+            return f'Value(<DEAD>)'
 
     def unwrap(self) -> ValueT:
-        self._set_unwrapped()
-        return self.value
+        try:
+            v = self.value
+        except AttributeError:
+            pass
+        else:
+            object.__delattr__(self, "value")
+            return v
+        raise AlreadyUsedError
 
     def send(self, gen: Generator[ResultT, ValueT, object]) -> ResultT:
-        self._set_unwrapped()
-        return gen.send(self.value)
+        return gen.send(self.unwrap())
 
     async def asend(self, agen: AsyncGenerator[ResultT, ValueT]) -> ResultT:
-        self._set_unwrapped()
-        return await agen.asend(self.value)
+        return await agen.asend(self.unwrap())
 
 
 @final
@@ -202,13 +203,25 @@ class Error(Outcome[NoReturn]):
     """The contained exception object."""
 
     def __repr__(self) -> str:
-        return f'Error({self.error!r})'
+        try:
+            return f'Error({self.error!r})'
+        except AttributeError:
+            return 'Error(<DEAD>)'
+
+    def _unwrap_error(self) -> BaseException:
+        try:
+            v = self.error
+        except AttributeError:
+            pass
+        else:
+            object.__delattr__(self, "error")
+            return v
+        raise AlreadyUsedError
 
     def unwrap(self) -> NoReturn:
-        self._set_unwrapped()
         # Tracebacks show the 'raise' line below out of context, so let's give
         # this variable a name that makes sense out of context.
-        captured_error = self.error
+        captured_error = self._unwrap_error()
         try:
             raise captured_error
         finally:
@@ -227,12 +240,10 @@ def unwrap(self) -> NoReturn:
             del captured_error, self
 
     def send(self, gen: Generator[ResultT, NoReturn, object]) -> ResultT:
-        self._set_unwrapped()
-        return gen.throw(self.error)
+        return gen.throw(self._unwrap_error())
 
     async def asend(self, agen: AsyncGenerator[ResultT, NoReturn]) -> ResultT:
-        self._set_unwrapped()
-        return await agen.athrow(self.error)
+        return await agen.athrow(self._unwrap_error())
 
 
 # A convenience alias to a union of both results, allowing exhaustiveness checking.
diff --git a/tests/test_sync.py b/tests/test_sync.py
index 855d776..ca33401 100644
--- a/tests/test_sync.py
+++ b/tests/test_sync.py
@@ -10,8 +10,9 @@
 def test_Outcome():
     v = Value(1)
     assert v.value == 1
-    assert v.unwrap() == 1
     assert repr(v) == "Value(1)"
+    assert v.unwrap() == 1
+    assert repr(v) == "Value(<DEAD>)"
 
     with pytest.raises(AlreadyUsedError):
         v.unwrap()
@@ -21,11 +22,12 @@ def test_Outcome():
     exc = RuntimeError("oops")
     e = Error(exc)
     assert e.error is exc
+    assert repr(e) == f"Error({exc!r})"
     with pytest.raises(RuntimeError):
         e.unwrap()
     with pytest.raises(AlreadyUsedError):
         e.unwrap()
-    assert repr(e) == f"Error({exc!r})"
+    assert repr(e) == "Error(<DEAD>)"
 
     e = Error(exc)
     with pytest.raises(TypeError):