diff --git a/crates/ty_python_semantic/resources/mdtest/annotations/callable.md b/crates/ty_python_semantic/resources/mdtest/annotations/callable.md index 1a7974089e..37f5923496 100644 --- a/crates/ty_python_semantic/resources/mdtest/annotations/callable.md +++ b/crates/ty_python_semantic/resources/mdtest/annotations/callable.md @@ -398,7 +398,7 @@ def f_okay(c: Callable[[], None]): c.__qualname__ = "my_callable" result = getattr_static(c, "__qualname__") - reveal_type(result) # revealed: Never + reveal_type(result) # revealed: property if isinstance(result, property) and result.fset: c.__qualname__ = "my_callable" # okay ``` diff --git a/crates/ty_python_semantic/src/types.rs b/crates/ty_python_semantic/src/types.rs index 91fe0ee8fa..3217f0bf05 100644 --- a/crates/ty_python_semantic/src/types.rs +++ b/crates/ty_python_semantic/src/types.rs @@ -3309,19 +3309,14 @@ impl<'db> Type<'db> { let name_str = name.as_str(); match self { - Type::Union(union) => union - .map_with_boundness(db, |elem| { - elem.member_lookup_with_policy(db, name_str.into(), policy) - .place - }) - .into(), + Type::Union(union) => union.map_with_boundness_and_qualifiers(db, |elem| { + elem.member_lookup_with_policy(db, name_str.into(), policy) + }), Type::Intersection(intersection) => intersection - .map_with_boundness(db, |elem| { + .map_with_boundness_and_qualifiers(db, |elem| { elem.member_lookup_with_policy(db, name_str.into(), policy) - .place - }) - .into(), + }), Type::Dynamic(..) | Type::Never => Place::bound(self).into(), @@ -9743,8 +9738,8 @@ impl<'db> IntersectionType<'db> { let mut builder = IntersectionBuilder::new(db); let mut qualifiers = TypeQualifiers::empty(); - let mut any_unbound = false; - let mut any_possibly_unbound = false; + let mut all_unbound = true; + let mut any_definitely_bound = false; for ty in self.positive_elements_or_object(db) { let PlaceAndQualifiers { place: member, @@ -9752,12 +9747,11 @@ impl<'db> IntersectionType<'db> { } = transform_fn(&ty); qualifiers |= new_qualifiers; match member { - Place::Unbound => { - any_unbound = true; - } + Place::Unbound => {} Place::Type(ty_member, member_boundness) => { - if member_boundness == Boundness::PossiblyUnbound { - any_possibly_unbound = true; + all_unbound = false; + if member_boundness == Boundness::Bound { + any_definitely_bound = true; } builder = builder.add_positive(ty_member); @@ -9766,15 +9760,15 @@ impl<'db> IntersectionType<'db> { } PlaceAndQualifiers { - place: if any_unbound { + place: if all_unbound { Place::Unbound } else { Place::Type( builder.build(), - if any_possibly_unbound { - Boundness::PossiblyUnbound - } else { + if any_definitely_bound { Boundness::Bound + } else { + Boundness::PossiblyUnbound }, ) },