Skip to content

Commit 4226670

Browse files
committed
Filter out overloads from bindings as well
1 parent e02176b commit 4226670

File tree

2 files changed

+83
-52
lines changed

2 files changed

+83
-52
lines changed

crates/ty_python_semantic/resources/mdtest/public_types.md

Lines changed: 7 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -402,29 +402,22 @@ def _():
402402
reveal_type(g) # revealed: (Overload[(x: int) -> int, (x: str) -> str]) | str
403403
```
404404

405-
### Conditional overloads
405+
### Overload only defined in one branch
406406

407407
```py
408408
from typing import overload
409409

410410
def flag() -> bool:
411411
return True
412412

413-
@overload
414-
def f(x: int) -> int: ...
415-
416413
if flag():
417414
@overload
418-
def f(x: str) -> str: ...
419-
420-
else:
415+
def f(x: int) -> int: ...
421416
@overload
422-
def f(x: bytes) -> bytes: ...
423-
424-
reveal_type(f) # revealed: (Overload[(x: int) -> int, (x: str) -> str]) | (Overload[(x: int) -> int, (x: bytes) -> bytes])
417+
def f(x: str) -> str: ...
418+
def f(x: int | str) -> int | str:
419+
raise NotImplementedError
425420

426-
def _():
427-
# TODO: ideally, this should be the same union type as above.
428-
# revealed: (def f(x: int) -> int) | (Overload[(x: int) -> int, (x: str) -> str]) | (Overload[(x: int) -> int, (x: bytes) -> bytes])
429-
reveal_type(f)
421+
def _():
422+
reveal_type(f) # revealed: Overload[(x: int) -> int, (x: str) -> str]
430423
```

crates/ty_python_semantic/src/place.rs

Lines changed: 76 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -941,7 +941,15 @@ fn place_from_bindings_impl<'db>(
941941

942942
if let Some(first) = types.next() {
943943
let ty = if let Some(second) = types.next() {
944-
UnionType::from_elements(db, [first, second].into_iter().chain(types))
944+
let mut builder = PublicTypeBuilder::new(db);
945+
builder.add(first);
946+
builder.add(second);
947+
948+
for ty in types {
949+
builder.add(ty);
950+
}
951+
952+
builder.build()
945953
} else {
946954
first
947955
};
@@ -969,73 +977,103 @@ fn place_from_bindings_impl<'db>(
969977
}
970978
}
971979

972-
/// Accumulates multiple (potentially conflicting) declared types and type qualifiers,
973-
/// and eventually builds a union from them.
980+
/// Accumulates types from multiple bindings or declarations, and eventually builds a
981+
/// union type from them.
974982
///
975983
/// `@overload`ed function literal types are discarded if they are immediately followed
976984
/// by their implementation. This is to ensure that we do not merge all of them into the
977985
/// union type. The last one will include the other overloads already.
978986
struct PublicTypeBuilder<'db> {
979-
queue: Option<TypeAndQualifiers<'db>>,
987+
db: &'db dyn Db,
988+
queue: Option<Type<'db>>,
980989
builder: UnionBuilder<'db>,
981-
qualifiers: TypeQualifiers,
982-
first_type: Option<Type<'db>>,
983-
conflicting_types: FxOrderSet<Type<'db>>,
984990
}
985991

986992
impl<'db> PublicTypeBuilder<'db> {
987993
fn new(db: &'db dyn Db) -> Self {
988994
PublicTypeBuilder {
995+
db,
989996
queue: None,
990997
builder: UnionBuilder::new(db),
991-
qualifiers: TypeQualifiers::empty(),
992-
first_type: None,
993-
conflicting_types: FxOrderSet::default(),
994998
}
995999
}
9961000

997-
fn push_element(&mut self, db: &'db dyn Db, element: TypeAndQualifiers<'db>) {
998-
let element_ty = element.inner_type();
999-
1000-
if let Some(first_ty) = self.first_type {
1001-
if !first_ty.is_equivalent_to(db, element_ty) {
1002-
self.conflicting_types.insert(element_ty);
1003-
}
1004-
} else {
1005-
self.first_type = Some(element_ty);
1006-
}
1007-
1008-
self.builder.add_in_place(element_ty);
1009-
self.qualifiers = self.qualifiers.union(element.qualifiers());
1001+
fn add_to_union(&mut self, element: Type<'db>) {
1002+
self.builder.add_in_place(element);
10101003
}
10111004

1012-
fn drain_queue(&mut self, db: &'db dyn Db) {
1005+
fn drain_queue(&mut self) {
10131006
if let Some(queued_element) = self.queue.take() {
1014-
self.push_element(db, queued_element);
1007+
self.add_to_union(queued_element);
10151008
}
10161009
}
10171010

1018-
fn add(&mut self, db: &'db dyn Db, element: TypeAndQualifiers<'db>) {
1019-
let element_type = element.inner_type();
1020-
match element_type {
1011+
fn add(&mut self, element: Type<'db>) -> bool {
1012+
match element {
10211013
Type::FunctionLiteral(function) => {
1022-
if function.literal(db).last_definition(db).is_overload(db) {
1014+
if function
1015+
.literal(self.db)
1016+
.last_definition(self.db)
1017+
.is_overload(self.db)
1018+
{
10231019
self.queue = Some(element);
1020+
false
10241021
} else {
10251022
self.queue = None;
1026-
self.push_element(db, element);
1023+
self.add_to_union(element);
1024+
true
10271025
}
10281026
}
10291027
_ => {
1030-
self.drain_queue(db);
1031-
self.push_element(db, element);
1028+
self.drain_queue();
1029+
self.add_to_union(element);
1030+
true
10321031
}
10331032
}
10341033
}
10351034

1036-
fn build(mut self, db: &'db dyn Db) -> DeclaredTypeAndConflictingTypes<'db> {
1037-
self.drain_queue(db);
1035+
fn build(mut self) -> Type<'db> {
1036+
self.drain_queue();
1037+
self.builder.build()
1038+
}
1039+
}
1040+
1041+
/// Accumulates multiple (potentially conflicting) declared types and type qualifiers,
1042+
/// and eventually builds a union from them.
1043+
struct DeclaredTypeBuilder<'db> {
1044+
inner: PublicTypeBuilder<'db>,
1045+
qualifiers: TypeQualifiers,
1046+
first_type: Option<Type<'db>>,
1047+
conflicting_types: FxOrderSet<Type<'db>>,
1048+
}
1049+
1050+
impl<'db> DeclaredTypeBuilder<'db> {
1051+
fn new(db: &'db dyn Db) -> Self {
1052+
DeclaredTypeBuilder {
1053+
inner: PublicTypeBuilder::new(db),
1054+
qualifiers: TypeQualifiers::empty(),
1055+
first_type: None,
1056+
conflicting_types: FxOrderSet::default(),
1057+
}
1058+
}
1059+
1060+
fn add(&mut self, element: TypeAndQualifiers<'db>) {
1061+
let element_ty = element.inner_type();
1062+
1063+
if self.inner.add(element_ty) {
1064+
if let Some(first_ty) = self.first_type {
1065+
if !first_ty.is_equivalent_to(self.inner.db, element_ty) {
1066+
self.conflicting_types.insert(element_ty);
1067+
}
1068+
} else {
1069+
self.first_type = Some(element_ty);
1070+
}
1071+
}
1072+
1073+
self.qualifiers = self.qualifiers.union(element.qualifiers());
1074+
}
10381075

1076+
fn build(mut self) -> DeclaredTypeAndConflictingTypes<'db> {
10391077
if !self.conflicting_types.is_empty() {
10401078
self.conflicting_types.insert_before(
10411079
0,
@@ -1045,7 +1083,7 @@ impl<'db> PublicTypeBuilder<'db> {
10451083
}
10461084

10471085
(
1048-
TypeAndQualifiers::new(self.builder.build(), self.qualifiers),
1086+
TypeAndQualifiers::new(self.inner.build(), self.qualifiers),
10491087
self.conflicting_types.into_boxed_slice(),
10501088
)
10511089
}
@@ -1112,11 +1150,11 @@ fn place_from_declarations_impl<'db>(
11121150
let mut types = types.peekable();
11131151

11141152
if types.peek().is_some() {
1115-
let mut builder = PublicTypeBuilder::new(db);
1153+
let mut builder = DeclaredTypeBuilder::new(db);
11161154
for element in types {
1117-
builder.add(db, element);
1155+
builder.add(element);
11181156
}
1119-
let (declared, conflicting) = builder.build(db);
1157+
let (declared, conflicting) = builder.build();
11201158

11211159
if !conflicting.is_empty() {
11221160
return Err((declared, conflicting));

0 commit comments

Comments
 (0)