@@ -215,7 +215,7 @@ same also applies to enum classes with members, which are implicitly final:
215215
216216``` toml
217217[environment ]
218- python-version = " 3.10 "
218+ python-version = " 3.12 "
219219```
220220
221221``` py
@@ -235,3 +235,170 @@ def _(x: type[Foo], y: type[EllipsisType], z: type[Answer]):
235235 reveal_type(y) # revealed: <class 'EllipsisType'>
236236 reveal_type(z) # revealed: <class 'Answer'>
237237```
238+
239+ ## Subtyping ` @final ` classes
240+
241+ ``` toml
242+ [environment ]
243+ python-version = " 3.12"
244+ ```
245+
246+ ``` py
247+ from typing import final, Any
248+ from ty_extensions import is_assignable_to, is_subtype_of, is_disjoint_from, static_assert
249+
250+ class Biv[T]: ...
251+
252+ class Cov[T]:
253+ def pop (self ) -> T:
254+ raise NotImplementedError
255+
256+ class Contra[T]:
257+ def push (self , value : T) -> None :
258+ pass
259+
260+ class Inv[T]:
261+ x: T
262+
263+ @final
264+ class BivSub[T](Biv[T]): ...
265+
266+ @final
267+ class CovSub[T](Cov[T]): ...
268+
269+ @final
270+ class ContraSub[T](Contra[T]): ...
271+
272+ @final
273+ class InvSub[T](Inv[T]): ...
274+
275+ def _[T, U]():
276+ static_assert(is_subtype_of(type[BivSub[T]], type[BivSub[U]]))
277+ static_assert(not is_disjoint_from(type[BivSub[U]], type[BivSub[T]]))
278+
279+ static_assert(not is_subtype_of(type[CovSub[T]], type[CovSub[U]]))
280+ static_assert(not is_disjoint_from(type[CovSub[U]], type[CovSub[T]]))
281+
282+ static_assert(not is_subtype_of(type[ContraSub[T]], type[ContraSub[U]]))
283+ static_assert(not is_disjoint_from(type[ContraSub[U]], type[ContraSub[T]]))
284+
285+ static_assert(not is_subtype_of(type[InvSub[T]], type[InvSub[U]]))
286+ static_assert(not is_disjoint_from(type[InvSub[U]], type[InvSub[T]]))
287+
288+ def _ ():
289+ static_assert(is_subtype_of(type[BivSub[bool ]], type[BivSub[int ]]))
290+ static_assert(is_subtype_of(type[BivSub[int ]], type[BivSub[bool ]]))
291+ static_assert(is_disjoint_from(type[BivSub[int ]], type[BivSub[str ]]))
292+ static_assert(not is_disjoint_from(type[BivSub[bool ]], type[BivSub[int ]]))
293+
294+ static_assert(is_subtype_of(type[CovSub[bool ]], type[CovSub[int ]]))
295+ static_assert(not is_subtype_of(type[CovSub[int ]], type[CovSub[bool ]]))
296+ static_assert(is_disjoint_from(type[CovSub[int ]], type[CovSub[str ]]))
297+ static_assert(not is_disjoint_from(type[CovSub[bool ]], type[CovSub[int ]]))
298+
299+ static_assert(not is_subtype_of(type[ContraSub[bool ]], type[ContraSub[int ]]))
300+ static_assert(is_subtype_of(type[ContraSub[int ]], type[ContraSub[bool ]]))
301+ static_assert(is_disjoint_from(type[ContraSub[int ]], type[ContraSub[str ]]))
302+ static_assert(not is_disjoint_from(type[ContraSub[bool ]], type[ContraSub[int ]]))
303+
304+ static_assert(not is_subtype_of(type[InvSub[bool ]], type[InvSub[int ]]))
305+ static_assert(not is_subtype_of(type[InvSub[int ]], type[InvSub[bool ]]))
306+ static_assert(is_disjoint_from(type[InvSub[int ]], type[InvSub[str ]]))
307+ static_assert(not is_disjoint_from(type[InvSub[bool ]], type[InvSub[int ]]))
308+
309+ def _[T]():
310+ static_assert(is_subtype_of(type[BivSub[T]], type[BivSub[Any]]))
311+ static_assert(is_subtype_of(type[BivSub[Any]], type[BivSub[T]]))
312+ static_assert(is_assignable_to(type[BivSub[T]], type[BivSub[Any]]))
313+ static_assert(is_assignable_to(type[BivSub[Any]], type[BivSub[T]]))
314+ static_assert(not is_disjoint_from(type[BivSub[T]], type[BivSub[Any]]))
315+
316+ static_assert(not is_subtype_of(type[CovSub[T]], type[CovSub[Any]]))
317+ static_assert(not is_subtype_of(type[CovSub[Any]], type[CovSub[T]]))
318+ static_assert(is_assignable_to(type[CovSub[T]], type[CovSub[Any]]))
319+ static_assert(is_assignable_to(type[CovSub[Any]], type[CovSub[T]]))
320+ static_assert(not is_disjoint_from(type[CovSub[T]], type[CovSub[Any]]))
321+
322+ static_assert(not is_subtype_of(type[ContraSub[T]], type[ContraSub[Any]]))
323+ static_assert(not is_subtype_of(type[ContraSub[Any]], type[ContraSub[T]]))
324+ static_assert(is_assignable_to(type[ContraSub[T]], type[ContraSub[Any]]))
325+ static_assert(is_assignable_to(type[ContraSub[Any]], type[ContraSub[T]]))
326+ static_assert(not is_disjoint_from(type[ContraSub[T]], type[ContraSub[Any]]))
327+
328+ static_assert(not is_subtype_of(type[InvSub[T]], type[InvSub[Any]]))
329+ static_assert(not is_subtype_of(type[InvSub[Any]], type[InvSub[T]]))
330+ static_assert(is_assignable_to(type[InvSub[T]], type[InvSub[Any]]))
331+ static_assert(is_assignable_to(type[InvSub[Any]], type[InvSub[T]]))
332+ static_assert(not is_disjoint_from(type[InvSub[T]], type[InvSub[Any]]))
333+
334+ def _[T, U]():
335+ static_assert(is_subtype_of(type[BivSub[T]], type[Biv[T]]))
336+ static_assert(not is_subtype_of(type[Biv[T]], type[BivSub[T]]))
337+ static_assert(not is_disjoint_from(type[BivSub[T]], type[Biv[T]]))
338+ static_assert(not is_disjoint_from(type[BivSub[U]], type[Biv[T]]))
339+ static_assert(not is_disjoint_from(type[BivSub[U]], type[Biv[U]]))
340+
341+ static_assert(is_subtype_of(type[CovSub[T]], type[Cov[T]]))
342+ static_assert(not is_subtype_of(type[Cov[T]], type[CovSub[T]]))
343+ static_assert(not is_disjoint_from(type[CovSub[T]], type[Cov[T]]))
344+ static_assert(not is_disjoint_from(type[CovSub[U]], type[Cov[T]]))
345+ static_assert(not is_disjoint_from(type[CovSub[U]], type[Cov[U]]))
346+
347+ static_assert(is_subtype_of(type[ContraSub[T]], type[Contra[T]]))
348+ static_assert(not is_subtype_of(type[Contra[T]], type[ContraSub[T]]))
349+ static_assert(not is_disjoint_from(type[ContraSub[T]], type[Contra[T]]))
350+ static_assert(not is_disjoint_from(type[ContraSub[U]], type[Contra[T]]))
351+ static_assert(not is_disjoint_from(type[ContraSub[U]], type[Contra[U]]))
352+
353+ static_assert(is_subtype_of(type[InvSub[T]], type[Inv[T]]))
354+ static_assert(not is_subtype_of(type[Inv[T]], type[InvSub[T]]))
355+ static_assert(not is_disjoint_from(type[InvSub[T]], type[Inv[T]]))
356+ static_assert(not is_disjoint_from(type[InvSub[U]], type[Inv[T]]))
357+ static_assert(not is_disjoint_from(type[InvSub[U]], type[Inv[U]]))
358+
359+ def _ ():
360+ static_assert(is_subtype_of(type[BivSub[bool ]], type[Biv[int ]]))
361+ static_assert(is_subtype_of(type[BivSub[int ]], type[Biv[bool ]]))
362+ static_assert(not is_disjoint_from(type[BivSub[bool ]], type[Biv[int ]]))
363+ static_assert(not is_disjoint_from(type[BivSub[int ]], type[Biv[bool ]]))
364+
365+ static_assert(is_subtype_of(type[CovSub[bool ]], type[Cov[int ]]))
366+ static_assert(not is_subtype_of(type[CovSub[int ]], type[Cov[bool ]]))
367+ static_assert(not is_disjoint_from(type[CovSub[bool ]], type[Cov[int ]]))
368+ static_assert(not is_disjoint_from(type[CovSub[int ]], type[Cov[bool ]]))
369+
370+ static_assert(not is_subtype_of(type[ContraSub[bool ]], type[Contra[int ]]))
371+ static_assert(is_subtype_of(type[ContraSub[int ]], type[Contra[bool ]]))
372+ static_assert(not is_disjoint_from(type[ContraSub[int ]], type[Contra[bool ]]))
373+ static_assert(not is_disjoint_from(type[ContraSub[bool ]], type[Contra[int ]]))
374+
375+ static_assert(not is_subtype_of(type[InvSub[bool ]], type[Inv[int ]]))
376+ static_assert(not is_subtype_of(type[InvSub[int ]], type[Inv[bool ]]))
377+ static_assert(not is_disjoint_from(type[InvSub[bool ]], type[Inv[int ]]))
378+ static_assert(not is_disjoint_from(type[InvSub[int ]], type[Inv[bool ]]))
379+
380+ def _[T]():
381+ static_assert(is_subtype_of(type[BivSub[T]], type[Biv[Any]]))
382+ static_assert(is_subtype_of(type[BivSub[Any]], type[Biv[T]]))
383+ static_assert(is_assignable_to(type[BivSub[T]], type[Biv[Any]]))
384+ static_assert(is_assignable_to(type[BivSub[Any]], type[Biv[T]]))
385+ static_assert(not is_disjoint_from(type[BivSub[T]], type[Biv[Any]]))
386+
387+ static_assert(not is_subtype_of(type[CovSub[T]], type[Cov[Any]]))
388+ static_assert(not is_subtype_of(type[CovSub[Any]], type[Cov[T]]))
389+ static_assert(is_assignable_to(type[CovSub[T]], type[Cov[Any]]))
390+ static_assert(is_assignable_to(type[CovSub[Any]], type[Cov[T]]))
391+ static_assert(not is_disjoint_from(type[CovSub[T]], type[Cov[Any]]))
392+
393+ static_assert(not is_subtype_of(type[ContraSub[T]], type[Contra[Any]]))
394+ static_assert(not is_subtype_of(type[ContraSub[Any]], type[Contra[T]]))
395+ static_assert(is_assignable_to(type[ContraSub[T]], type[Contra[Any]]))
396+ static_assert(is_assignable_to(type[ContraSub[Any]], type[Contra[T]]))
397+ static_assert(not is_disjoint_from(type[ContraSub[T]], type[Contra[Any]]))
398+
399+ static_assert(not is_subtype_of(type[InvSub[T]], type[Inv[Any]]))
400+ static_assert(not is_subtype_of(type[InvSub[Any]], type[Inv[T]]))
401+ static_assert(is_assignable_to(type[InvSub[T]], type[Inv[Any]]))
402+ static_assert(is_assignable_to(type[InvSub[Any]], type[Inv[T]]))
403+ static_assert(not is_disjoint_from(type[InvSub[T]], type[Inv[Any]]))
404+ ```
0 commit comments