From ec539b013f99bfb4a28efcb58b73030d44ed1d12 Mon Sep 17 00:00:00 2001 From: Shunsuke Shibayama Date: Fri, 4 Oct 2024 15:57:22 +0900 Subject: [PATCH] fix: type specification bugs --- Cargo.lock | 75 +++++++----- Cargo.toml | 6 +- crates/py2erg/convert.rs | 258 ++++++++++++++++++++++++++------------- tests/class.py | 20 +++ tests/collection.py | 2 +- tests/test.rs | 2 +- tests/typespec.py | 13 ++ 7 files changed, 256 insertions(+), 120 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 52cccf3..ab50241 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -43,9 +43,9 @@ checksum = "86fdf8605db99b54d3cd748a44c6d04df638eb5dafb219b135d0149bd0db01f6" [[package]] name = "autocfg" -version = "1.3.0" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" +checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" [[package]] name = "backtrace" @@ -99,9 +99,9 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "cc" -version = "1.1.21" +version = "1.1.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07b1695e2c7e8fc85310cde85aeaab7e3097f593c91d209d3f9df76c928100f0" +checksum = "812acba72f0a070b003d3697490d2b55b837230ae7c6c6497f05cc2ddbb8d938" dependencies = [ "shlex", ] @@ -134,7 +134,7 @@ dependencies = [ "proc-macro2", "quote", "rustc_version", - "syn 2.0.77", + "syn 2.0.79", ] [[package]] @@ -145,9 +145,9 @@ checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" [[package]] name = "els" -version = "0.1.57-nightly.3" +version = "0.1.58-nightly.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa300ad75154fdc24c02e66148c5fb15aff48a2cfe8dd18191deb239ba5bcc64" +checksum = "eed2c90d92d8be15be9e928f06d34e0cfe03c8c10e6351326859cecf3789dcac" dependencies = [ "erg_common", "erg_compiler", @@ -159,9 +159,9 @@ dependencies = [ [[package]] name = "erg_common" -version = "0.6.45-nightly.3" +version = "0.6.46-nightly.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a750b2538983b9a967f1d8af9dddfc23d2a75f1c84ecaeb88e171dcb047c185" +checksum = "4758c25017a49a7f3d8cb3287360deae39c696936a6747cf9e3d9f81cb94c010" dependencies = [ "backtrace-on-stack-overflow", "erg_proc_macros", @@ -172,9 +172,9 @@ dependencies = [ [[package]] name = "erg_compiler" -version = "0.6.45-nightly.3" +version = "0.6.46-nightly.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e65b36a8419d694b11effc1e123d9ff16ac50d677950d9b60f47e8bc2429be7b" +checksum = "8c5c7fad1c74774dcbc293b79bb62a024135fcde4faf13411a3490761cb71a98" dependencies = [ "erg_common", "erg_parser", @@ -182,9 +182,9 @@ dependencies = [ [[package]] name = "erg_parser" -version = "0.6.45-nightly.3" +version = "0.6.46-nightly.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ec2dd2b5827961fffe7bdbc253a904de0104d0b7677a61faa3c9e47d21aac5e" +checksum = "c564e2914429af720277cb61256362762790da8c635558f77c4d6ae4c3a64f3a" dependencies = [ "erg_common", "erg_proc_macros", @@ -193,9 +193,9 @@ dependencies = [ [[package]] name = "erg_proc_macros" -version = "0.6.45-nightly.3" +version = "0.6.46-nightly.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4df44f047bae2eae631309bb3f692daaa0a9724eca8e59104cdf57336c55ad45" +checksum = "3fac38f9d18406130093186708186dad6f59efc04b0eddc0a8d0364be9361a90" dependencies = [ "quote", "syn 1.0.109", @@ -264,7 +264,7 @@ dependencies = [ "Inflector", "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.79", ] [[package]] @@ -290,9 +290,9 @@ checksum = "507460a910eb7b32ee961886ff48539633b788a36b65692b95f225b844c82553" [[package]] name = "libc" -version = "0.2.158" +version = "0.2.159" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8adc4bb1803a324070e64a98ae98f38934d91957a99cfb3a43dcbc01bc56439" +checksum = "561d97a539a36e26a9a5fad1ea11a3039a67714694aaa379433e580854bc3dc5" [[package]] name = "libm" @@ -464,9 +464,12 @@ dependencies = [ [[package]] name = "once_cell" -version = "1.19.0" +version = "1.20.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" +checksum = "82881c4be219ab5faaf2ad5e5e5ecdff8c66bd7402ca3160975c93b24961afd1" +dependencies = [ + "portable-atomic", +] [[package]] name = "parking_lot" @@ -541,6 +544,12 @@ dependencies = [ "siphasher", ] +[[package]] +name = "portable-atomic" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc9c68a3f6da06753e9335d63e27f6b9754dd1920d941135b7ea8224f141adb2" + [[package]] name = "ppv-lite86" version = "0.2.20" @@ -641,9 +650,9 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.5.4" +version = "0.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0884ad60e090bf1345b93da0a5de8923c93884cd03f40dfcfddd3b4bee661853" +checksum = "9b6dfecf2c74bce2466cabf93f6664d6998a69eb21e39f4207930065b27b771f" dependencies = [ "bitflags 2.6.0", ] @@ -757,7 +766,7 @@ checksum = "243902eda00fad750862fc144cea25caca5e20d615af0a81bee94ca738f1df1f" dependencies = [ "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.79", ] [[package]] @@ -780,7 +789,7 @@ checksum = "6c64451ba24fc7a6a2d60fc75dd9c83c90903b19028d4eff35e88fc1e86564e9" dependencies = [ "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.79", ] [[package]] @@ -820,9 +829,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.77" +version = "2.0.79" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f35bcdf61fd8e7be6caf75f429fdca8beb3ed76584befb503b1569faee373ed" +checksum = "89132cd0bf050864e1d38dc3bbc07a0eb8e7530af26344d3d2bbbef83499f590" dependencies = [ "proc-macro2", "quote", @@ -917,9 +926,9 @@ dependencies = [ [[package]] name = "unicode-bidi" -version = "0.3.15" +version = "0.3.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08f95100a766bf4f8f28f90d77e0a5461bbdb219042e7679bebe79004fed8d75" +checksum = "5ab17db44d7388991a428b2ee655ce0c212e862eff1768a455c58f9aad6e7893" [[package]] name = "unicode-ident" @@ -1025,7 +1034,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.79", "wasm-bindgen-shared", ] @@ -1047,7 +1056,7 @@ checksum = "afc340c74d9005395cf9dd098506f7f44e38f2b4a21c6aaacf9a105ea5e1e836" dependencies = [ "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.79", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -1089,7 +1098,7 @@ checksum = "2bbd5b46c938e506ecbce286b6628a02171d56153ba733b6c741fc627ec9579b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.79", ] [[package]] @@ -1100,7 +1109,7 @@ checksum = "053c4c462dc91d3b1504c6fe5a726dd15e216ba718e84a0e46a88fbe5ded3515" dependencies = [ "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.79", ] [[package]] @@ -1204,5 +1213,5 @@ checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.79", ] diff --git a/Cargo.toml b/Cargo.toml index 04811c1..542f9a0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -24,9 +24,9 @@ edition = "2021" repository = "https://github.com/mtshiba/pylyzer" [workspace.dependencies] -erg_common = { version = "0.6.45-nightly.3", features = ["py_compat", "els"] } -erg_compiler = { version = "0.6.45-nightly.3", features = ["py_compat", "els"] } -els = { version = "0.1.57-nightly.3", features = ["py_compat"] } +erg_common = { version = "0.6.46-nightly.1", features = ["py_compat", "els"] } +erg_compiler = { version = "0.6.46-nightly.1", features = ["py_compat", "els"] } +els = { version = "0.1.58-nightly.1", features = ["py_compat"] } # rustpython-parser = { version = "0.3.0", features = ["all-nodes-with-ranges", "location"] } # rustpython-ast = { version = "0.3.0", features = ["all-nodes-with-ranges", "location"] } rustpython-parser = { git = "https://github.com/RustPython/Parser", version = "0.4.0", features = ["all-nodes-with-ranges", "location"] } diff --git a/crates/py2erg/convert.rs b/crates/py2erg/convert.rs index 141b75b..7ac903d 100644 --- a/crates/py2erg/convert.rs +++ b/crates/py2erg/convert.rs @@ -9,15 +9,16 @@ use erg_common::traits::{Locational, Stream}; use erg_common::{fmt_vec, log, set}; use erg_compiler::artifact::IncompleteArtifact; use erg_compiler::erg_parser::ast::{ - Accessor, Args, BinOp, Block, ClassAttr, ClassAttrs, ClassDef, ConstAccessor, ConstArgs, - ConstAttribute, ConstDict, ConstExpr, ConstKeyValue, ConstPosArg, Decorator, Def, DefBody, - DefId, DefaultParamSignature, Dict, Dummy, Expr, Identifier, KeyValue, KwArg, Lambda, - LambdaSignature, List, ListComprehension, Literal, Methods, Module, NonDefaultParamSignature, - NormalDict, NormalList, NormalRecord, NormalSet, NormalTuple, ParamPattern, ParamTySpec, - Params, PosArg, PreDeclTypeSpec, ReDef, Record, RecordAttrs, Set, SetComprehension, Signature, - SubrSignature, SubrTypeSpec, Tuple, TupleTypeSpec, TypeAscription, TypeBoundSpec, - TypeBoundSpecs, TypeSpec, TypeSpecWithOp, UnaryOp, VarName, VarPattern, VarRecordAttr, - VarRecordAttrs, VarRecordPattern, VarSignature, VisModifierSpec, + Accessor, Args, BinOp, Block, ClassAttr, ClassAttrs, ClassDef, ConstAccessor, ConstApp, + ConstArgs, ConstAttribute, ConstBinOp, ConstBlock, ConstDict, ConstExpr, ConstKeyValue, + ConstLambda, ConstList, ConstListWithLength, ConstNormalSet, ConstPosArg, ConstSet, Decorator, + Def, DefBody, DefId, DefaultParamSignature, Dict, Dummy, Expr, Identifier, KeyValue, KwArg, + Lambda, LambdaSignature, List, ListComprehension, Literal, Methods, Module, + NonDefaultParamSignature, NormalDict, NormalList, NormalRecord, NormalSet, NormalTuple, + ParamPattern, ParamTySpec, Params, PosArg, PreDeclTypeSpec, ReDef, Record, RecordAttrs, Set, + SetComprehension, Signature, SubrSignature, SubrTypeSpec, Tuple, TupleTypeSpec, TypeAscription, + TypeBoundSpec, TypeBoundSpecs, TypeSpec, TypeSpecWithOp, UnaryOp, VarName, VarPattern, + VarRecordAttr, VarRecordAttrs, VarRecordPattern, VarSignature, VisModifierSpec, }; use erg_compiler::erg_parser::desugar::Desugarer; use erg_compiler::erg_parser::token::{Token, TokenKind, COLON, DOT, EQUAL}; @@ -693,6 +694,152 @@ impl ASTConverter { )) } + #[allow(clippy::only_used_in_recursion)] + fn convert_const_expr(&self, expr: ConstExpr) -> ConstExpr { + match expr { + ConstExpr::UnaryOp(un) if un.op.is(TokenKind::Mutate) => *un.expr, + ConstExpr::App(app) + if app + .attr_name + .as_ref() + .is_some_and(|n| n.inspect() == "__getitem__") => + { + let obj = self.convert_const_expr(*app.obj); + let mut args = app.args.map(&mut |arg| self.convert_const_expr(arg)); + if args.pos_args.is_empty() { + return ConstExpr::App(ConstApp::new(obj, app.attr_name, args)); + } + let mut args = match args.pos_args.remove(0).expr { + ConstExpr::Tuple(tuple) => tuple.elems, + other => { + args.pos_args.insert(0, ConstPosArg::new(other)); + args + } + }; + match obj.local_name() { + Some("Union") => { + if args.pos_args.len() >= 2 { + let first = args.pos_args.remove(0).expr; + let or_op = Token::dummy(TokenKind::OrOp, "or"); + args.pos_args.into_iter().fold(first, |acc, expr| { + ConstExpr::BinOp(ConstBinOp::new(or_op.clone(), acc, expr.expr)) + }) + } else if args.pos_args.len() == 1 { + args.pos_args.remove(0).expr + } else { + ConstExpr::App(ConstApp::new(obj, app.attr_name, args)) + } + } + Some("GenericDict") => { + if args.pos_args.len() == 2 { + let key = args.pos_args.remove(0).expr; + let value = args.pos_args.remove(0).expr; + let key_value = ConstKeyValue::new(key, value); + ConstExpr::Dict(ConstDict::new( + Token::DUMMY, + Token::DUMMY, + vec![key_value], + )) + } else { + ConstExpr::App(ConstApp::new(obj, app.attr_name, args)) + } + } + Some("GenericList") => { + if args.pos_args.len() == 2 { + let elem = args.pos_args.remove(0).expr; + let len = args.pos_args.remove(0).expr; + let l_brace = Token::dummy(TokenKind::LSqBr, "["); + let r_brace = Token::dummy(TokenKind::RSqBr, "]"); + ConstExpr::List(ConstList::WithLength(ConstListWithLength::new( + l_brace, r_brace, elem, len, + ))) + } else { + let obj = ConstExpr::Accessor(ConstAccessor::Local( + Identifier::private("List".into()), + )); + ConstExpr::App(ConstApp::new(obj, None, args)) + } + } + Some("Optional") => { + let arg = args.pos_args.remove(0).expr; + let none = ConstExpr::Accessor(ConstAccessor::Local(Identifier::private( + "NoneType".into(), + ))); + let or_op = Token::dummy(TokenKind::OrOp, "or"); + ConstExpr::BinOp(ConstBinOp::new(or_op, arg, none)) + } + Some("Literal") => { + let set = ConstNormalSet::new(Token::DUMMY, Token::DUMMY, args); + ConstExpr::Set(ConstSet::Normal(set)) + } + Some("Callable") => { + let params = match args.pos_args.remove(0).expr { + ConstExpr::List(ConstList::Normal(list)) => list.elems, + other => { + args.pos_args.insert(0, ConstPosArg::new(other)); + args.clone() + } + }; + let non_defaults = params + .pos_args + .into_iter() + .map(|param| { + let expr = match param.expr.downgrade() { + Expr::Literal(lit) if lit.is(TokenKind::NoneLit) => { + Expr::Accessor(Accessor::Ident(Identifier::private( + "NoneType".into(), + ))) + } + other => other, + }; + let ty = Parser::expr_to_type_spec(expr.clone()) + .unwrap_or(TypeSpec::mono(Identifier::private("Any".into()))); + let discard = Token::dummy(TokenKind::UBar, "_"); + let t_spec = TypeSpecWithOp::new( + Token::dummy(TokenKind::Colon, ":"), + ty, + expr, + ); + NonDefaultParamSignature::new( + ParamPattern::Discard(discard), + Some(t_spec), + ) + }) + .collect(); + let params = Params::new(non_defaults, None, vec![], None, None); + let ret = match args.pos_args.remove(0).expr { + ConstExpr::Lit(lit) if lit.is(TokenKind::NoneLit) => { + ConstExpr::Accessor(ConstAccessor::Local(Identifier::private( + "NoneType".into(), + ))) + } + other => other, + }; + let op = Token::dummy(TokenKind::ProcArrow, "=>"); + let body = ConstBlock::new(vec![ret]); + let sig = LambdaSignature::new(params, None, TypeBoundSpecs::empty()); + ConstExpr::Lambda(ConstLambda::new(sig, op, body, DefId(0))) + } + _ => ConstExpr::App(ConstApp::new(obj, app.attr_name, args)), + } + } + _ => expr.map(&mut |expr| self.convert_const_expr(expr)), + } + } + + fn convert_expr_to_const(&mut self, expr: py_ast::Expr) -> Option { + let expr = self.convert_expr(expr); + match Parser::validate_const_expr(expr) { + Ok(expr) => Some(self.convert_const_expr(expr)), + Err(err) => { + let err = + CompileError::new(err.into(), self.cfg.input.clone(), self.cur_namespace()); + self.errs.push(err); + None + } + } + } + // TODO: fn convert_compound_type_spec(&mut self, name: String, args: py_ast::Expr) -> TypeSpec { match &name[..] { @@ -731,19 +878,8 @@ impl ASTConverter { }; let mut elems = vec![]; for elem in tuple.elts { - let expr = self.convert_expr(elem); - match Parser::validate_const_expr(expr) { - Ok(expr) => { - elems.push(ConstPosArg::new(expr)); - } - Err(err) => { - let err = CompileError::new( - err.into(), - self.cfg.input.clone(), - self.cur_namespace(), - ); - self.errs.push(err); - } + if let Some(expr) = self.convert_expr_to_const(elem) { + elems.push(ConstPosArg::new(expr)); } } let elems = ConstArgs::new(elems, None, vec![], None, None); @@ -789,16 +925,9 @@ impl ASTConverter { } "Iterable" | "Iterator" | "Collection" | "Container" | "Sequence" | "MutableSequence" => { - let elem_t = self.convert_expr(args); - let elem_t = match Parser::validate_const_expr(elem_t) { - Ok(elem_t) => elem_t, - Err(err) => { - let err = CompileError::new( - err.into(), - self.cfg.input.clone(), - self.cur_namespace(), - ); - self.errs.push(err); + let elem_t = match self.convert_expr_to_const(args) { + Some(elem_t) => elem_t, + None => { ConstExpr::Accessor(ConstAccessor::Local(Identifier::private("Obj".into()))) } }; @@ -824,30 +953,16 @@ impl ASTConverter { self.errs.push(err); return Self::gen_dummy_type_spec(args.location()); }; - let key_t = self.convert_expr(tuple.elts.remove(0)); - let key_t = match Parser::validate_const_expr(key_t) { - Ok(key_t) => key_t, - Err(err) => { - let err = CompileError::new( - err.into(), - self.cfg.input.clone(), - self.cur_namespace(), - ); - self.errs.push(err); + let key_t = match self.convert_expr_to_const(tuple.elts.remove(0)) { + Some(key_t) => key_t, + None => { ConstExpr::Accessor(ConstAccessor::Local(Identifier::private("Obj".into()))) } }; let key_t = ConstPosArg::new(key_t); - let value_t = self.convert_expr(tuple.elts.remove(0)); - let value_t = match Parser::validate_const_expr(value_t) { - Ok(value_t) => value_t, - Err(err) => { - let err = CompileError::new( - err.into(), - self.cfg.input.clone(), - self.cur_namespace(), - ); - self.errs.push(err); + let value_t = match self.convert_expr_to_const(tuple.elts.remove(0)) { + Some(value_t) => value_t, + None => { ConstExpr::Accessor(ConstAccessor::Local(Identifier::private("Obj".into()))) } }; @@ -864,16 +979,9 @@ impl ASTConverter { let len = ConstExpr::Accessor(ConstAccessor::Local( self.convert_ident("_".into(), args.location()), )); - let elem_t = self.convert_expr(args); - let elem_t = match Parser::validate_const_expr(elem_t) { - Ok(elem_t) => elem_t, - Err(err) => { - let err = CompileError::new( - err.into(), - self.cfg.input.clone(), - self.cur_namespace(), - ); - self.errs.push(err); + let elem_t = match self.convert_expr_to_const(args) { + Some(elem_t) => elem_t, + None => { ConstExpr::Accessor(ConstAccessor::Local(Identifier::private("Obj".into()))) } }; @@ -895,29 +1003,15 @@ impl ASTConverter { return Self::gen_dummy_type_spec(args.location()); }; let (l_brace, r_brace) = Self::gen_enclosure_tokens(TokenKind::LBrace, tuple.range); - let key_t = self.convert_expr(tuple.elts.remove(0)); - let key_t = match Parser::validate_const_expr(key_t) { - Ok(key_t) => key_t, - Err(err) => { - let err = CompileError::new( - err.into(), - self.cfg.input.clone(), - self.cur_namespace(), - ); - self.errs.push(err); + let key_t = match self.convert_expr_to_const(tuple.elts.remove(0)) { + Some(key_t) => key_t, + None => { ConstExpr::Accessor(ConstAccessor::Local(Identifier::private("Obj".into()))) } }; - let val_t = self.convert_expr(tuple.elts.remove(0)); - let val_t = match Parser::validate_const_expr(val_t) { - Ok(val_t) => val_t, - Err(err) => { - let err = CompileError::new( - err.into(), - self.cfg.input.clone(), - self.cur_namespace(), - ); - self.errs.push(err); + let val_t = match self.convert_expr_to_const(tuple.elts.remove(0)) { + Some(val_t) => val_t, + None => { ConstExpr::Accessor(ConstAccessor::Local(Identifier::private("Obj".into()))) } }; diff --git a/tests/class.py b/tests/class.py index f425fa9..24edc40 100644 --- a/tests/class.py +++ b/tests/class.py @@ -78,3 +78,23 @@ def foo(self): g = G() assert g.foo() == 1 + +class Value: + value: object + +class H(Value): + value: int + + def __init__(self, value): + self.value = value + + def incremented(self): + return H(self.value + 1) + +class MyList(list): + @staticmethod + def try_new(lis) -> "MyList" | None: + if isinstance(lis, list): + return MyList(lis) + else: + return None diff --git a/tests/collection.py b/tests/collection.py index 66ec660..6ee7d90 100644 --- a/tests/collection.py +++ b/tests/collection.py @@ -9,7 +9,7 @@ union_arr.append("a") # OK union_arr.append(None) # ERR -dic = {"a": 1} +dic: dict[Literal["a", "b"], int] = {"a": 1} dic["b"] = 2 _ = dic["a"] _ = dic["b"] diff --git a/tests/test.rs b/tests/test.rs index 71a0458..b6ce673 100644 --- a/tests/test.rs +++ b/tests/test.rs @@ -104,7 +104,7 @@ fn exec_warns() -> Result<(), String> { #[test] fn exec_typespec() -> Result<(), String> { - expect("tests/typespec.py", 0, 7) + expect("tests/typespec.py", 0, 13) } #[test] diff --git a/tests/typespec.py b/tests/typespec.py index eb68867..5de6b0a 100644 --- a/tests/typespec.py +++ b/tests/typespec.py @@ -9,6 +9,19 @@ p: Optional[int] = "a" # ERR weekdays: Literal[1, 2, 3, 4, 5, 6, 7] = 1 # OK weekdays: Literal[1, 2, 3, 4, 5, 6, 7] = 8 # ERR +_: dict[str, dict[str, Union[int, str]]] = {"a": {"b": 1}} +_: dict[str, dict[str, list[int]]] = {"a": {"b": [1]}} +_: dict[str, dict[str, dict[str, int]]] = {"a": {"b": {"c": 1}}} +_: dict[str, dict[str, Optional[int]]] = {"a": {"b": 1}} +_: dict[str, dict[str, Literal[1, 2]]] = {"a": {"b": 1}} +_: dict[str, dict[str, Callable[[int], int]]] = {"a": {"b": abs}} +_: dict[str, dict[str, Callable[[int], None]]] = {"a": {"b": print}} +_: dict[str, dict[str, Opional[int]]] = {"a": {"b": 1}} # ERR +_: dict[str, dict[str, Union[int, str]]] = {"a": {"b": None}} # ERR +_: dict[str, dict[str, list[int]]] = {"a": {"b": ["c"]}} # ERR +_: dict[str, dict[str, Callable[[int], int]]] = {"a": {"b": print}} # ERR +_: dict[str, dict[str, Optional[int]]] = {"a": {"b": "c"}} # ERR +_: dict[str, dict[str, Literal[1, 2]]] = {"a": {"b": 3}} # ERR def f(x: Union[int, str]) -> None: pass