diff --git a/crates/ty_python_semantic/src/types/call/bind.rs b/crates/ty_python_semantic/src/types/call/bind.rs index 95f1db711f..6389ebe8bc 100644 --- a/crates/ty_python_semantic/src/types/call/bind.rs +++ b/crates/ty_python_semantic/src/types/call/bind.rs @@ -2891,9 +2891,16 @@ impl<'a, 'db> ArgumentTypeChecker<'a, 'db> { // should prefer the tighter specialization. // XXX: Determine typevar variance per argument + eprintln!( + "--> arg {} {} {}", + argument_index, + argument_constraints.display(self.db), + valid_argument_constraints.display(self.db), + ); constraints.intersect(self.db, valid_argument_constraints); } } + eprintln!("--> constraints {}", constraints.display(self.db)); // Attempt to promote any literal types assigned to the specialization. let maybe_promote = |identity, typevar, ty: Type<'db>| { @@ -2949,15 +2956,23 @@ impl<'a, 'db> ArgumentTypeChecker<'a, 'db> { generic_context.specialize_constrained_mapped(self.db, constraints, maybe_promote) else { // XXX: better error + eprintln!("--> X1"); return; }; // XXX: maybe_promote let isolated_return_ty = self .return_ty .apply_specialization(self.db, isolated_specialization); + eprintln!("--> spec {}", isolated_specialization.display_full(self.db)); + eprintln!("--> rty {}", isolated_return_ty.display(self.db)); let mut try_infer_tcx = || { let (return_ty, call_expression_tcx) = return_with_tcx?; + eprintln!( + "--> infer tcx {} {}", + return_ty.display(self.db), + call_expression_tcx.display(self.db) + ); // A type variable is not a useful type-context for expression inference, and applying it // to the return type can lead to confusing unions in nested generic calls. @@ -2968,6 +2983,7 @@ impl<'a, 'db> ArgumentTypeChecker<'a, 'db> { // If the return type is already assignable to the annotated type, we ignore the rest of // the type context and prefer the narrower inferred type. if isolated_return_ty.is_assignable_to(self.db, call_expression_tcx) { + eprintln!("--> X2"); return None; } @@ -2977,6 +2993,7 @@ impl<'a, 'db> ArgumentTypeChecker<'a, 'db> { .when_assignable_to(self.db, call_expression_tcx, self.inferable_typevars) .and(self.db, || valid_specializations); if return_constraints.is_never_satisfied(self.db) { + eprintln!("--> X3"); return None; } @@ -2987,6 +3004,7 @@ impl<'a, 'db> ArgumentTypeChecker<'a, 'db> { maybe_promote, ) else { // XXX: better return + eprintln!("--> X4"); return None; }; // XXX: maybe_promote @@ -3009,13 +3027,37 @@ impl<'a, 'db> ArgumentTypeChecker<'a, 'db> { let parameters = self.signature.parameters(); let parameter = ¶meters[parameter_index]; if let Some(mut expected_ty) = parameter.annotated_type() { + eprintln!( + "--> before {:?} {} {}", + adjusted_argument_index, + argument_type.display(self.db), + expected_ty.display(self.db), + ); if let Some(specialization) = self.specialization { argument_type = argument_type.apply_specialization(self.db, specialization); expected_ty = expected_ty.apply_specialization(self.db, specialization); + eprintln!( + "--> after {:?} {} {}", + adjusted_argument_index, + argument_type.display(self.db), + expected_ty.display(self.db), + ); + eprintln!(" {:?}", argument_type); + eprintln!(" {:?}", expected_ty); } // TODO: Soon we will go further, and build the actual specializations from the // constraint set that we get from this assignability check, instead of inferring and // building them in an earlier separate step. + let when = + argument_type.when_assignable_to(self.db, expected_ty, self.inferable_typevars); + eprintln!("===> check argument"); + eprintln!(" --> arg {}", argument_type.display(self.db)); + eprintln!(" --> param {}", expected_ty.display(self.db)); + eprintln!(" --> when {}", when.display(self.db)); + eprintln!( + " --> sat {}", + when.satisfied_by_all_typevars(self.db, self.inferable_typevars) + ); if !argument_type .when_assignable_to(self.db, expected_ty, self.inferable_typevars) .satisfied_by_all_typevars(self.db, self.inferable_typevars) diff --git a/crates/ty_python_semantic/src/types/generics.rs b/crates/ty_python_semantic/src/types/generics.rs index e7292f1340..a6b5c354b0 100644 --- a/crates/ty_python_semantic/src/types/generics.rs +++ b/crates/ty_python_semantic/src/types/generics.rs @@ -1432,6 +1432,7 @@ impl<'db> SpecializationBuilder<'db> { mut f: &mut dyn FnMut(TypeVarAssignment<'db>) -> Option>, ) -> Result<(), SpecializationError<'db>> { if formal == actual { + eprintln!(" --> AAA"); return Ok(()); } @@ -1510,6 +1511,7 @@ impl<'db> SpecializationBuilder<'db> { .satisfied_by_all_typevars(self.db, InferableTypeVars::None) }); if assignable_elements.exactly_one().is_ok() { + eprintln!(" --> BBB"); return Ok(()); } } diff --git a/crates/ty_python_semantic/src/types/signatures.rs b/crates/ty_python_semantic/src/types/signatures.rs index 74fe451e50..d4fe00e211 100644 --- a/crates/ty_python_semantic/src/types/signatures.rs +++ b/crates/ty_python_semantic/src/types/signatures.rs @@ -876,19 +876,22 @@ impl<'db> Signature<'db> { let mut check_types = |type1: Option>, type2: Option>| { let type1 = type1.unwrap_or(Type::unknown()); let type2 = type2.unwrap_or(Type::unknown()); - !result - .intersect( - db, - type1.has_relation_to_impl( - db, - type2, - inferable, - relation, - relation_visitor, - disjointness_visitor, - ), - ) - .is_never_satisfied(db) + eprintln!(" --> check param"); + eprintln!(" {}", type1.display(db)); + eprintln!(" {}", type2.display(db)); + let x = type1.has_relation_to_impl( + db, + type2, + inferable, + relation, + relation_visitor, + disjointness_visitor, + ); + eprintln!(" x {}", x.display(db),); + let y = result.intersect(db, x); + eprintln!(" y {}", y.display(db),); + eprintln!(" ? {}", !y.is_never_satisfied(db)); + !y.is_never_satisfied(db) }; // Return types are covariant. @@ -932,6 +935,7 @@ impl<'db> Signature<'db> { let Some(next_parameter) = parameters.next() else { // All parameters have been checked or both the parameter lists were empty. In // either case, `self` is a subtype of `other`. + eprintln!(" --> X1 {}", result.display(db)); return result; }; @@ -952,6 +956,7 @@ impl<'db> Signature<'db> { // `other`, then the non-variadic parameters in `self` must have a default // value. if default_type.is_none() { + eprintln!(" --> X2"); return ConstraintSet::from(false); } } @@ -964,6 +969,7 @@ impl<'db> Signature<'db> { EitherOrBoth::Right(_) => { // If there are more parameters in `other` than in `self`, then `self` is not a // subtype of `other`. + eprintln!(" --> X3"); return ConstraintSet::from(false); } @@ -984,12 +990,14 @@ impl<'db> Signature<'db> { }, ) => { if self_default.is_none() && other_default.is_some() { + eprintln!(" --> X4"); return ConstraintSet::from(false); } if !check_types( other_parameter.annotated_type(), self_parameter.annotated_type(), ) { + eprintln!(" --> X5"); return result; } } @@ -1005,16 +1013,19 @@ impl<'db> Signature<'db> { }, ) => { if self_name != other_name { + eprintln!(" --> X6"); return ConstraintSet::from(false); } // The following checks are the same as positional-only parameters. if self_default.is_none() && other_default.is_some() { + eprintln!(" --> X7"); return ConstraintSet::from(false); } if !check_types( other_parameter.annotated_type(), self_parameter.annotated_type(), ) { + eprintln!(" --> X8"); return result; } } @@ -1028,6 +1039,7 @@ impl<'db> Signature<'db> { other_parameter.annotated_type(), self_parameter.annotated_type(), ) { + eprintln!(" --> X9"); return result; } @@ -1068,6 +1080,7 @@ impl<'db> Signature<'db> { other_parameter.annotated_type(), self_parameter.annotated_type(), ) { + eprintln!(" --> X10"); return result; } parameters.next_other(); @@ -1079,6 +1092,7 @@ impl<'db> Signature<'db> { other_parameter.annotated_type(), self_parameter.annotated_type(), ) { + eprintln!(" --> X11"); return result; } } @@ -1094,12 +1108,16 @@ impl<'db> Signature<'db> { break; } - _ => return ConstraintSet::from(false), + _ => { + eprintln!(" --> X12"); + return ConstraintSet::from(false); + } } } } } + eprintln!(" --> YYY"); // At this point, the remaining parameters in `other` are keyword-only or keyword variadic. // But, `self` could contain any unmatched positional parameters. let (self_parameters, other_parameters) = parameters.into_remaining();