Hi Yilei, Thanks for the proposal! Detecting deprecated functions/classes etc. is indeed a very useful and important feature. However, I am generally lukewarm about doing this within a standardized type system. Here are my thoughts: 1) To me, "the function I am calling is deprecated" does not seem to violate any typing-related constraints, at least not in a traditional sense. We are not doing stuffs like passing an int to a function that expects a string or having an argument mismatch issues, which all lead to runtime errors. No soundness issues are involved here, and I'm not sure deprecation detection belongs to that camp. Of course, it does not mean that type systems cannot be extended to catch more issues, but for extensions like this I would generally expect more precise descriptions of the proposed system -- e.g. what are the additional typing constraints you want to introduce (like when and where should a type checker reports this "deprecation" error?), how does the new type interacts with pre-existing types (like how it affects subtyping and what are the meanings/behaviors of `Union[int, Annotated[str, Deprecated(...)]` or `Dict[str, Iterable[Annotated[int, Deprecated(...)]]]`?), etc. 2) Let's assume that we end up deciding we want to support deprecation detection in the type system. In that case, I would still argue against relying on `Annotated` for the job. My reading of PEP 593 is that the interpretation of `Annotated` is meant to be tooling-specific -- type checkers themselves may not want to assign specific meanings to those annotations as those meanings may create conflicts with downstream toolings. If you want to standardize your extensions to the type system, I personally think it would be much cleaner to just add new classes to stdlib (e.g. something like `typing.Deprecated[T]`?), which can do whatever `Annotated` can do but without the issues. 3) Let's assume that we end up adopting your approach. In that case, I would propose 2 small revisions to your `deprecated` API. The first one is that Pyre does not really want to support unbounded `Callable[[T], T]` in return type. See https://github.com/facebook/pyre-check/issues/329 . It would be nice if it can be rewritten into a callback protocol. The second one is that the `deprecated` function can be more fully typed with ParamSpec introduced in PEP 612. There's also this issue you mentioned in your message, but that's something to be fixed on the Pyre side. 4) Finally, let me also propose an alternative approach where the check gets implemented not inside the type system but as a (tool-specific) downstream linter instead. The idea is to have type checker expose an interface that returns all of the callsites it knows, and then let the linter go over them: for each of them see if the possible callees resides in a pre-determined deprecation list (which can be obtained by looking for syntactical hints around functions/classes/globals such as decorators, or even just a pre-defined list of names). If we do it like this, no standardized type system change is needed. The only thing that may need to be standardized here is the form of syntactical hints, which would be much lighter-weight than a standardized type system extension. - Jia