Repository: sqlalchemy/sqlalchemy

Issue:
`configure_mapper` function missing return type annotation
### Ensure stubs packages are not installed

- [X] No sqlalchemy stub packages is installed (both `sqlalchemy-stubs` and `sqlalchemy2-stubs` are not compatible with v2)

### Verify if the api is typed

- [X] The api is not in a module listed in [#6810](https://github.com/sqlalchemy/sqlalchemy/issues/6810) so it should pass type checking

### Describe the typing issue

When using Mypy as a typechecker, calls to `configure_mapper` result in a type error

### To Reproduce

```python
configure_mapper()
```


### Error

```
src/db_main.py: note: In function "set_up_pg_db":
src/db_main.py:51: error: Call to untyped function "configure_mappers" in typed context  [no-untyped-call]
        configure_mappers()
        ^~~~~~~~~~~~~~~~~~~
Found 1 error in 1 file (checked 166 source files)
``` 

### Versions

- OS: MacOS Ventura (13.5)
- Python: 3.8.5
- SQLAlchemy: 2.0.18
- Type checker (eg: mypy 0.991, pyright 1.1.290, etc): mypy 1.4.1


### Additional context

_No response_

Discussion:

Patch:
diff --git a/.github/workflows/create-wheels.yaml b/.github/workflows/create-wheels.yaml
index 5eb2eef04..adb78402c 100644
--- a/.github/workflows/create-wheels.yaml
+++ b/.github/workflows/create-wheels.yaml
@@ -49,7 +49,7 @@ jobs:
       fail-fast: false
 
     steps:
-      - uses: actions/checkout@v3
+      - uses: actions/checkout@v4
 
       - name: Remove tag_build from setup.cfg
         # sqlalchemy has `tag_build` set to `dev` in setup.cfg. We need to remove it before creating the weel
@@ -73,7 +73,7 @@ jobs:
 
       - name: Build compiled wheels
         if: ${{ matrix.wheel_mode == 'compiled' }}
-        uses: pypa/cibuildwheel@v2.14.1
+        uses: pypa/cibuildwheel@v2.15.0
         env:
           CIBW_ARCHS_LINUX: ${{ matrix.linux_archs }}
           CIBW_BUILD: ${{ matrix.python }}
diff --git a/.github/workflows/run-on-pr.yaml b/.github/workflows/run-on-pr.yaml
index 40ed73eeb..c19e7a590 100644
--- a/.github/workflows/run-on-pr.yaml
+++ b/.github/workflows/run-on-pr.yaml
@@ -37,7 +37,7 @@ jobs:
     # steps to run in each job. Some are github actions, others run shell commands
     steps:
       - name: Checkout repo
-        uses: actions/checkout@v3
+        uses: actions/checkout@v4
 
       - name: Set up python
         uses: actions/setup-python@v4
@@ -72,7 +72,7 @@ jobs:
 
     steps:
       - name: Checkout repo
-        uses: actions/checkout@v3
+        uses: actions/checkout@v4
 
       - name: Set up python
         uses: actions/setup-python@v4
diff --git a/doc/build/changelog/unreleased_20/10280.rst b/doc/build/changelog/unreleased_20/10280.rst
new file mode 100644
index 000000000..6b4c64085
--- /dev/null
+++ b/doc/build/changelog/unreleased_20/10280.rst
@@ -0,0 +1,13 @@
+.. change::
+    :tags: bug, sql
+    :tickets: 10280
+
+    The :class:`.Values` construct will now automatically create a proxy (i.e.
+    a copy) of a :class:`_sql.column` if the column were already associated
+    with an existing FROM clause.  This allows that an expression like
+    ``values_obj.c.colname`` will produce the correct FROM clause even in the
+    case that ``colname`` was passed as a :class:`_sql.column` that was already
+    used with a previous :class:`.Values` or other table construct.
+    Originally this was considered to be a candidate for an error condition,
+    however it's likely this pattern is already in widespread use so it's
+    now added to support.
diff --git a/doc/build/changelog/unreleased_20/10288.rst b/doc/build/changelog/unreleased_20/10288.rst
new file mode 100644
index 000000000..18b0bb070
--- /dev/null
+++ b/doc/build/changelog/unreleased_20/10288.rst
@@ -0,0 +1,12 @@
+.. change::
+    :tags: usecase, typing
+    :tickets: 10288
+
+    Made the contained type for :class:`.Mapped` covariant; this is to allow
+    greater flexibility for end-user typing scenarios, such as the use of
+    protocols to represent particular mapped class structures that are passed
+    to other functions. As part of this change, the contained type was also
+    made covariant for dependent and related types such as
+    :class:`_orm.base.SQLORMOperations`, :class:`_orm.WriteOnlyMapped`, and
+    :class:`_sql.SQLColumnExpression`. Pull request courtesy Roméo Després.
+
diff --git a/doc/build/core/engines.rst b/doc/build/core/engines.rst
index 696f058e6..d1741d9ea 100644
--- a/doc/build/core/engines.rst
+++ b/doc/build/core/engines.rst
@@ -505,7 +505,7 @@ namespace of SA loggers that can be turned on is as follows:
   on :paramref:`_sa.create_engine.echo_pool`, respectively.
 
 * ``sqlalchemy.dialects`` - controls custom logging for SQL dialects, to the
-  extend that logging is used within specific dialects, which is generally
+  extent that logging is used within specific dialects, which is generally
   minimal.
 
 * ``sqlalchemy.orm`` - controls logging of various ORM functions to the extent
diff --git a/examples/asyncio/async_orm.py b/examples/asyncio/async_orm.py
index eabc0250d..592323be4 100644
--- a/examples/asyncio/async_orm.py
+++ b/examples/asyncio/async_orm.py
@@ -96,7 +96,7 @@ async def async_main():
 
         result = await session.scalars(select(A).order_by(A.id))
 
-        a1 = result.one()
+        a1 = result.first()
 
         a1.data = "new data"
 
diff --git a/lib/sqlalchemy/ext/hybrid.py b/lib/sqlalchemy/ext/hybrid.py
index 83dfb5033..1ac6fafc1 100644
--- a/lib/sqlalchemy/ext/hybrid.py
+++ b/lib/sqlalchemy/ext/hybrid.py
@@ -927,10 +927,10 @@ class _HybridDeleterType(Protocol[_T_co]):
         ...
 
 
-class _HybridExprCallableType(Protocol[_T]):
+class _HybridExprCallableType(Protocol[_T_co]):
     def __call__(
         s, cls: Any
-    ) -> Union[_HasClauseElement, SQLColumnExpression[_T]]:
+    ) -> Union[_HasClauseElement, SQLColumnExpression[_T_co]]:
         ...
 
 
