Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 6 additions & 50 deletions conformance/third_party/conformance.exp
Original file line number Diff line number Diff line change
Expand Up @@ -9862,39 +9862,6 @@
"stop_column": 26,
"stop_line": 76
},
{
"code": -2,
"column": 16,
"concise_description": "assert_type(type, type[Any]) failed",
"description": "assert_type(type, type[Any]) failed",
"line": 84,
"name": "assert-type",
"severity": "error",
"stop_column": 30,
"stop_line": 84
},
{
"code": -2,
"column": 17,
"concise_description": "Object of class `type` has no attribute `unknown`",
"description": "Object of class `type` has no attribute `unknown`",
"line": 99,
"name": "missing-attribute",
"severity": "error",
"stop_column": 26,
"stop_line": 99
},
{
"code": -2,
"column": 17,
"concise_description": "Object of class `type` has no attribute `unknown`",
"description": "Object of class `type` has no attribute `unknown`",
"line": 100,
"name": "missing-attribute",
"severity": "error",
"stop_column": 26,
"stop_line": 100
},
{
"code": -2,
"column": 5,
Expand All @@ -9917,22 +9884,11 @@
"stop_column": 14,
"stop_line": 120
},
{
"code": -2,
"column": 16,
"concise_description": "assert_type(type, type[Any]) failed",
"description": "assert_type(type, type[Any]) failed",
"line": 139,
"name": "assert-type",
"severity": "error",
"stop_column": 30,
"stop_line": 139
},
{
"code": -2,
"column": 1,
"concise_description": "TODO: Expr::attr_infer_for_type attribute base undefined for type: TypeAlias[TA1, type[type[Unknown]]] (trying to access unknown)",
"description": "TODO: Expr::attr_infer_for_type attribute base undefined for type: TypeAlias[TA1, type[type[Unknown]]] (trying to access unknown)",
"concise_description": "TODO: Expr::attr_infer_for_type attribute base undefined for type: TypeAlias[TA1, type[type]] (trying to access unknown)",
"description": "TODO: Expr::attr_infer_for_type attribute base undefined for type: TypeAlias[TA1, type[type]] (trying to access unknown)",
"line": 143,
"name": "missing-attribute",
"severity": "error",
Expand All @@ -9953,8 +9909,8 @@
{
"code": -2,
"column": 1,
"concise_description": "Class `type` has no class attribute `unknown`",
"description": "Class `type` has no class attribute `unknown`",
"concise_description": "TODO: Expr::attr_infer_for_type attribute base undefined for type: TypeAlias[TA3, type[type]] (trying to access unknown)",
"description": "TODO: Expr::attr_infer_for_type attribute base undefined for type: TypeAlias[TA3, type[type]] (trying to access unknown)",
"line": 145,
"name": "missing-attribute",
"severity": "error",
Expand Down Expand Up @@ -10579,8 +10535,8 @@
{
"code": -2,
"column": 7,
"concise_description": "Typed dictionary definitions may not specify a metaclass",
"description": "Typed dictionary definitions may not specify a metaclass",
"concise_description": "Metaclass of `BadTypedDict2` has type `type` that is not a simple class type",
"description": "Metaclass of `BadTypedDict2` has type `type` that is not a simple class type",
"line": 44,
"name": "invalid-inheritance",
"severity": "error",
Expand Down
6 changes: 1 addition & 5 deletions conformance/third_party/conformance.result
Original file line number Diff line number Diff line change
Expand Up @@ -280,11 +280,7 @@
"specialtypes_none.py": [],
"specialtypes_promotions.py": [],
"specialtypes_type.py": [
"Line 70: Expected 1 errors",
"Line 84: Unexpected errors ['assert_type(type, type[Any]) failed']",
"Line 99: Unexpected errors ['Object of class `type` has no attribute `unknown`']",
"Line 100: Unexpected errors ['Object of class `type` has no attribute `unknown`']",
"Line 139: Unexpected errors ['assert_type(type, type[Any]) failed']"
"Line 70: Expected 1 errors"
],
"tuples_type_compat.py": [],
"tuples_type_form.py": [],
Expand Down
4 changes: 2 additions & 2 deletions conformance/third_party/results.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"pass": 106,
"fail": 32,
"pass_rate": 0.77,
"differences": 133,
"differences": 129,
"passing": [
"aliases_explicit.py",
"aliases_newtype.py",
Expand Down Expand Up @@ -144,7 +144,7 @@
"qualifiers_annotated.py": 6,
"qualifiers_final_annotation.py": 7,
"specialtypes_never.py": 1,
"specialtypes_type.py": 5
"specialtypes_type.py": 1
},
"comment": "@generated"
}
1 change: 1 addition & 0 deletions crates/pyrefly_types/src/display.rs
Original file line number Diff line number Diff line change
Expand Up @@ -708,6 +708,7 @@ impl<'a> TypeDisplayContext<'a> {
output.write_str(ta.name.as_str())
}
}
Type::Type(box Type::Any(AnyStyle::Implicit)) => output.write_str("type"),
Type::Type(ty) => {
output.write_str("type[")?;
self.fmt_helper_generic(ty, false, output)?;
Expand Down
13 changes: 13 additions & 0 deletions pyrefly/lib/alt/class/class_metadata.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ use pyrefly_types::type_var::Restriction;
use pyrefly_types::typed_dict::ExtraItem;
use pyrefly_types::typed_dict::ExtraItems;
use pyrefly_types::typed_dict::TypedDict;
use pyrefly_types::types::AnyStyle;
use pyrefly_types::types::Forallable;
use pyrefly_util::display::DisplayWithCtx;
use pyrefly_util::prelude::SliceExt;
Expand Down Expand Up @@ -914,6 +915,18 @@ impl<'a, Ans: LookupAnswer> AnswersSolver<'a, Ans> {
}
}
}
Type::Type(box Type::Any(AnyStyle::Implicit)) => {
// `type[Any]` is canoicalized from `type` or `Type`
let type_obj = self.stdlib.builtins_type().class_object();
let metadata = self.get_metadata_for_class(type_obj);
BaseClassParseResult::Parsed({
ParsedBaseClass {
class_object: type_obj.dupe(),
range,
metadata,
}
})
}
_ => {
if is_new_type || !ty.is_any() {
BaseClassParseResult::InvalidType(ty, range)
Expand Down
6 changes: 6 additions & 0 deletions pyrefly/lib/alt/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1289,12 +1289,18 @@ impl<'a, Ans: LookupAnswer> AnswersSolver<'a, Ans> {
Type::ClassDef(cls) => {
if cls.is_builtin("tuple") {
*ty = Type::type_form(Type::unbounded_tuple(Type::Any(AnyStyle::Implicit)));
} else if cls.is_builtin("type") {
// type is equivalent to type[Any]
*ty = Type::type_form(Type::type_form(Type::Any(AnyStyle::Implicit)));
} else if cls.has_toplevel_qname("typing", "Any") {
*ty = Type::type_form(Type::any_explicit())
} else {
*ty = Type::type_form(self.promote(cls, range, errors));
}
}
Type::ClassType(cls) if cls.is_builtin("type") => {
*ty = Type::type_form(Type::Any(AnyStyle::Implicit));
}
_ => {}
})
}
Expand Down
8 changes: 8 additions & 0 deletions pyrefly/lib/alt/types/class_bases.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ use pyrefly_python::short_identifier::ShortIdentifier;
use pyrefly_types::class::ClassType;
use pyrefly_types::special_form::SpecialForm;
use pyrefly_types::typed_dict::TypedDict;
use pyrefly_types::types::AnyStyle;
use pyrefly_util::display::commas_iter;
use ruff_python_ast::Expr;
use ruff_text_size::Ranged;
Expand Down Expand Up @@ -299,6 +300,13 @@ impl<'a, Ans: LookupAnswer> AnswersSolver<'a, Ans> {
}
}
}
(Type::Type(box Type::Any(AnyStyle::Implicit)), range) => {
// `type` is canonicalized to `Type[Any]`, so we need to handle it here.
let class = self.stdlib.builtins_type().clone();
let bases = self
.get_base_types_for_class(self.stdlib.builtins_type().class_object());
Some((class, bases, range))
}
(_, _) => None,
}
})
Expand Down
15 changes: 14 additions & 1 deletion pyrefly/lib/test/simple.rs
Original file line number Diff line number Diff line change
Expand Up @@ -844,6 +844,19 @@ c2: type[C, C] = C # E: Expected 1 type argument for `type`, got 2
"#,
);

testcase!(
test_type_without_argument_is_equivalent_to_type_any,
r#"
from typing import assert_type, Any
def f(x: type) -> None:
g(x)
assert_type(x, type[Any])
def g(x: type[Any]) -> None:
f(x)
assert_type(x, type)
"#,
);

testcase!(
test_annotated,
r#"
Expand Down Expand Up @@ -1402,7 +1415,7 @@ def g(x: type) -> None: ...
f(int)
f(Type)
f(type)
f(42) # E: not assignable to parameter `x` with type `type[Unknown]`
f(42) # E: not assignable to parameter `x` with type `type`

g(int)
g(Type)
Expand Down
Loading