[ty] Add version hint for failed stdlib accesses#20909
Conversation
Diagnostic diff on typing conformance testsNo changes detected when running ty on typing conformance tests ✅ |
|
...est/snapshots/super.md_-_Super_-_Basic_Usage_-_Explicit_Super_Objec…_(b753048091f275c0).snap
Outdated
Show resolved
Hide resolved
|
To be honest, I'm not sure if this initial step is a strict improvement. Sure, it seems helpful in the rare case where you are accessing an attribute that is not available on the Python version that you have configured, but is available under the exact name on a higher version. But in the vast majority of "test.exe".trimsuffix(".exe") # no, it's called "replacesuffix"Note that the diagnostic change here does not show up in the ecosystem diff because |
AlexWaygood
left a comment
There was a problem hiding this comment.
Yeah, I agree with @sharkdp that in its current state this could just add a lot of noise and not be that helpful :-(
But I think it's pretty easy to make a few adjustments to this so that it's less noisy, but still pretty useful. Something like this, where we do actually check that the exact symbol exists in the symbol table somewhere (the definition just isn't visible on this Python version), could work pretty well:
diff --git a/crates/ty_python_semantic/src/semantic_index/place.rs b/crates/ty_python_semantic/src/semantic_index/place.rs
index 38e3d92816..75d3eaac65 100644
--- a/crates/ty_python_semantic/src/semantic_index/place.rs
+++ b/crates/ty_python_semantic/src/semantic_index/place.rs
@@ -181,7 +181,6 @@ impl PlaceTable {
}
/// Looks up a symbol by its name and returns a reference to it, if it exists.
- #[cfg(test)]
pub(crate) fn symbol_by_name(&self, name: &str) -> Option<&Symbol> {
self.symbols.symbol_id(name).map(|id| self.symbol(id))
}
diff --git a/crates/ty_python_semantic/src/types/diagnostic.rs b/crates/ty_python_semantic/src/types/diagnostic.rs
index f07d934dad..cb6bf8c4e7 100644
--- a/crates/ty_python_semantic/src/types/diagnostic.rs
+++ b/crates/ty_python_semantic/src/types/diagnostic.rs
@@ -9,6 +9,7 @@ use crate::lint::{Level, LintRegistryBuilder, LintStatus};
use crate::module_resolver::file_to_module;
use crate::semantic_index::definition::{Definition, DefinitionKind};
use crate::semantic_index::place::{PlaceTable, ScopedPlaceId};
+use crate::semantic_index::{global_scope, place_table};
use crate::suppression::FileSuppressionId;
use crate::types::call::CallError;
use crate::types::class::{DisjointBase, DisjointBaseKind, Field};
@@ -3155,6 +3156,16 @@ pub(super) fn hint_if_stdlib_attribute_exists_on_other_versions(
value_type: &Type,
attr: &Identifier,
) {
+ let Type::ModuleLiteral(module) = *value_type else {
+ return;
+ };
+ let Some(file) = module.module(db).file(db) else {
+ return;
+ };
+ let symbol_table = place_table(db, global_scope(db, file));
+ if symbol_table.symbol_by_name(attr).is_none() {
+ return;
+ }
let Some(definition) = value_type.definition(db) else {
return;
};This edit would mean that the suggestions would only fire on unresolved-attribute errors involving module-literal types. But I think probably most "oops, I tried to access this attribute that only exists on a new Python version" errors involve module-literal objects. So I think even this limited hint would help a lot of users and be a great first step.
8f49ef0 to
d08d591
Compare
|
Heh, I considered that implementation originally and was like "wait I can do better, and modules are their own definitions so this handles those too!" Having seen the results, I agree it's a safer minimum. |
0c41f90 to
1198cb2
Compare
|
Pushed up the new implementation. |
1198cb2 to
3079cc3
Compare
AlexWaygood
left a comment
There was a problem hiding this comment.
Thank you, this is great!
…rable * origin/main: [ty] Support dataclass-transform `field_specifiers` (#20888) Bump 0.14.1 (#20925) Standardize syntax error construction (#20903) [`pydoclint`] Implement `docstring-extraneous-parameter` (`DOC102`) (#20376) [ty] Fix panic 'missing root' when handling completion request (#20917) [ty] Run file watching tests serial when using nextest (#20918) [ty] Add version hint for failed stdlib attribute accesses (#20909) More CI improvements (#20920) [ty] Check typeshed VERSIONS for parent modules when reporting failed stdlib imports (#20908)
* main: [ty] Prefer declared type for invariant collection literals (#20927) [ty] Don't track inferability via different `Type` variants (#20677) [ty] Use declared variable types as bidirectional type context (#20796) [ty] Avoid unnecessarily widening generic specializations (#20875) [ty] Support dataclass-transform `field_specifiers` (#20888) Bump 0.14.1 (#20925) Standardize syntax error construction (#20903) [`pydoclint`] Implement `docstring-extraneous-parameter` (`DOC102`) (#20376) [ty] Fix panic 'missing root' when handling completion request (#20917) [ty] Run file watching tests serial when using nextest (#20918) [ty] Add version hint for failed stdlib attribute accesses (#20909) More CI improvements (#20920) [ty] Check typeshed VERSIONS for parent modules when reporting failed stdlib imports (#20908)
…mport a member added on a newer version (#21615) ## Summary Fixes astral-sh/ty#1620. #20909 added hints if you do something like this and your Python version is set to 3.10 or lower: ```py import typing typing.LiteralString ``` And we also have hints if you try to do something like this and your Python version is set too low: ```py from stdlib_module import new_submodule ``` But we don't currently have any subdiagnostic hint if you do something like _this_ and your Python version is set too low: ```py from typing import LiteralString ``` This PR adds that hint! ## Test Plan snapshots --------- Co-authored-by: Aria Desires <[email protected]>
This is the ultra-minimal implementation of
that was previously discussed as a good starting point. In particular we don't actually bother trying to figure out the exact python versions, but we still mention "hey btw for No Reason At All... you're on python 3.10" when you try to access something that has a definition rooted in the stdlib that we believe exists sometimes.