[ty] fix non-deterministic overload function inference (#20966)

This commit is contained in:
Shunsuke Shibayama 2025-10-19 19:13:10 +09:00 committed by GitHub
parent 1f8297cfe6
commit 36d4b02fa9
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -106,7 +106,7 @@ use crate::types::{
};
use crate::types::{ClassBase, add_inferred_python_version_hint_to_diagnostic};
use crate::unpack::{EvaluationMode, UnpackPosition};
use crate::{Db, FxOrderSet, Program};
use crate::{Db, FxIndexSet, FxOrderSet, Program};
mod annotation_expression;
mod type_expression;
@ -257,8 +257,10 @@ pub(super) struct TypeInferenceBuilder<'db, 'ast> {
/// return x
/// ```
///
/// To keep the calculation deterministic, we use an `FxIndexSet` whose order is determined by the sequence of insertion calls.
///
/// [`check_overloaded_functions`]: TypeInferenceBuilder::check_overloaded_functions
called_functions: FxHashSet<FunctionType<'db>>,
called_functions: FxIndexSet<FunctionType<'db>>,
/// Whether we are in a context that binds unbound typevars.
typevar_binding_context: Option<Definition<'db>>,
@ -312,7 +314,7 @@ impl<'db, 'ast> TypeInferenceBuilder<'db, 'ast> {
region,
scope,
return_types_and_ranges: vec![],
called_functions: FxHashSet::default(),
called_functions: FxIndexSet::default(),
deferred_state: DeferredExpressionState::None,
multi_inference_state: MultiInferenceState::Panic,
expressions: FxHashMap::default(),
@ -949,7 +951,7 @@ impl<'db, 'ast> TypeInferenceBuilder<'db, 'ast> {
// Collect all the unique overloaded function places in this scope. This requires a set
// because an overloaded function uses the same place for each of the overloads and the
// implementation.
let overloaded_function_places: FxHashSet<_> = self
let overloaded_function_places: FxIndexSet<_> = self
.declarations
.iter()
.filter_map(|(definition, ty)| {
@ -971,7 +973,7 @@ impl<'db, 'ast> TypeInferenceBuilder<'db, 'ast> {
.index
.use_def_map(self.scope().file_scope_id(self.db()));
let mut public_functions = FxHashSet::default();
let mut public_functions = FxIndexSet::default();
for place in overloaded_function_places {
if let Place::Defined(Type::FunctionLiteral(function), _, Definedness::AlwaysDefined) =