diff --git a/lib/sqlalchemy/orm/attributes.py b/lib/sqlalchemy/orm/attributes.py
index 6a9766c6f..b1bda2281 100644
--- a/lib/sqlalchemy/orm/attributes.py
+++ b/lib/sqlalchemy/orm/attributes.py
@@ -120,6 +120,7 @@ if TYPE_CHECKING:
 
 
 _T = TypeVar("_T")
+_T_co = TypeVar("_T_co", bound=Any, covariant=True)
 
 
 _AllPendingType = Sequence[
@@ -132,10 +133,10 @@ _UNKNOWN_ATTR_KEY = object()
 
 @inspection._self_inspects
 class QueryableAttribute(
-    _DeclarativeMapped[_T],
-    SQLORMExpression[_T],
+    _DeclarativeMapped[_T_co],
+    SQLORMExpression[_T_co],
     interfaces.InspectionAttr,
-    interfaces.PropComparator[_T],
+    interfaces.PropComparator[_T_co],
     roles.JoinTargetRole,
     roles.OnClauseRole,
     sql_base.Immutable,
@@ -178,13 +179,13 @@ class QueryableAttribute(
 
     is_attribute = True
 
-    dispatch: dispatcher[QueryableAttribute[_T]]
+    dispatch: dispatcher[QueryableAttribute[_T_co]]
 
     class_: _ExternalEntityType[Any]
     key: str
     parententity: _InternalEntityType[Any]
     impl: AttributeImpl
-    comparator: interfaces.PropComparator[_T]
+    comparator: interfaces.PropComparator[_T_co]
     _of_type: Optional[_InternalEntityType[Any]]
     _extra_criteria: Tuple[ColumnElement[bool], ...]
     _doc: Optional[str]
@@ -198,7 +199,7 @@ class QueryableAttribute(
         class_: _ExternalEntityType[_O],
         key: str,
         parententity: _InternalEntityType[_O],
-        comparator: interfaces.PropComparator[_T],
+        comparator: interfaces.PropComparator[_T_co],
         impl: Optional[AttributeImpl] = None,
         of_type: Optional[_InternalEntityType[Any]] = None,
         extra_criteria: Tuple[ColumnElement[bool], ...] = (),
@@ -314,7 +315,7 @@ class QueryableAttribute(
 
     """
 
-    expression: ColumnElement[_T]
+    expression: ColumnElement[_T_co]
     """The SQL expression object represented by this
     :class:`.QueryableAttribute`.
 
@@ -376,7 +377,7 @@ class QueryableAttribute(
     def _annotations(self) -> _AnnotationDict:
         return self.__clause_element__()._annotations
 
-    def __clause_element__(self) -> ColumnElement[_T]:
+    def __clause_element__(self) -> ColumnElement[_T_co]:
         return self.expression
 
     @property
@@ -443,7 +444,7 @@ class QueryableAttribute(
             extra_criteria=self._extra_criteria,
         )
 
-    def label(self, name: Optional[str]) -> Label[_T]:
+    def label(self, name: Optional[str]) -> Label[_T_co]:
         return self.__clause_element__().label(name)
 
     def operate(
diff --git a/lib/sqlalchemy/orm/base.py b/lib/sqlalchemy/orm/base.py
index ecb10591a..362346cc2 100644
--- a/lib/sqlalchemy/orm/base.py
+++ b/lib/sqlalchemy/orm/base.py
@@ -56,6 +56,7 @@ if typing.TYPE_CHECKING:
     from ..sql.operators import OperatorType
 
 _T = TypeVar("_T", bound=Any)
+_T_co = TypeVar("_T_co", bound=Any, covariant=True)
 
 _O = TypeVar("_O", bound=object)
 
@@ -678,12 +679,12 @@ class InspectionAttrInfo(InspectionAttr):
         return {}
 
 
-class SQLORMOperations(SQLCoreOperations[_T], TypingOnly):
+class SQLORMOperations(SQLCoreOperations[_T_co], TypingOnly):
     __slots__ = ()
 
     if typing.TYPE_CHECKING:
 
-        def of_type(self, class_: _EntityType[Any]) -> PropComparator[_T]:
+        def of_type(self, class_: _EntityType[Any]) -> PropComparator[_T_co]:
             ...
 
         def and_(
@@ -706,7 +707,7 @@ class SQLORMOperations(SQLCoreOperations[_T], TypingOnly):
             ...
 
 
-class ORMDescriptor(Generic[_T], TypingOnly):
+class ORMDescriptor(Generic[_T_co], TypingOnly):
     """Represent any Python descriptor that provides a SQL expression
     construct at the class level."""
 
@@ -717,26 +718,26 @@ class ORMDescriptor(Generic[_T], TypingOnly):
         @overload
         def __get__(
             self, instance: Any, owner: Literal[None]
-        ) -> ORMDescriptor[_T]:
+        ) -> ORMDescriptor[_T_co]:
             ...
 
         @overload
         def __get__(
             self, instance: Literal[None], owner: Any
-        ) -> SQLCoreOperations[_T]:
+        ) -> SQLCoreOperations[_T_co]:
             ...
 
         @overload
-        def __get__(self, instance: object, owner: Any) -> _T:
+        def __get__(self, instance: object, owner: Any) -> _T_co:
             ...
 
         def __get__(
             self, instance: object, owner: Any
-        ) -> Union[ORMDescriptor[_T], SQLCoreOperations[_T], _T]:
+        ) -> Union[ORMDescriptor[_T_co], SQLCoreOperations[_T_co], _T_co]:
             ...
 
 
-class _MappedAnnotationBase(Generic[_T], TypingOnly):
+class _MappedAnnotationBase(Generic[_T_co], TypingOnly):
     """common class for Mapped and similar ORM container classes.
 
     these are classes that can appear on the left side of an ORM declarative
@@ -749,7 +750,7 @@ class _MappedAnnotationBase(Generic[_T], TypingOnly):
 
 
 class SQLORMExpression(
-    SQLORMOperations[_T], SQLColumnExpression[_T], TypingOnly
+    SQLORMOperations[_T_co], SQLColumnExpression[_T_co], TypingOnly
 ):
     """A type that may be used to indicate any ORM-level attribute or
     object that acts in place of one, in the context of SQL expression
@@ -771,9 +772,9 @@ class SQLORMExpression(
 
 
 class Mapped(
-    SQLORMExpression[_T],
-    ORMDescriptor[_T],
-    _MappedAnnotationBase[_T],
+    SQLORMExpression[_T_co],
+    ORMDescriptor[_T_co],
+    _MappedAnnotationBase[_T_co],
     roles.DDLConstraintColumnRole,
 ):
     """Represent an ORM mapped attribute on a mapped class.
@@ -819,24 +820,24 @@ class Mapped(
         @overload
         def __get__(
             self, instance: None, owner: Any
-        ) -> InstrumentedAttribute[_T]:
+        ) -> InstrumentedAttribute[_T_co]:
             ...
 
         @overload
-        def __get__(self, instance: object, owner: Any) -> _T:
+        def __get__(self, instance: object, owner: Any) -> _T_co:
             ...
 
         def __get__(
             self, instance: Optional[object], owner: Any
-        ) -> Union[InstrumentedAttribute[_T], _T]:
+        ) -> Union[InstrumentedAttribute[_T_co], _T_co]:
             ...
 
         @classmethod
-        def _empty_constructor(cls, arg1: Any) -> Mapped[_T]:
+        def _empty_constructor(cls, arg1: Any) -> Mapped[_T_co]:
             ...
 
         def __set__(
-            self, instance: Any, value: Union[SQLCoreOperations[_T], _T]
+            self, instance: Any, value: Union[SQLCoreOperations[_T_co], _T_co]
         ) -> None:
             ...
 
@@ -844,7 +845,7 @@ class Mapped(
             ...
 
 
-class _MappedAttribute(Generic[_T], TypingOnly):
+class _MappedAttribute(Generic[_T_co], TypingOnly):
     """Mixin for attributes which should be replaced by mapper-assigned
     attributes.
 
@@ -853,7 +854,7 @@ class _MappedAttribute(Generic[_T], TypingOnly):
     __slots__ = ()
 
 
-class _DeclarativeMapped(Mapped[_T], _MappedAttribute[_T]):
+class _DeclarativeMapped(Mapped[_T_co], _MappedAttribute[_T_co]):
     """Mixin for :class:`.MapperProperty` subclasses that allows them to
     be compatible with ORM-annotated declarative mappings.
 
@@ -878,7 +879,7 @@ class _DeclarativeMapped(Mapped[_T], _MappedAttribute[_T]):
         return NotImplemented
 
 
-class DynamicMapped(_MappedAnnotationBase[_T]):
+class DynamicMapped(_MappedAnnotationBase[_T_co]):
     """Represent the ORM mapped attribute type for a "dynamic" relationship.
 
     The :class:`_orm.DynamicMapped` type annotation may be used in an
@@ -918,23 +919,27 @@ class DynamicMapped(_MappedAnnotationBase[_T]):
         @overload
         def __get__(
             self, instance: None, owner: Any
-        ) -> InstrumentedAttribute[_T]:
+        ) -> InstrumentedAttribute[_T_co]:
             ...
 
         @overload
-        def __get__(self, instance: object, owner: Any) -> AppenderQuery[_T]:
+        def __get__(
+            self, instance: object, owner: Any
+        ) -> AppenderQuery[_T_co]:
             ...
 
         def __get__(
             self, instance: Optional[object], owner: Any
-        ) -> Union[InstrumentedAttribute[_T], AppenderQuery[_T]]:
+        ) -> Union[InstrumentedAttribute[_T_co], AppenderQuery[_T_co]]:
             ...
 
-        def __set__(self, instance: Any, value: typing.Collection[_T]) -> None:
+        def __set__(
+            self, instance: Any, value: typing.Collection[_T_co]
+        ) -> None:
             ...
 
 
-class WriteOnlyMapped(_MappedAnnotationBase[_T]):
+class WriteOnlyMapped(_MappedAnnotationBase[_T_co]):
     """Represent the ORM mapped attribute type for a "write only" relationship.
 
     The :class:`_orm.WriteOnlyMapped` type annotation may be used in an
@@ -970,19 +975,21 @@ class WriteOnlyMapped(_MappedAnnotationBase[_T]):
         @overload
         def __get__(
             self, instance: None, owner: Any
-        ) -> InstrumentedAttribute[_T]:
+        ) -> InstrumentedAttribute[_T_co]:
             ...
 
         @overload
         def __get__(
             self, instance: object, owner: Any
-        ) -> WriteOnlyCollection[_T]:
+        ) -> WriteOnlyCollection[_T_co]:
             ...
 
         def __get__(
             self, instance: Optional[object], owner: Any
-        ) -> Union[InstrumentedAttribute[_T], WriteOnlyCollection[_T]]:
+        ) -> Union[InstrumentedAttribute[_T_co], WriteOnlyCollection[_T_co]]:
             ...
 
-        def __set__(self, instance: Any, value: typing.Collection[_T]) -> None:
+        def __set__(
+            self, instance: Any, value: typing.Collection[_T_co]
+        ) -> None:
             ...
diff --git a/lib/sqlalchemy/orm/interfaces.py b/lib/sqlalchemy/orm/interfaces.py
index 88cafcb64..daba973cb 100644
--- a/lib/sqlalchemy/orm/interfaces.py
+++ b/lib/sqlalchemy/orm/interfaces.py
@@ -107,6 +107,7 @@ if typing.TYPE_CHECKING:
 _StrategyKey = Tuple[Any, ...]
 
 _T = TypeVar("_T", bound=Any)
+_T_co = TypeVar("_T_co", bound=Any, covariant=True)
 
 _TLS = TypeVar("_TLS", bound="Type[LoaderStrategy]")
 
@@ -653,7 +654,7 @@ class MapperProperty(
 
 
 @inspection._self_inspects
-class PropComparator(SQLORMOperations[_T], Generic[_T], ColumnOperators):
+class PropComparator(SQLORMOperations[_T_co], Generic[_T_co], ColumnOperators):
     r"""Defines SQL operations for ORM mapped attributes.
 
     SQLAlchemy allows for operators to
@@ -740,7 +741,7 @@ class PropComparator(SQLORMOperations[_T], Generic[_T], ColumnOperators):
 
     _parententity: _InternalEntityType[Any]
     _adapt_to_entity: Optional[AliasedInsp[Any]]
-    prop: RODescriptorReference[MapperProperty[_T]]
+    prop: RODescriptorReference[MapperProperty[_T_co]]
 
     def __init__(
         self,
diff --git a/lib/sqlalchemy/orm/mapper.py b/lib/sqlalchemy/orm/mapper.py
index e78830e5b..06671a5e1 100644
--- a/lib/sqlalchemy/orm/mapper.py
+++ b/lib/sqlalchemy/orm/mapper.py
@@ -4097,7 +4097,7 @@ class _OptGetColumnsNotAvailable(Exception):
     pass
 
 
-def configure_mappers():
+def configure_mappers() -> None:
     """Initialize the inter-mapper relationships of all mappers that
     have been constructed thus far across all :class:`_orm.registry`
     collections.
diff --git a/lib/sqlalchemy/sql/elements.py b/lib/sqlalchemy/sql/elements.py
index a6b4c8ab1..3917b5f02 100644
--- a/lib/sqlalchemy/sql/elements.py
+++ b/lib/sqlalchemy/sql/elements.py
@@ -117,6 +117,7 @@ _NUMERIC = Union[float, Decimal]
 _NUMBER = Union[float, int, Decimal]
 
 _T = TypeVar("_T", bound="Any")
+_T_co = TypeVar("_T_co", bound=Any, covariant=True)
 _OPT = TypeVar("_OPT", bound="Any")
 _NT = TypeVar("_NT", bound="_NUMERIC")
 
@@ -804,7 +805,7 @@ class CompilerColumnElement(
 # SQLCoreOperations should be suiting the ExpressionElementRole
 # and ColumnsClauseRole.   however the MRO issues become too elaborate
 # at the moment.
-class SQLCoreOperations(Generic[_T], ColumnOperators, TypingOnly):
+class SQLCoreOperations(Generic[_T_co], ColumnOperators, TypingOnly):
     __slots__ = ()
 
     # annotations for comparison methods
@@ -873,7 +874,7 @@ class SQLCoreOperations(Generic[_T], ColumnOperators, TypingOnly):
         def __or__(self, other: Any) -> BooleanClauseList:
             ...
 
-        def __invert__(self) -> ColumnElement[_T]:
+        def __invert__(self) -> ColumnElement[_T_co]:
             ...
 
         def __lt__(self, other: Any) -> ColumnElement[bool]:
@@ -900,7 +901,7 @@ class SQLCoreOperations(Generic[_T], ColumnOperators, TypingOnly):
         def __ge__(self, other: Any) -> ColumnElement[bool]:
             ...
 
-        def __neg__(self) -> UnaryExpression[_T]:
+        def __neg__(self) -> UnaryExpression[_T_co]:
             ...
 
         def __contains__(self, other: Any) -> ColumnElement[bool]:
@@ -961,7 +962,7 @@ class SQLCoreOperations(Generic[_T], ColumnOperators, TypingOnly):
         def bitwise_and(self, other: Any) -> BinaryExpression[Any]:
             ...
 
-        def bitwise_not(self) -> UnaryExpression[_T]:
+        def bitwise_not(self) -> UnaryExpression[_T_co]:
             ...
 
         def bitwise_lshift(self, other: Any) -> BinaryExpression[Any]:
@@ -1074,22 +1075,22 @@ class SQLCoreOperations(Generic[_T], ColumnOperators, TypingOnly):
         ) -> ColumnElement[str]:
             ...
 
-        def desc(self) -> UnaryExpression[_T]:
+        def desc(self) -> UnaryExpression[_T_co]:
             ...
 
-        def asc(self) -> UnaryExpression[_T]:
+        def asc(self) -> UnaryExpression[_T_co]:
             ...
 
-        def nulls_first(self) -> UnaryExpression[_T]:
+        def nulls_first(self) -> UnaryExpression[_T_co]:
             ...
 
-        def nullsfirst(self) -> UnaryExpression[_T]:
+        def nullsfirst(self) -> UnaryExpression[_T_co]:
             ...
 
-        def nulls_last(self) -> UnaryExpression[_T]:
+        def nulls_last(self) -> UnaryExpression[_T_co]:
             ...
 
-        def nullslast(self) -> UnaryExpression[_T]:
+        def nullslast(self) -> UnaryExpression[_T_co]:
             ...
 
         def collate(self, collation: str) -> CollationClause:
@@ -1100,7 +1101,7 @@ class SQLCoreOperations(Generic[_T], ColumnOperators, TypingOnly):
         ) -> BinaryExpression[bool]:
             ...
 
-        def distinct(self: _SQO[_T]) -> UnaryExpression[_T]:
+        def distinct(self: _SQO[_T_co]) -> UnaryExpression[_T_co]:
             ...
 
         def any_(self) -> CollectionAggregate[Any]:
@@ -1128,19 +1129,11 @@ class SQLCoreOperations(Generic[_T], ColumnOperators, TypingOnly):
         ) -> ColumnElement[str]:
             ...
 
-        @overload
-        def __add__(self, other: Any) -> ColumnElement[Any]:
-            ...
-
         def __add__(self, other: Any) -> ColumnElement[Any]:
             ...
 
         @overload
-        def __radd__(self: _SQO[_NT], other: Any) -> ColumnElement[_NT]:
-            ...
-
-        @overload
-        def __radd__(self: _SQO[int], other: Any) -> ColumnElement[int]:
+        def __radd__(self: _SQO[_NMT], other: Any) -> ColumnElement[_NMT]:
             ...
 
         @overload
@@ -1282,7 +1275,7 @@ class SQLCoreOperations(Generic[_T], ColumnOperators, TypingOnly):
 
 
 class SQLColumnExpression(
-    SQLCoreOperations[_T], roles.ExpressionElementRole[_T], TypingOnly
+    SQLCoreOperations[_T_co], roles.ExpressionElementRole[_T_co], TypingOnly
 ):
     """A type that may be used to indicate any SQL column element or object
     that acts in place of one.
diff --git a/lib/sqlalchemy/sql/roles.py b/lib/sqlalchemy/sql/roles.py
index f8aac70b9..6f2992243 100644
--- a/lib/sqlalchemy/sql/roles.py
+++ b/lib/sqlalchemy/sql/roles.py
@@ -23,6 +23,7 @@ if TYPE_CHECKING:
     from .selectable import Subquery
 
 _T = TypeVar("_T", bound=Any)
+_T_co = TypeVar("_T_co", bound=Any, covariant=True)
 
 
 class SQLRole:
@@ -110,7 +111,7 @@ class ColumnsClauseRole(AllowsLambdaRole, UsesInspection, ColumnListRole):
         raise NotImplementedError()
 
 
-class TypedColumnsClauseRole(Generic[_T], SQLRole):
+class TypedColumnsClauseRole(Generic[_T_co], SQLRole):
     """element-typed form of ColumnsClauseRole"""
 
     __slots__ = ()
@@ -162,7 +163,7 @@ class WhereHavingRole(OnClauseRole):
     _role_name = "SQL expression for WHERE/HAVING role"
 
 
-class ExpressionElementRole(TypedColumnsClauseRole[_T]):
+class ExpressionElementRole(TypedColumnsClauseRole[_T_co]):
     # note when using generics for ExpressionElementRole,
     # the generic type needs to be in
     # sqlalchemy.sql.coercions._impl_lookup mapping also.
diff --git a/lib/sqlalchemy/sql/selectable.py b/lib/sqlalchemy/sql/selectable.py
index b13c53249..71fca7e1f 100644
--- a/lib/sqlalchemy/sql/selectable.py
+++ b/lib/sqlalchemy/sql/selectable.py
@@ -3169,6 +3169,7 @@ class Values(roles.InElementRole, Generative, LateralFromClause):
     ):
         super().__init__()
         self._column_args = columns
+
         if name is None:
             self._unnamed = True
             self.name = _anonymous_label.safe_construct(id(self), "anon")
@@ -3262,6 +3263,13 @@ class Values(roles.InElementRole, Generative, LateralFromClause):
 
     def _populate_column_collection(self) -> None:
         for c in self._column_args:
+            if c.table is not None and c.table is not self:
+                _, c = c._make_proxy(self)
+            else:
+                # if the column was used in other contexts, ensure
+                # no memoizations of other FROM clauses.
+                # see test_values.py -> test_auto_proxy_select_direct_col
+                c._reset_memoizations()
             self._columns.add(c)
             c.table = self
 


Test patch:
diff --git a/.github/workflows/run-test.yaml b/.github/workflows/run-test.yaml
index 9de4a3ec2..f48470308 100644
--- a/.github/workflows/run-test.yaml
+++ b/.github/workflows/run-test.yaml
@@ -73,7 +73,7 @@ jobs:
     # steps to run in each job. Some are github actions, others run shell commands
     steps:
       - name: Checkout repo
-        uses: actions/checkout@v3
+        uses: actions/checkout@v4
 
       - name: Set up python
         uses: actions/setup-python@v4
@@ -116,7 +116,7 @@ jobs:
 
     steps:
       - name: Checkout repo
-        uses: actions/checkout@v3
+        uses: actions/checkout@v4
 
       - name: Set up emulation
         run: |
@@ -172,7 +172,7 @@ jobs:
     # steps to run in each job. Some are github actions, others run shell commands
     steps:
       - name: Checkout repo
-        uses: actions/checkout@v3
+        uses: actions/checkout@v4
 
       - name: Set up python
         uses: actions/setup-python@v4
diff --git a/test/dialect/oracle/test_reflection.py b/test/dialect/oracle/test_reflection.py
index 35af2f573..2a82c25d9 100644
--- a/test/dialect/oracle/test_reflection.py
+++ b/test/dialect/oracle/test_reflection.py
@@ -618,32 +618,25 @@ class DontReflectIOTTest(fixtures.TestBase):
         eq_({t.name for t in m.tables.values()}, {"admin_docindex"})
 
 
-def all_tables_compression_missing():
-    with testing.db.connect() as conn:
-        if (
-            "Enterprise Edition"
-            not in conn.exec_driver_sql("select * from v$version").scalar()
-            # this works in Oracle Database 18c Express Edition Release
-        ) and testing.db.dialect.server_version_info < (18,):
+def enterprise_edition_or_version(version):
+    def check():
+        if testing.db.dialect.server_version_info < (version,):
+            with testing.db.connect() as conn:
+                return (
+                    "Enterprise Edition"
+                    in conn.exec_driver_sql("select * from v$version").scalar()
+                )
+        else:
             return True
-        return False
-
 
-def all_tables_compress_for_missing():
-    with testing.db.connect() as conn:
-        if (
-            "Enterprise Edition"
-            not in conn.exec_driver_sql("select * from v$version").scalar()
-        ):
-            return True
-        return False
+    return check
 
 
 class TableReflectionTest(fixtures.TestBase):
     __only_on__ = "oracle"
     __backend__ = True
 
-    @testing.fails_if(all_tables_compression_missing)
+    @testing.only_on(enterprise_edition_or_version(18))
     def test_reflect_basic_compression(self, metadata, connection):
         tbl = Table(
             "test_compress",
@@ -659,7 +652,7 @@ class TableReflectionTest(fixtures.TestBase):
         # Don't hardcode the exact value, but it must be non-empty
         assert tbl.dialect_options["oracle"]["compress"]
 
-    @testing.fails_if(all_tables_compress_for_missing)
+    @testing.only_on(enterprise_edition_or_version(19))
     def test_reflect_oltp_compression(self, metadata, connection):
         tbl = Table(
             "test_compress",
@@ -672,7 +665,10 @@ class TableReflectionTest(fixtures.TestBase):
         m2 = MetaData()
 
         tbl = Table("test_compress", m2, autoload_with=connection)
-        assert tbl.dialect_options["oracle"]["compress"] == "OLTP"
+        assert tbl.dialect_options["oracle"]["compress"] in (
+            "OLTP",
+            "ADVANCED",
+        )
 
     def test_reflect_hidden_column(self):
         with testing.db.begin() as conn:
diff --git a/test/orm/dml/test_update_delete_where.py b/test/orm/dml/test_update_delete_where.py
index 9efb82a1d..03468972d 100644
--- a/test/orm/dml/test_update_delete_where.py
+++ b/test/orm/dml/test_update_delete_where.py
@@ -1116,7 +1116,7 @@ class UpdateDeleteTest(fixtures.MappedTest):
         )
 
         result = sess.execute(stmt)
-        eq_(result.all(), [(2, "jack", 37), (4, "jane", 27)])
+        eq_(set(result), {(2, "jack", 37), (4, "jane", 27)})
 
         eq_([john.age, jack.age, jill.age, jane.age], [25, 37, 29, 27])
         eq_(
diff --git a/test/sql/test_values.py b/test/sql/test_values.py
index 62e1f1cb5..7f0c8a74a 100644
--- a/test/sql/test_values.py
+++ b/test/sql/test_values.py
@@ -7,8 +7,10 @@ from sqlalchemy import ForeignKey
 from sqlalchemy import Integer
 from sqlalchemy import String
 from sqlalchemy import Table
+from sqlalchemy import table
 from sqlalchemy import testing
 from sqlalchemy import true
+from sqlalchemy import values
 from sqlalchemy.engine import default
 from sqlalchemy.sql import func
 from sqlalchemy.sql import select
@@ -17,6 +19,8 @@ from sqlalchemy.sql.compiler import FROM_LINTING
 from sqlalchemy.testing import AssertsCompiledSQL
 from sqlalchemy.testing import expect_raises_message
 from sqlalchemy.testing import fixtures
+from sqlalchemy.testing import is_
+from sqlalchemy.testing import is_not
 from sqlalchemy.util import OrderedDict
 
 
@@ -70,6 +74,95 @@ class ValuesTest(fixtures.TablesTest, AssertsCompiledSQL):
         ):
             str(v1)
 
+    @testing.fixture
+    def _auto_proxy_fixture(self):
+        c1 = column("q", Integer)
+        c2 = column("p", Integer)
+        t = table("t", c1)  # noqa: F841
+
+        v1 = values(c1, c2).data([(1, 2), (3, 4)])
+
+        return c1, c2, t, v1
+
+    def test_auto_proxy_col_ownership(self, _auto_proxy_fixture):
+        """test #10280"""
+
+        c1, c2, t, v1 = _auto_proxy_fixture
+
+        is_(c2, v1.c.p)
+        is_not(c1, v1.c.q)
+
+    def test_auto_proxy_select_c_col(self, _auto_proxy_fixture):
+        """test #10280"""
+
+        c1, c2, t, v1 = _auto_proxy_fixture
+        self.assert_compile(select(t.c.q), "SELECT t.q FROM t")
+        self.assert_compile(
+            select(v1.c.q),
+            "SELECT q FROM (VALUES (:param_1, :param_2), "
+            "(:param_3, :param_4))",
+            checkparams={
+                "param_1": 1,
+                "param_2": 2,
+                "param_3": 3,
+                "param_4": 4,
+            },
+        )
+
+    def test_auto_proxy_select_direct_col(self, _auto_proxy_fixture):
+        """test #10280"""
+
+        c1, c2, t, v1 = _auto_proxy_fixture
+        self.assert_compile(select(c1), "SELECT t.q FROM t")
+
+        # for VALUES, the column does not have its set_parent called up front.
+        # this is to make the construction of values() faster, as the values.c
+        # use case is not required in order to use the construct
+        self.assert_compile(select(c2), "SELECT p")
+
+        # once we call v.c, then it's set up.
+        # patch for #10280 added an extra step to make sure this works
+        # even after the previous compile is called.
+        # is this how it should work?  not sure, just testing how it is
+        # right now
+        v1.c.p
+
+        self.assert_compile(
+            select(c2),
+            "SELECT p FROM (VALUES (:param_1, :param_2), "
+            "(:param_3, :param_4))",
+            checkparams={
+                "param_1": 1,
+                "param_2": 2,
+                "param_3": 3,
+                "param_4": 4,
+            },
+        )
+
+    def test_auto_proxy_make_new_values(self, _auto_proxy_fixture):
+        """test #10280"""
+
+        c1, c2, t, v1 = _auto_proxy_fixture
+
+        self.assert_compile(
+            select(v1.c.p),
+            "SELECT p FROM (VALUES (:param_1, :param_2), "
+            "(:param_3, :param_4))",
+            checkparams={
+                "param_1": 1,
+                "param_2": 2,
+                "param_3": 3,
+                "param_4": 4,
+            },
+        )
+
+        v2 = values(c1, c2).data([(5, 6)])
+        self.assert_compile(
+            select(v2.c.p),
+            "SELECT p FROM (VALUES (:param_1, :param_2))",
+            checkparams={"param_1": 5, "param_2": 6},
+        )
+
     def test_column_quoting(self):
         v1 = Values(
             column("CaseSensitive", Integer),
diff --git a/test/typing/plain_files/orm/mapped_covariant.py b/test/typing/plain_files/orm/mapped_covariant.py
new file mode 100644
index 000000000..58cc1ab6c
--- /dev/null
+++ b/test/typing/plain_files/orm/mapped_covariant.py
@@ -0,0 +1,53 @@
+"""Tests Mapped covariance."""
+
+from typing import Protocol
+
+from sqlalchemy import ForeignKey
+from sqlalchemy.orm import DeclarativeBase
+from sqlalchemy.orm import Mapped
+from sqlalchemy.orm import mapped_column
+from sqlalchemy.orm import relationship
+
+
+# Protocols
+
+
+class ParentProtocol(Protocol):
+    name: Mapped[str]
+
+
+class ChildProtocol(Protocol):
+    # Read-only for simplicity, mutable protocol members are complicated,
+    # see https://mypy.readthedocs.io/en/latest/common_issues.html#covariant-subtyping-of-mutable-protocol-members-is-rejected
+    @property
+    def parent(self) -> Mapped[ParentProtocol]:
+        ...
+
+
+def get_parent_name(child: ChildProtocol) -> str:
+    return child.parent.name
+
+
+# Implementations
+
+
+class Base(DeclarativeBase):
+    pass
+
+
+class Parent(Base):
+    __tablename__ = "parent"
+
+    name: Mapped[str] = mapped_column(primary_key=True)
+
+
+class Child(Base):
+    __tablename__ = "child"
+
+    name: Mapped[str] = mapped_column(primary_key=True)
+    parent_name: Mapped[str] = mapped_column(ForeignKey(Parent.name))
+
+    parent: Mapped[Parent] = relationship()
+
+
+assert get_parent_name(Child(parent=Parent(name="foo"))) == "foo"