@@ -205,11 +205,12 @@ use crate::rank::RankBitBox;
205205use crate :: semantic_index:: place:: ScopedPlaceId ;
206206use crate :: semantic_index:: place_table;
207207use crate :: semantic_index:: predicate:: {
208- PatternPredicate , PatternPredicateKind , Predicate , PredicateNode , Predicates , ScopedPredicateId ,
208+ CallableAndCallExpr , PatternPredicate , PatternPredicateKind , Predicate , PredicateNode ,
209+ Predicates , ScopedPredicateId ,
209210} ;
210211use crate :: types:: {
211- IntersectionBuilder , KnownClass , NarrowingConstraint , Truthiness , Type , TypeContext ,
212- UnionBuilder , UnionType , infer_expression_type, infer_narrowing_constraint,
212+ CallableTypes , IntersectionBuilder , KnownClass , NarrowingConstraint , Truthiness , Type ,
213+ TypeContext , UnionBuilder , UnionType , infer_expression_type, infer_narrowing_constraint,
213214} ;
214215
215216/// A ternary formula that defines under what conditions a binding is visible. (A ternary formula
@@ -1089,12 +1090,62 @@ impl ReachabilityConstraints {
10891090 . bool ( db)
10901091 . negate_if ( !predicate. is_positive )
10911092 }
1092- PredicateNode :: ReturnsNever ( call_expr) => {
1093- let call_expr_ty = infer_expression_type ( db, call_expr, TypeContext :: default ( ) ) ;
1094- if call_expr_ty. is_equivalent_to ( db, Type :: Never ) {
1095- Truthiness :: AlwaysTrue
1093+ PredicateNode :: ReturnsNever ( CallableAndCallExpr {
1094+ callable,
1095+ call_expr,
1096+ is_await,
1097+ } ) => {
1098+ // We first infer just the type of the callable. In the most likely case that the
1099+ // function is not marked with `NoReturn`, or that it always returns `NoReturn`,
1100+ // doing so allows us to avoid the more expensive work of inferring the entire call
1101+ // expression (which could involve inferring argument types to possibly run the overload
1102+ // selection algorithm).
1103+ // Avoiding this on the happy-path is important because these constraints can be
1104+ // very large in number, since we add them on all statement level function calls.
1105+ let ty = infer_expression_type ( db, callable, TypeContext :: default ( ) ) ;
1106+
1107+ // Short-circuit for well known types that are known not to return `Never` when called.
1108+ // Without the short-circuit, we've seen that threads keep blocking each other
1109+ // because they all try to acquire Salsa's `CallableType` lock that ensures each type
1110+ // is only interned once. The lock is so heavily congested because there are only
1111+ // very few dynamic types, in which case Salsa's sharding the locks by value
1112+ // doesn't help much.
1113+ // See <https://github.com/astral-sh/ty/issues/968>.
1114+ if matches ! ( ty, Type :: Dynamic ( _) ) {
1115+ return Truthiness :: AlwaysFalse . negate_if ( !predicate. is_positive ) ;
1116+ }
1117+
1118+ let overloads_iterator = if let Some ( callable) = ty
1119+ . try_upcast_to_callable ( db)
1120+ . and_then ( CallableTypes :: exactly_one)
1121+ {
1122+ callable. signatures ( db) . overloads . iter ( )
10961123 } else {
1124+ return Truthiness :: AlwaysFalse . negate_if ( !predicate. is_positive ) ;
1125+ } ;
1126+
1127+ let mut no_overloads_return_never = true ;
1128+ let mut all_overloads_return_never = true ;
1129+ let mut any_overload_is_generic = false ;
1130+
1131+ for overload in overloads_iterator {
1132+ let returns_never = overload. return_ty . is_equivalent_to ( db, Type :: Never ) ;
1133+ no_overloads_return_never &= !returns_never;
1134+ all_overloads_return_never &= returns_never;
1135+ any_overload_is_generic |= overload. return_ty . has_typevar ( db) ;
1136+ }
1137+
1138+ if no_overloads_return_never && !any_overload_is_generic && !is_await {
10971139 Truthiness :: AlwaysFalse
1140+ } else if all_overloads_return_never {
1141+ Truthiness :: AlwaysTrue
1142+ } else {
1143+ let call_expr_ty = infer_expression_type ( db, call_expr, TypeContext :: default ( ) ) ;
1144+ if call_expr_ty. is_equivalent_to ( db, Type :: Never ) {
1145+ Truthiness :: AlwaysTrue
1146+ } else {
1147+ Truthiness :: AlwaysFalse
1148+ }
10981149 }
10991150 . negate_if ( !predicate. is_positive )
11001151 }
0 commit comments