Skip to content

Commit 4aee039

Browse files
authored
[ty] Show the raw argument type in reveal_type (#19400)
This PR is changes how `reveal_type` determines what type to reveal, in a way that should be a no-op to most callers. Previously, we would reveal the type of the first parameter, _after_ all of the call binding machinery had done its work. This includes inferring the specialization of a generic function, and then applying that specialization to all parameter and argument types, which is relevant since the typeshed definition of `reveal_type` is generic: ```pyi def reveal_type(obj: _T, /) -> _T: ... ``` Normally this does not matter, since we infer `_T = [arg type]` and apply that to the parameter type, yielding `[arg type]`. But applying that specialization also simplifies the argument type, which makes `reveal_type` less useful as a debugging aid when we want to see the actual, raw, unsimplified argument type. With this patch, we now grab the original unmodified argument type and reveal that instead. In addition to making the debugging aid example work, this also makes our `reveal_type` implementation more robust to custom typeshed definitions, such as ```py def reveal_type(obj: Any) -> Any: ... ``` (That custom definition is probably not what anyone would want, since you wouldn't be able to depend on the return type being equivalent to the argument type, but still)
1 parent 1fd9103 commit 4aee039

File tree

3 files changed

+213
-195
lines changed

3 files changed

+213
-195
lines changed

crates/ty_python_semantic/src/types/class.rs

Lines changed: 83 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -3387,10 +3387,10 @@ impl KnownClass {
33873387
self,
33883388
context: &InferContext<'db, '_>,
33893389
index: &SemanticIndex<'db>,
3390-
overload_binding: &Binding<'db>,
3391-
call_argument_types: &CallArguments<'_, 'db>,
3390+
overload: &mut Binding<'db>,
3391+
call_arguments: &CallArguments<'_, 'db>,
33923392
call_expression: &ast::ExprCall,
3393-
) -> Option<Type<'db>> {
3393+
) {
33943394
let db = context.db();
33953395
let scope = context.scope();
33963396
let module = context.module();
@@ -3401,14 +3401,15 @@ impl KnownClass {
34013401
// In this case, we need to infer the two arguments:
34023402
// 1. The nearest enclosing class
34033403
// 2. The first parameter of the current function (typically `self` or `cls`)
3404-
match overload_binding.parameter_types() {
3404+
match overload.parameter_types() {
34053405
[] => {
34063406
let Some(enclosing_class) =
34073407
nearest_enclosing_class(db, index, scope, module)
34083408
else {
34093409
BoundSuperError::UnavailableImplicitArguments
34103410
.report_diagnostic(context, call_expression.into());
3411-
return Some(Type::unknown());
3411+
overload.set_return_type(Type::unknown());
3412+
return;
34123413
};
34133414

34143415
// The type of the first parameter if the given scope is function-like (i.e. function or lambda).
@@ -3430,7 +3431,8 @@ impl KnownClass {
34303431
let Some(first_param) = first_param else {
34313432
BoundSuperError::UnavailableImplicitArguments
34323433
.report_diagnostic(context, call_expression.into());
3433-
return Some(Type::unknown());
3434+
overload.set_return_type(Type::unknown());
3435+
return;
34343436
};
34353437

34363438
let definition = index.expect_single_definition(first_param);
@@ -3447,18 +3449,17 @@ impl KnownClass {
34473449
Type::unknown()
34483450
});
34493451

3450-
Some(bound_super)
3452+
overload.set_return_type(bound_super);
34513453
}
34523454
[Some(pivot_class_type), Some(owner_type)] => {
34533455
let bound_super = BoundSuperType::build(db, *pivot_class_type, *owner_type)
34543456
.unwrap_or_else(|err| {
34553457
err.report_diagnostic(context, call_expression.into());
34563458
Type::unknown()
34573459
});
3458-
3459-
Some(bound_super)
3460+
overload.set_return_type(bound_super);
34603461
}
3461-
_ => None,
3462+
_ => {}
34623463
}
34633464
}
34643465

@@ -3473,12 +3474,14 @@ impl KnownClass {
34733474
_ => None,
34743475
}
34753476
}) else {
3476-
let builder =
3477-
context.report_lint(&INVALID_LEGACY_TYPE_VARIABLE, call_expression)?;
3478-
builder.into_diagnostic(
3479-
"A legacy `typing.TypeVar` must be immediately assigned to a variable",
3480-
);
3481-
return None;
3477+
if let Some(builder) =
3478+
context.report_lint(&INVALID_LEGACY_TYPE_VARIABLE, call_expression)
3479+
{
3480+
builder.into_diagnostic(
3481+
"A legacy `typing.TypeVar` must be immediately assigned to a variable",
3482+
);
3483+
}
3484+
return;
34823485
};
34833486

34843487
let [
@@ -3489,9 +3492,9 @@ impl KnownClass {
34893492
contravariant,
34903493
covariant,
34913494
_infer_variance,
3492-
] = overload_binding.parameter_types()
3495+
] = overload.parameter_types()
34933496
else {
3494-
return None;
3497+
return;
34953498
};
34963499

34973500
let covariant = covariant
@@ -3504,30 +3507,37 @@ impl KnownClass {
35043507

35053508
let variance = match (contravariant, covariant) {
35063509
(Truthiness::Ambiguous, _) => {
3507-
let builder =
3508-
context.report_lint(&INVALID_LEGACY_TYPE_VARIABLE, call_expression)?;
3509-
builder.into_diagnostic(
3510-
"The `contravariant` parameter of a legacy `typing.TypeVar` \
3510+
if let Some(builder) =
3511+
context.report_lint(&INVALID_LEGACY_TYPE_VARIABLE, call_expression)
3512+
{
3513+
builder.into_diagnostic(
3514+
"The `contravariant` parameter of a legacy `typing.TypeVar` \
35113515
cannot have an ambiguous value",
3512-
);
3513-
return None;
3516+
);
3517+
}
3518+
return;
35143519
}
35153520
(_, Truthiness::Ambiguous) => {
3516-
let builder =
3517-
context.report_lint(&INVALID_LEGACY_TYPE_VARIABLE, call_expression)?;
3518-
builder.into_diagnostic(
3519-
"The `covariant` parameter of a legacy `typing.TypeVar` \
3521+
if let Some(builder) =
3522+
context.report_lint(&INVALID_LEGACY_TYPE_VARIABLE, call_expression)
3523+
{
3524+
builder.into_diagnostic(
3525+
"The `covariant` parameter of a legacy `typing.TypeVar` \
35203526
cannot have an ambiguous value",
3521-
);
3522-
return None;
3527+
);
3528+
}
3529+
return;
35233530
}
35243531
(Truthiness::AlwaysTrue, Truthiness::AlwaysTrue) => {
3525-
let builder =
3526-
context.report_lint(&INVALID_LEGACY_TYPE_VARIABLE, call_expression)?;
3527-
builder.into_diagnostic(
3528-
"A legacy `typing.TypeVar` cannot be both covariant and contravariant",
3529-
);
3530-
return None;
3532+
if let Some(builder) =
3533+
context.report_lint(&INVALID_LEGACY_TYPE_VARIABLE, call_expression)
3534+
{
3535+
builder.into_diagnostic(
3536+
"A legacy `typing.TypeVar` cannot be both \
3537+
covariant and contravariant",
3538+
);
3539+
}
3540+
return;
35313541
}
35323542
(Truthiness::AlwaysTrue, Truthiness::AlwaysFalse) => {
35333543
TypeVarVariance::Contravariant
@@ -3541,19 +3551,21 @@ impl KnownClass {
35413551
let name_param = name_param.into_string_literal().map(|name| name.value(db));
35423552

35433553
if name_param.is_none_or(|name_param| name_param != target.id) {
3544-
let builder =
3545-
context.report_lint(&INVALID_LEGACY_TYPE_VARIABLE, call_expression)?;
3546-
builder.into_diagnostic(format_args!(
3547-
"The name of a legacy `typing.TypeVar`{} must match \
3554+
if let Some(builder) =
3555+
context.report_lint(&INVALID_LEGACY_TYPE_VARIABLE, call_expression)
3556+
{
3557+
builder.into_diagnostic(format_args!(
3558+
"The name of a legacy `typing.TypeVar`{} must match \
35483559
the name of the variable it is assigned to (`{}`)",
3549-
if let Some(name_param) = name_param {
3550-
format!(" (`{name_param}`)")
3551-
} else {
3552-
String::new()
3553-
},
3554-
target.id,
3555-
));
3556-
return None;
3560+
if let Some(name_param) = name_param {
3561+
format!(" (`{name_param}`)")
3562+
} else {
3563+
String::new()
3564+
},
3565+
target.id,
3566+
));
3567+
}
3568+
return;
35573569
}
35583570

35593571
let bound_or_constraint = match (bound, constraints) {
@@ -3568,8 +3580,8 @@ impl KnownClass {
35683580
// typevar constraints.
35693581
let elements = UnionType::new(
35703582
db,
3571-
overload_binding
3572-
.arguments_for_parameter(call_argument_types, 1)
3583+
overload
3584+
.arguments_for_parameter(call_arguments, 1)
35733585
.map(|(_, ty)| ty)
35743586
.collect::<Box<_>>(),
35753587
);
@@ -3578,13 +3590,13 @@ impl KnownClass {
35783590

35793591
// TODO: Emit a diagnostic that TypeVar cannot be both bounded and
35803592
// constrained
3581-
(Some(_), Some(_)) => return None,
3593+
(Some(_), Some(_)) => return,
35823594

35833595
(None, None) => None,
35843596
};
35853597

35863598
let containing_assignment = index.expect_single_definition(target);
3587-
Some(Type::KnownInstance(KnownInstanceType::TypeVar(
3599+
overload.set_return_type(Type::KnownInstance(KnownInstanceType::TypeVar(
35883600
TypeVarInstance::new(
35893601
db,
35903602
&target.id,
@@ -3594,7 +3606,7 @@ impl KnownClass {
35943606
*default,
35953607
TypeVarKind::Legacy,
35963608
),
3597-
)))
3609+
)));
35983610
}
35993611

36003612
KnownClass::TypeAliasType => {
@@ -3609,32 +3621,31 @@ impl KnownClass {
36093621
}
36103622
});
36113623

3612-
let [Some(name), Some(value), ..] = overload_binding.parameter_types() else {
3613-
return None;
3624+
let [Some(name), Some(value), ..] = overload.parameter_types() else {
3625+
return;
36143626
};
36153627

3616-
name.into_string_literal()
3617-
.map(|name| {
3618-
Type::KnownInstance(KnownInstanceType::TypeAliasType(TypeAliasType::Bare(
3619-
BareTypeAliasType::new(
3620-
db,
3621-
ast::name::Name::new(name.value(db)),
3622-
containing_assignment,
3623-
value,
3624-
),
3625-
)))
3626-
})
3627-
.or_else(|| {
3628-
let builder =
3629-
context.report_lint(&INVALID_TYPE_ALIAS_TYPE, call_expression)?;
3628+
let Some(name) = name.into_string_literal() else {
3629+
if let Some(builder) =
3630+
context.report_lint(&INVALID_TYPE_ALIAS_TYPE, call_expression)
3631+
{
36303632
builder.into_diagnostic(
36313633
"The name of a `typing.TypeAlias` must be a string literal",
36323634
);
3633-
None
3634-
})
3635+
}
3636+
return;
3637+
};
3638+
overload.set_return_type(Type::KnownInstance(KnownInstanceType::TypeAliasType(
3639+
TypeAliasType::Bare(BareTypeAliasType::new(
3640+
db,
3641+
ast::name::Name::new(name.value(db)),
3642+
containing_assignment,
3643+
value,
3644+
)),
3645+
)));
36353646
}
36363647

3637-
_ => None,
3648+
_ => {}
36383649
}
36393650
}
36403651
}

0 commit comments

Comments
 (0)