Skip to content

Print deprecation warning on types and aliases #15962

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Conversation

ysbaddaden
Copy link
Contributor

@ysbaddaden ysbaddaden commented Jul 4, 2025

We can already deprecate a type and have the documentation report the deprecation, but there was no warning when trying to access the type as reported in #11043.

This PR enables a few use cases to also print a deprecation warning during compilation: when calling a class method on the type (no need to deprecate every method) which includes the constructors, when directly referencing a type (e.g. p Foo) and when extending a type in a class definition. There are more cases, but these should already cover a bunch.

This will be useful for #15805 for example:

In src/crystal/system/thread.cr:66:15

 66 | @detached = Atomic::Flag.new
                  ^-----------
Warning: Deprecated Atomic::Flag. Use Atomic(Bool) instead.

This PR also allows to deprecate an alias, which prints a deprecation warning and documents the deprecation. For example after renaming the contexts in #15936 and create deprecated aliases for the legacy names (instead of being fully silent).

We could already deprecate a type and have the documentation report the
deprecation. We now also print a deprecation warning during compilation
when we try to access the type, when calling a class method on the type
(no need to deprecate every method) but also when extending a type
during a class (or struct) definition.

There are more cases that haven't been implemented, yet (include,
extend, instance methods, ...).

We can also now deprecate an alias, which prints a deprecation warning
and documents the deprecation.
@ysbaddaden ysbaddaden self-assigned this Jul 4, 2025
@ysbaddaden
Copy link
Contributor Author

ysbaddaden commented Jul 4, 2025

There's a deprecation to take care of. Trying to compile crystal or the std specs, we get the following deprecation (6 times):

In src/llvm/abi/aarch64.cr:5:28

 5 | class LLVM::ABI::AArch64 < LLVM::ABI
                                ^--------
Warning: Deprecated LLVM::ABI. This API is now internal to the compiler and no longer updated publicly.

We don't use the types (we use Crystal::ABI), but we require the files and the deprecation warning happens when we visit the ClassDef... that appear to be always visited, regardless of their reachability.

@ysbaddaden
Copy link
Contributor Author

Unless we can detect that a class is used or not, and in that case skip checking its superclass for deprecation, maybe we could deprecate each specific ABI and check the superclass if the class itself ain't deprecated 🤔

@straight-shoota
Copy link
Member

Perhaps subclasses should implicitly inherit the deprecation of their parent class?
Then inheriting won't produce a warning, but using the inherited class would.

I suppose there could be some use cases where you don't want that, though. I.e. only deprecate the parent class, not the children, but the inheritance relationship needs to be kept until the deprecated parent is actually removed. Maybe that could be configured with an annotation property? But I'd leave that for later. Implicitly deprecating all children seems like a more useful default behaviour.

@HertzDevil
Copy link
Contributor

A deprecated use site referring to another deprecated entity should not emit a warning. A deprecated class inheriting from another deprecated one is fine, the same way methods behave (#13513).

I would leave the annotation on both parents and subclasses.

This avoids warnings about the superclass just because we required LLVM
and that required the deprecated abi classes.
@ysbaddaden
Copy link
Contributor Author

A deprecated use site referring to another deprecated entity should not emit a warning.

I did just that: don't check superclass for deprecation if the class is deprecated, and annotated the LLVM::ABI::* types with a deprecation. No more warnings until we use them.

@@ -140,6 +140,13 @@ module Crystal
def transform(node : ClassDef)
super

# check superclass for deprecation if the node isn't deprecated
if (type = node.type.lookup_type?(node.name)) && !type.annotation(@program.deprecated_annotation)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

BTW: node.type is NilType ... I must lookup the type by its name (actually a Path) to get the actual type for the ClassDef node 🙃

There's probably a reason, but it escapes me.

Co-authored-by: Johannes Müller <[email protected]>
@straight-shoota straight-shoota added this to the 1.18.0 milestone Jul 15, 2025
ysbaddaden added a commit to ysbaddaden/crystal that referenced this pull request Jul 17, 2025
It documents each individual class as deprecated, not just the LLVM::ABI
superclass.

This will also avoid warnings about the superclass after crystal-lang#15962 just
because we required LLVM and that in turn required the deprecated abi
classes.
@ysbaddaden
Copy link
Contributor Author

I added a couple specs for the namespace and instance methods (unaffected). We should detect include Foo and extend Foo but that could be its own PR.

@ysbaddaden
Copy link
Contributor Author

And another one for referencing a deprecated type, such as p Foo.

@straight-shoota straight-shoota removed this from the 1.18.0 milestone Jul 18, 2025
straight-shoota pushed a commit that referenced this pull request Jul 19, 2025
It documents each individual class as deprecated, not just the `LLVM::ABI` superclass.

This will also avoid warnings about the superclass after #15962 just because we required LLVM and that in turn required the deprecated abi classes.
@straight-shoota
Copy link
Member

Use in generic arguments does not yet trigger a deprecation warning in this branch (#11043 (comment)).
@ysbaddaden Do you plan to add that here, or should we merge as is and add that in a follow-up?

@ysbaddaden
Copy link
Contributor Author

Argh, Generics. That eluded me. Let's say a follow-up, along with include and extend?

@straight-shoota
Copy link
Member

They're both actually pretty simple given the prep work you did in this PR. I added some commits directly to this branch.

@straight-shoota straight-shoota added this to the 1.18.0 milestone Jul 22, 2025
@ysbaddaden
Copy link
Contributor Author

Oh, thanks a ton @straight-shoota 🙇

@straight-shoota straight-shoota merged commit 9eb36f2 into crystal-lang:master Jul 24, 2025
39 checks passed
@ysbaddaden ysbaddaden deleted the feature/warning-on-deprecated-alias-and-types branch July 24, 2025 06:57
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants