Skip to content

Commit

Permalink
Fix initialize-to-...-in-stub behavior
Browse files Browse the repository at this point in the history
Summary:
This commit separates Pyre2's decision about whether to type check the
value in an `AnnAssign` versus whether to treat it as initialized.

We need this so that we can correctly skip typing `...` assignment in stubs,
while also correctly treating it as indicating initialization.

This fixes a bug in class-and-instance attribute handling from stubs.

Reviewed By: rchen152

Differential Revision: D68279121

fbshipit-source-id: f0a896e86b1bd84c392566bd7e81ca255aa71c87
  • Loading branch information
stroxler authored and facebook-github-bot committed Jan 17, 2025
1 parent ee99cd4 commit eb9be03
Show file tree
Hide file tree
Showing 2 changed files with 24 additions and 23 deletions.
40 changes: 22 additions & 18 deletions pyre2/pyre2/bin/binding/bindings.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1648,10 +1648,20 @@ impl<'a> BindingsBuilder<'a> {
};
let ann_key = self.table.insert(ann_key, ann_val);

let (binding, is_initialized) = if let Some(mut value) = x.value
&& (!self.module_info.is_interface()
|| !matches!(&*value, Expr::EllipsisLiteral(_)))
{
let (value, is_initialized) = if let Some(value) = x.value {
// Treat a name as initialized, but skip actually checking the value, if we are assigning `...` in a stub.
if self.module_info.is_interface()
&& matches!(&*value, Expr::EllipsisLiteral(_))
{
(None, true)
} else {
(Some(value), true)
}
} else {
(None, false)
};

let binding = if let Some(mut value) = value {
// Handle forward references in explicit type aliases.
if let Expr::Name(name) = *x.annotation
&& name.id == "TypeAlias"
Expand All @@ -1661,22 +1671,16 @@ impl<'a> BindingsBuilder<'a> {
self.ensure_expr(&value);
}
let range = value.range();
(
Binding::NameAssign(
name.id.clone(),
Some(ann_key),
Box::new(Binding::Expr(Some(ann_key), *value)),
range,
),
true,
Binding::NameAssign(
name.id.clone(),
Some(ann_key),
Box::new(Binding::Expr(Some(ann_key), *value)),
range,
)
} else {
(
Binding::AnnotatedType(
ann_key,
Box::new(Binding::AnyType(AnyStyle::Implicit)),
),
false,
Binding::AnnotatedType(
ann_key,
Box::new(Binding::AnyType(AnyStyle::Implicit)),
)
};
self.bind_definition(&name, binding, Some(ann_key), is_initialized);
Expand Down
7 changes: 2 additions & 5 deletions pyre2/pyre2/bin/test/attributes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@

use crate::test::util::TestEnv;
use crate::testcase;
use crate::testcase_with_bug;

testcase!(
test_set_attribute,
Expand Down Expand Up @@ -427,16 +426,14 @@ class A:
t
}

testcase_with_bug!(
"We are incorrectly treating `...` assignment as not initializing attributes in stubs",
testcase!(
test_stub_initializes_attr_with_ellipses,
env_with_stub(),
r#"
from typing import assert_type
from foo import A
# TODO(stroxler) The error on the second line below is correct, but the first line should have no errors.
assert_type(A.x, int) # E: Instance-only attribute `x` of class `A` is not visible on the class # E: assert_type(Any, int)
assert_type(A.x, int)
A.y # E: Instance-only attribute `y` of class `A` is not visible on the class
"#,
);

0 comments on commit eb9be03

Please sign in to comment.