Skip to content

Commit b05868f

Browse files
committed
Record unbound in attrs after fallback mechanism
1 parent 7362cf9 commit b05868f

File tree

1 file changed

+81
-8
lines changed
  • crates/ty_python_semantic/src/types

1 file changed

+81
-8
lines changed

crates/ty_python_semantic/src/types/infer.rs

Lines changed: 81 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -7027,7 +7027,7 @@ impl<'db, 'ast> TypeInferenceBuilder<'db, 'ast> {
70277027
}
70287028

70297029
fn narrow_expr_with_applicable_constraints<'r>(
7030-
&self,
7030+
&mut self,
70317031
target: impl Into<ast::ExprRef<'r>>,
70327032
target_ty: Type<'db>,
70337033
constraint_keys: &[(FileScopeId, ConstraintKey)],
@@ -7061,7 +7061,7 @@ impl<'db, 'ast> TypeInferenceBuilder<'db, 'ast> {
70617061

70627062
let mut assigned_type = None;
70637063
if let Some(place_expr) = PlaceExpr::try_from_expr(attribute) {
7064-
let (resolved, keys) = self.record_place_load(
7064+
let (resolved, keys) = self.infer_place_load(
70657065
PlaceExprRef::from(&place_expr),
70667066
ast::ExprRef::Attribute(attribute),
70677067
);
@@ -7071,10 +7071,16 @@ impl<'db, 'ast> TypeInferenceBuilder<'db, 'ast> {
70717071
}
70727072
}
70737073

7074-
let resolved_type = value_type
7075-
.member(db, &attr.id)
7076-
.map_type(|ty| self.narrow_expr_with_applicable_constraints(attribute, ty, &constraint_keys))
7077-
.unwrap_with_diagnostic(|lookup_error| match lookup_error {
7074+
let fallback_place = value_type.member(db, &attr.id);
7075+
if !fallback_place.place.is_definitely_bound() {
7076+
self.all_definitely_bound = false;
7077+
eprintln!("attribute: {:?} was not bound", attribute);
7078+
}
7079+
7080+
let resolved_type =
7081+
fallback_place.map_type(|ty| {
7082+
self.narrow_expr_with_applicable_constraints(attribute, ty, &constraint_keys)
7083+
}).unwrap_with_diagnostic(|lookup_error| match lookup_error {
70787084
LookupError::Unbound(_) => {
70797085
let report_unresolved_attribute = self.is_reachable(attribute);
70807086

@@ -11361,8 +11367,8 @@ mod tests {
1136111367
1136211368
class Toggle:
1136311369
def __init__(self: "Toggle"):
11364-
if self.x:
11365-
self.x: Literal[False] = False
11370+
if not self.x:
11371+
self.x: Literal[True] = True
1136611372
"#,
1136711373
)
1136811374
.unwrap();
@@ -11390,6 +11396,73 @@ mod tests {
1139011396
assert_eq!(cycles.len(), 1);
1139111397
}
1139211398

11399+
#[test]
11400+
fn analyze_cycles_gridout() {
11401+
let mut db = setup_db();
11402+
let filename = "src/gridout.py";
11403+
db.write_dedented(
11404+
filename,
11405+
r#"
11406+
EMPTY = b""
11407+
class GridOut:
11408+
def __init__(self: "GridOut") -> None:
11409+
self._buffer_pos = 0
11410+
self._buffer = b""
11411+
def readchunk(self: "GridOut") -> bytes:
11412+
if not len(self._buffer) - self._buffer_pos:
11413+
raise Exception("truncated chunk")
11414+
self._buffer_pos = 0
11415+
return EMPTY
11416+
def _read_size_or_line(self: "GridOut", size: int = -1) -> bytes:
11417+
if size > self._position:
11418+
size = self._position
11419+
if size == 0:
11420+
return bytes()
11421+
received = 0
11422+
needed = size - received
11423+
while received < size:
11424+
if self._buffer:
11425+
buf = self._buffer
11426+
chunk_start = self._buffer_pos
11427+
chunk_data = buf[self._buffer_pos :]
11428+
self._buffer = EMPTY
11429+
else:
11430+
buf = self.readchunk()
11431+
chunk_start = 0
11432+
chunk_data = buf
11433+
needed = buf.find(EMPTY, chunk_start, chunk_start + needed)
11434+
if len(chunk_data) > needed:
11435+
self._buffer = buf
11436+
self._buffer_pos = chunk_start + needed
11437+
self._position -= len(self._buffer) - self._buffer_pos
11438+
return b""
11439+
"#,
11440+
)
11441+
.unwrap();
11442+
11443+
db.clear_salsa_events();
11444+
assert_file_diagnostics(&db, filename, &[]);
11445+
let events = db.take_salsa_events();
11446+
let cycles = salsa::attach(&db, || {
11447+
events
11448+
.iter()
11449+
.filter_map(|event| {
11450+
if let salsa::EventKind::WillIterateCycle {
11451+
database_key,
11452+
iteration_count,
11453+
fell_back: _,
11454+
} = event.kind
11455+
{
11456+
Some(format!("{database_key:?}, {iteration_count:?}"))
11457+
} else {
11458+
None
11459+
}
11460+
})
11461+
.collect::<Vec<_>>()
11462+
});
11463+
assert_eq!(cycles.len(), 2414);
11464+
}
11465+
1139311466
#[test]
1139411467
fn not_literal_string() -> anyhow::Result<()> {
1139511468
let mut db = setup_db();

0 commit comments

Comments
 (0)