Skip to content

Commit 4018672

Browse files
ibraheemdevthejchap
authored andcommitted
Support relative --ty-path in ty-benchmark (astral-sh#18385)
## Summary This currently doesn't work because the benchmark changes the working directory. Also updates the process name to make it easier to compare two local ty binaries.
1 parent aa1fad6 commit 4018672

File tree

1 file changed

+148
-130
lines changed
  • crates/ty_python_semantic/src/types

1 file changed

+148
-130
lines changed

crates/ty_python_semantic/src/types/infer.rs

Lines changed: 148 additions & 130 deletions
Original file line numberDiff line numberDiff line change
@@ -3113,87 +3113,162 @@ impl<'db> TypeInferenceBuilder<'db> {
31133113
dataclass_params.is_some_and(|params| params.contains(DataclassParams::FROZEN))
31143114
};
31153115

3116-
match object_ty.class_member(db, attribute.into()) {
3117-
meta_attr @ SymbolAndQualifiers { .. } if meta_attr.is_class_var() => {
3116+
// First, try to call the `__setattr__` dunder method. If this is present/defined, overrides
3117+
// assigning the attributed by the normal mechanism.
3118+
let setattr_dunder_call_result = object_ty.try_call_dunder_with_policy(
3119+
db,
3120+
"__setattr__",
3121+
&mut CallArgumentTypes::positional([
3122+
Type::StringLiteral(StringLiteralType::new(db, Box::from(attribute))),
3123+
value_ty,
3124+
]),
3125+
MemberLookupPolicy::MRO_NO_OBJECT_FALLBACK,
3126+
);
3127+
3128+
match setattr_dunder_call_result {
3129+
Ok(result) => match result.return_type(db) {
3130+
Type::Never => {
3131+
if emit_diagnostics {
3132+
if let Some(builder) =
3133+
self.context.report_lint(&INVALID_ASSIGNMENT, target)
3134+
{
3135+
builder.into_diagnostic(format_args!(
3136+
"Cannot assign to attribute `{attribute}` on type `{}` \
3137+
via `__setattr__` that returns `Never`",
3138+
object_ty.display(db)
3139+
));
3140+
}
3141+
}
3142+
false
3143+
}
3144+
_ => true,
3145+
},
3146+
Err(CallDunderError::CallError(..)) => {
31183147
if emit_diagnostics {
31193148
if let Some(builder) =
3120-
self.context.report_lint(&INVALID_ATTRIBUTE_ACCESS, target)
3149+
self.context.report_lint(&UNRESOLVED_ATTRIBUTE, target)
31213150
{
31223151
builder.into_diagnostic(format_args!(
3123-
"Cannot assign to ClassVar `{attribute}` \
3124-
from an instance of type `{ty}`",
3125-
ty = object_ty.display(self.db()),
3152+
"Can not assign object of `{}` to attribute \
3153+
`{attribute}` on type `{}` with \
3154+
custom `__setattr__` method.",
3155+
value_ty.display(db),
3156+
object_ty.display(db)
31263157
));
31273158
}
31283159
}
31293160
false
31303161
}
3131-
SymbolAndQualifiers {
3132-
symbol: Symbol::Type(meta_attr_ty, meta_attr_boundness),
3133-
qualifiers: _,
3134-
} => {
3135-
if is_read_only() {
3136-
if emit_diagnostics {
3137-
if let Some(builder) =
3138-
self.context.report_lint(&INVALID_ASSIGNMENT, target)
3139-
{
3140-
builder.into_diagnostic(format_args!(
3162+
Err(CallDunderError::PossiblyUnbound(_)) => true,
3163+
Err(CallDunderError::MethodNotAvailable) => {
3164+
match object_ty.class_member(db, attribute.into()) {
3165+
meta_attr @ SymbolAndQualifiers { .. } if meta_attr.is_class_var() => {
3166+
if emit_diagnostics {
3167+
if let Some(builder) =
3168+
self.context.report_lint(&INVALID_ATTRIBUTE_ACCESS, target)
3169+
{
3170+
builder.into_diagnostic(format_args!(
3171+
"Cannot assign to ClassVar `{attribute}` \
3172+
from an instance of type `{ty}`",
3173+
ty = object_ty.display(self.db()),
3174+
));
3175+
}
3176+
}
3177+
false
3178+
}
3179+
SymbolAndQualifiers {
3180+
symbol: Symbol::Type(meta_attr_ty, meta_attr_boundness),
3181+
qualifiers: _,
3182+
} => {
3183+
if is_read_only() {
3184+
if emit_diagnostics {
3185+
if let Some(builder) =
3186+
self.context.report_lint(&INVALID_ASSIGNMENT, target)
3187+
{
3188+
builder.into_diagnostic(format_args!(
31413189
"Property `{attribute}` defined in `{ty}` is read-only",
31423190
ty = object_ty.display(self.db()),
31433191
));
3144-
}
3145-
}
3146-
false
3147-
} else {
3148-
let assignable_to_meta_attr = if let Symbol::Type(meta_dunder_set, _) =
3149-
meta_attr_ty.class_member(db, "__set__".into()).symbol
3150-
{
3151-
let successful_call = meta_dunder_set
3152-
.try_call(
3153-
db,
3154-
&CallArgumentTypes::positional([
3155-
meta_attr_ty,
3156-
object_ty,
3157-
value_ty,
3158-
]),
3159-
)
3160-
.is_ok();
3192+
}
3193+
}
3194+
false
3195+
} else {
3196+
let assignable_to_meta_attr =
3197+
if let Symbol::Type(meta_dunder_set, _) =
3198+
meta_attr_ty.class_member(db, "__set__".into()).symbol
3199+
{
3200+
let successful_call = meta_dunder_set
3201+
.try_call(
3202+
db,
3203+
&CallArgumentTypes::positional([
3204+
meta_attr_ty,
3205+
object_ty,
3206+
value_ty,
3207+
]),
3208+
)
3209+
.is_ok();
31613210

3162-
if !successful_call && emit_diagnostics {
3163-
if let Some(builder) =
3164-
self.context.report_lint(&INVALID_ASSIGNMENT, target)
3165-
{
3166-
// TODO: Here, it would be nice to emit an additional diagnostic that explains why the call failed
3167-
builder.into_diagnostic(format_args!(
3211+
if !successful_call && emit_diagnostics {
3212+
if let Some(builder) = self
3213+
.context
3214+
.report_lint(&INVALID_ASSIGNMENT, target)
3215+
{
3216+
// TODO: Here, it would be nice to emit an additional diagnostic that explains why the call failed
3217+
builder.into_diagnostic(format_args!(
31683218
"Invalid assignment to data descriptor attribute \
31693219
`{attribute}` on type `{}` with custom `__set__` method",
31703220
object_ty.display(db)
31713221
));
3172-
}
3173-
}
3222+
}
3223+
}
31743224

3175-
successful_call
3176-
} else {
3177-
ensure_assignable_to(meta_attr_ty)
3178-
};
3225+
successful_call
3226+
} else {
3227+
ensure_assignable_to(meta_attr_ty)
3228+
};
31793229

3180-
let assignable_to_instance_attribute =
3181-
if meta_attr_boundness == Boundness::PossiblyUnbound {
3182-
let (assignable, boundness) = if let Symbol::Type(
3183-
instance_attr_ty,
3184-
instance_attr_boundness,
3185-
) =
3186-
object_ty.instance_member(db, attribute).symbol
3187-
{
3188-
(
3189-
ensure_assignable_to(instance_attr_ty),
3190-
instance_attr_boundness,
3191-
)
3192-
} else {
3193-
(true, Boundness::PossiblyUnbound)
3194-
};
3230+
let assignable_to_instance_attribute =
3231+
if meta_attr_boundness == Boundness::PossiblyUnbound {
3232+
let (assignable, boundness) = if let Symbol::Type(
3233+
instance_attr_ty,
3234+
instance_attr_boundness,
3235+
) =
3236+
object_ty.instance_member(db, attribute).symbol
3237+
{
3238+
(
3239+
ensure_assignable_to(instance_attr_ty),
3240+
instance_attr_boundness,
3241+
)
3242+
} else {
3243+
(true, Boundness::PossiblyUnbound)
3244+
};
3245+
3246+
if boundness == Boundness::PossiblyUnbound {
3247+
report_possibly_unbound_attribute(
3248+
&self.context,
3249+
target,
3250+
attribute,
3251+
object_ty,
3252+
);
3253+
}
3254+
3255+
assignable
3256+
} else {
3257+
true
3258+
};
3259+
3260+
assignable_to_meta_attr && assignable_to_instance_attribute
3261+
}
3262+
}
31953263

3196-
if boundness == Boundness::PossiblyUnbound {
3264+
SymbolAndQualifiers {
3265+
symbol: Symbol::Unbound,
3266+
..
3267+
} => {
3268+
if let Symbol::Type(instance_attr_ty, instance_attr_boundness) =
3269+
object_ty.instance_member(db, attribute).symbol
3270+
{
3271+
if instance_attr_boundness == Boundness::PossiblyUnbound {
31973272
report_possibly_unbound_attribute(
31983273
&self.context,
31993274
target,
@@ -3202,79 +3277,23 @@ impl<'db> TypeInferenceBuilder<'db> {
32023277
);
32033278
}
32043279

3205-
assignable
3206-
} else {
3207-
true
3208-
};
3209-
3210-
assignable_to_meta_attr && assignable_to_instance_attribute
3211-
}
3212-
}
3213-
3214-
SymbolAndQualifiers {
3215-
symbol: Symbol::Unbound,
3216-
..
3217-
} => {
3218-
if let Symbol::Type(instance_attr_ty, instance_attr_boundness) =
3219-
object_ty.instance_member(db, attribute).symbol
3220-
{
3221-
if instance_attr_boundness == Boundness::PossiblyUnbound {
3222-
report_possibly_unbound_attribute(
3223-
&self.context,
3224-
target,
3225-
attribute,
3226-
object_ty,
3227-
);
3228-
}
3229-
3230-
if is_read_only() {
3231-
if emit_diagnostics {
3232-
if let Some(builder) =
3233-
self.context.report_lint(&INVALID_ASSIGNMENT, target)
3234-
{
3235-
builder.into_diagnostic(format_args!(
3280+
if is_read_only() {
3281+
if emit_diagnostics {
3282+
if let Some(builder) = self
3283+
.context
3284+
.report_lint(&INVALID_ASSIGNMENT, target)
3285+
{
3286+
builder.into_diagnostic(format_args!(
32363287
"Property `{attribute}` defined in `{ty}` is read-only",
32373288
ty = object_ty.display(self.db()),
32383289
));
3239-
}
3240-
}
3241-
false
3242-
} else {
3243-
ensure_assignable_to(instance_attr_ty)
3244-
}
3245-
} else {
3246-
let result = object_ty.try_call_dunder_with_policy(
3247-
db,
3248-
"__setattr__",
3249-
&mut CallArgumentTypes::positional([
3250-
Type::StringLiteral(StringLiteralType::new(
3251-
db,
3252-
Box::from(attribute),
3253-
)),
3254-
value_ty,
3255-
]),
3256-
MemberLookupPolicy::MRO_NO_OBJECT_FALLBACK,
3257-
);
3258-
3259-
match result {
3260-
Ok(_) | Err(CallDunderError::PossiblyUnbound(_)) => true,
3261-
Err(CallDunderError::CallError(..)) => {
3262-
if emit_diagnostics {
3263-
if let Some(builder) =
3264-
self.context.report_lint(&UNRESOLVED_ATTRIBUTE, target)
3265-
{
3266-
builder.into_diagnostic(format_args!(
3267-
"Can not assign object of `{}` to attribute \
3268-
`{attribute}` on type `{}` with \
3269-
custom `__setattr__` method.",
3270-
value_ty.display(db),
3271-
object_ty.display(db)
3272-
));
3290+
}
32733291
}
3292+
false
3293+
} else {
3294+
ensure_assignable_to(instance_attr_ty)
32743295
}
3275-
false
3276-
}
3277-
Err(CallDunderError::MethodNotAvailable) => {
3296+
} else {
32783297
if emit_diagnostics {
32793298
if let Some(builder) =
32803299
self.context.report_lint(&UNRESOLVED_ATTRIBUTE, target)
@@ -3286,7 +3305,6 @@ impl<'db> TypeInferenceBuilder<'db> {
32863305
));
32873306
}
32883307
}
3289-
32903308
false
32913309
}
32923310
}

0 commit comments

Comments
 (0)