From 5f65e842e8559198c114c5731768c313fcce52c6 Mon Sep 17 00:00:00 2001 From: Micha Reiser Date: Tue, 15 Oct 2024 13:06:32 +0200 Subject: [PATCH] Upgrade salsa (#13757) --- Cargo.lock | 6 +- Cargo.toml | 2 +- crates/red_knot/tests/file_watching.rs | 69 ++++++++--- .../src/module_resolver/resolver.rs | 114 +++++++++--------- .../src/semantic_model.rs | 2 +- crates/red_knot_python_semantic/src/stdlib.rs | 4 +- crates/red_knot_python_semantic/src/types.rs | 20 +-- .../src/types/builder.rs | 2 +- .../src/types/display.rs | 8 +- .../src/types/infer.rs | 28 ++--- crates/red_knot_workspace/src/lint.rs | 2 +- crates/ruff_graph/src/resolver.rs | 6 +- 12 files changed, 143 insertions(+), 120 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 965a28362d..ce8524b873 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3009,7 +3009,7 @@ checksum = "e86697c916019a8588c99b5fac3cead74ec0b4b819707a682fd4d23fa0ce1ba1" [[package]] name = "salsa" version = "0.18.0" -source = "git+https://github.com/salsa-rs/salsa.git?rev=4a7c955255e707e64e43f3ce5eabb771ae067768#4a7c955255e707e64e43f3ce5eabb771ae067768" +source = "git+https://github.com/salsa-rs/salsa.git?rev=b14be5c0392f4c55eca60b92e457a35549372382#b14be5c0392f4c55eca60b92e457a35549372382" dependencies = [ "append-only-vec", "arc-swap", @@ -3029,12 +3029,12 @@ dependencies = [ [[package]] name = "salsa-macro-rules" version = "0.1.0" -source = "git+https://github.com/salsa-rs/salsa.git?rev=4a7c955255e707e64e43f3ce5eabb771ae067768#4a7c955255e707e64e43f3ce5eabb771ae067768" +source = "git+https://github.com/salsa-rs/salsa.git?rev=b14be5c0392f4c55eca60b92e457a35549372382#b14be5c0392f4c55eca60b92e457a35549372382" [[package]] name = "salsa-macros" version = "0.18.0" -source = "git+https://github.com/salsa-rs/salsa.git?rev=4a7c955255e707e64e43f3ce5eabb771ae067768#4a7c955255e707e64e43f3ce5eabb771ae067768" +source = "git+https://github.com/salsa-rs/salsa.git?rev=b14be5c0392f4c55eca60b92e457a35549372382#b14be5c0392f4c55eca60b92e457a35549372382" dependencies = [ "heck", "proc-macro2", diff --git a/Cargo.toml b/Cargo.toml index 234ac4dc7a..57c0712e48 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -117,7 +117,7 @@ rayon = { version = "1.10.0" } regex = { version = "1.10.2" } rstest = { version = "0.22.0", default-features = false } rustc-hash = { version = "2.0.0" } -salsa = { git = "https://github.com/salsa-rs/salsa.git", rev = "4a7c955255e707e64e43f3ce5eabb771ae067768" } +salsa = { git = "https://github.com/salsa-rs/salsa.git", rev = "b14be5c0392f4c55eca60b92e457a35549372382" } schemars = { version = "0.8.16" } seahash = { version = "4.1.0" } serde = { version = "1.0.197", features = ["derive"] } diff --git a/crates/red_knot/tests/file_watching.rs b/crates/red_knot/tests/file_watching.rs index 3b27aacf63..8067214235 100644 --- a/crates/red_knot/tests/file_watching.rs +++ b/crates/red_knot/tests/file_watching.rs @@ -501,7 +501,10 @@ fn directory_moved_to_workspace() -> anyhow::Result<()> { .with_context(|| "Failed to create __init__.py")?; std::fs::write(a_original_path.as_std_path(), "").with_context(|| "Failed to create a.py")?; - let sub_a_module = resolve_module(case.db().upcast(), ModuleName::new_static("sub.a").unwrap()); + let sub_a_module = resolve_module( + case.db().upcast(), + &ModuleName::new_static("sub.a").unwrap(), + ); assert_eq!(sub_a_module, None); assert_eq!( @@ -525,7 +528,11 @@ fn directory_moved_to_workspace() -> anyhow::Result<()> { .expect("a.py to exist"); // `import sub.a` should now resolve - assert!(resolve_module(case.db().upcast(), ModuleName::new_static("sub.a").unwrap()).is_some()); + assert!(resolve_module( + case.db().upcast(), + &ModuleName::new_static("sub.a").unwrap() + ) + .is_some()); assert_eq!( case.collect_package_files(&case.workspace_path("bar.py")), @@ -544,7 +551,11 @@ fn directory_moved_to_trash() -> anyhow::Result<()> { ])?; let bar = case.system_file(case.workspace_path("bar.py")).unwrap(); - assert!(resolve_module(case.db().upcast(), ModuleName::new_static("sub.a").unwrap()).is_some()); + assert!(resolve_module( + case.db().upcast(), + &ModuleName::new_static("sub.a").unwrap() + ) + .is_some()); let sub_path = case.workspace_path("sub"); let init_file = case @@ -569,7 +580,11 @@ fn directory_moved_to_trash() -> anyhow::Result<()> { case.apply_changes(changes); // `import sub.a` should no longer resolve - assert!(resolve_module(case.db().upcast(), ModuleName::new_static("sub.a").unwrap()).is_none()); + assert!(resolve_module( + case.db().upcast(), + &ModuleName::new_static("sub.a").unwrap() + ) + .is_none()); assert!(!init_file.exists(case.db())); assert!(!a_file.exists(case.db())); @@ -592,10 +607,14 @@ fn directory_renamed() -> anyhow::Result<()> { let bar = case.system_file(case.workspace_path("bar.py")).unwrap(); - assert!(resolve_module(case.db().upcast(), ModuleName::new_static("sub.a").unwrap()).is_some()); assert!(resolve_module( case.db().upcast(), - ModuleName::new_static("foo.baz").unwrap() + &ModuleName::new_static("sub.a").unwrap() + ) + .is_some()); + assert!(resolve_module( + case.db().upcast(), + &ModuleName::new_static("foo.baz").unwrap() ) .is_none()); @@ -623,11 +642,15 @@ fn directory_renamed() -> anyhow::Result<()> { case.apply_changes(changes); // `import sub.a` should no longer resolve - assert!(resolve_module(case.db().upcast(), ModuleName::new_static("sub.a").unwrap()).is_none()); + assert!(resolve_module( + case.db().upcast(), + &ModuleName::new_static("sub.a").unwrap() + ) + .is_none()); // `import foo.baz` should now resolve assert!(resolve_module( case.db().upcast(), - ModuleName::new_static("foo.baz").unwrap() + &ModuleName::new_static("foo.baz").unwrap() ) .is_some()); @@ -665,7 +688,11 @@ fn directory_deleted() -> anyhow::Result<()> { let bar = case.system_file(case.workspace_path("bar.py")).unwrap(); - assert!(resolve_module(case.db().upcast(), ModuleName::new_static("sub.a").unwrap()).is_some()); + assert!(resolve_module( + case.db().upcast(), + &ModuleName::new_static("sub.a").unwrap() + ) + .is_some()); let sub_path = case.workspace_path("sub"); @@ -688,7 +715,11 @@ fn directory_deleted() -> anyhow::Result<()> { case.apply_changes(changes); // `import sub.a` should no longer resolve - assert!(resolve_module(case.db().upcast(), ModuleName::new_static("sub.a").unwrap()).is_none()); + assert!(resolve_module( + case.db().upcast(), + &ModuleName::new_static("sub.a").unwrap() + ) + .is_none()); assert!(!init_file.exists(case.db())); assert!(!a_file.exists(case.db())); @@ -710,7 +741,7 @@ fn search_path() -> anyhow::Result<()> { let site_packages = case.root_path().join("site_packages"); assert_eq!( - resolve_module(case.db(), ModuleName::new("a").unwrap()), + resolve_module(case.db(), &ModuleName::new("a").unwrap()), None ); @@ -720,7 +751,7 @@ fn search_path() -> anyhow::Result<()> { case.apply_changes(changes); - assert!(resolve_module(case.db().upcast(), ModuleName::new_static("a").unwrap()).is_some()); + assert!(resolve_module(case.db().upcast(), &ModuleName::new_static("a").unwrap()).is_some()); assert_eq!( case.collect_package_files(&case.workspace_path("bar.py")), &[case.system_file(case.workspace_path("bar.py")).unwrap()] @@ -736,7 +767,7 @@ fn add_search_path() -> anyhow::Result<()> { let site_packages = case.workspace_path("site_packages"); std::fs::create_dir_all(site_packages.as_std_path())?; - assert!(resolve_module(case.db().upcast(), ModuleName::new_static("a").unwrap()).is_none()); + assert!(resolve_module(case.db().upcast(), &ModuleName::new_static("a").unwrap()).is_none()); // Register site-packages as a search path. case.update_search_path_settings(SearchPathConfiguration { @@ -751,7 +782,7 @@ fn add_search_path() -> anyhow::Result<()> { case.apply_changes(changes); - assert!(resolve_module(case.db().upcast(), ModuleName::new_static("a").unwrap()).is_some()); + assert!(resolve_module(case.db().upcast(), &ModuleName::new_static("a").unwrap()).is_some()); Ok(()) } @@ -805,7 +836,7 @@ fn changed_versions_file() -> anyhow::Result<()> { // Unset the custom typeshed directory. assert_eq!( - resolve_module(case.db(), ModuleName::new("os").unwrap()), + resolve_module(case.db(), &ModuleName::new("os").unwrap()), None ); @@ -820,7 +851,7 @@ fn changed_versions_file() -> anyhow::Result<()> { case.apply_changes(changes); - assert!(resolve_module(case.db(), ModuleName::new("os").unwrap()).is_some()); + assert!(resolve_module(case.db(), &ModuleName::new("os").unwrap()).is_some()); Ok(()) } @@ -1044,7 +1075,7 @@ mod unix { let baz = resolve_module( case.db().upcast(), - ModuleName::new_static("bar.baz").unwrap(), + &ModuleName::new_static("bar.baz").unwrap(), ) .expect("Expected bar.baz to exist in site-packages."); let baz_workspace = case.workspace_path("bar/baz.py"); @@ -1125,7 +1156,7 @@ mod unix { let baz = resolve_module( case.db().upcast(), - ModuleName::new_static("bar.baz").unwrap(), + &ModuleName::new_static("bar.baz").unwrap(), ) .expect("Expected bar.baz to exist in site-packages."); let bar_baz = case.workspace_path("bar/baz.py"); @@ -1229,7 +1260,7 @@ mod unix { let baz = resolve_module( case.db().upcast(), - ModuleName::new_static("bar.baz").unwrap(), + &ModuleName::new_static("bar.baz").unwrap(), ) .expect("Expected bar.baz to exist in site-packages."); let baz_site_packages_path = diff --git a/crates/red_knot_python_semantic/src/module_resolver/resolver.rs b/crates/red_knot_python_semantic/src/module_resolver/resolver.rs index 51ce7bb407..a51bee3065 100644 --- a/crates/red_knot_python_semantic/src/module_resolver/resolver.rs +++ b/crates/red_knot_python_semantic/src/module_resolver/resolver.rs @@ -17,7 +17,7 @@ use super::module::{Module, ModuleKind}; use super::path::{ModulePath, SearchPath, SearchPathValidationError}; /// Resolves a module name to a module. -pub fn resolve_module(db: &dyn Db, module_name: ModuleName) -> Option { +pub fn resolve_module(db: &dyn Db, module_name: &ModuleName) -> Option { let interned_name = ModuleNameIngredient::new(db, module_name); resolve_module_query(db, interned_name) @@ -103,7 +103,7 @@ pub(crate) fn file_to_module(db: &dyn Db, file: File) -> Option { // If it doesn't, then that means that multiple modules have the same name in different // root paths, but that the module corresponding to `path` is in a lower priority search path, // in which case we ignore it. - let module = resolve_module(db, module_name)?; + let module = resolve_module(db, &module_name)?; if file == module.file() { Some(module) @@ -728,11 +728,11 @@ mod tests { .build(); let foo_module_name = ModuleName::new_static("foo").unwrap(); - let foo_module = resolve_module(&db, foo_module_name.clone()).unwrap(); + let foo_module = resolve_module(&db, &foo_module_name).unwrap(); assert_eq!( Some(&foo_module), - resolve_module(&db, foo_module_name.clone()).as_ref() + resolve_module(&db, &foo_module_name).as_ref() ); assert_eq!("foo", foo_module.name()); @@ -755,7 +755,7 @@ mod tests { .build(); let builtins_module_name = ModuleName::new_static("builtins").unwrap(); - let builtins = resolve_module(&db, builtins_module_name).expect("builtins to resolve"); + let builtins = resolve_module(&db, &builtins_module_name).expect("builtins to resolve"); assert_eq!(builtins.file().path(&db), &stdlib.join("builtins.pyi")); } @@ -776,7 +776,7 @@ mod tests { .build(); let builtins_module_name = ModuleName::new_static("builtins").unwrap(); - let builtins = resolve_module(&db, builtins_module_name).expect("builtins to resolve"); + let builtins = resolve_module(&db, &builtins_module_name).expect("builtins to resolve"); assert_eq!(builtins.file().path(&db), &stdlib.join("builtins.pyi")); } @@ -794,11 +794,11 @@ mod tests { .build(); let functools_module_name = ModuleName::new_static("functools").unwrap(); - let functools_module = resolve_module(&db, functools_module_name.clone()).unwrap(); + let functools_module = resolve_module(&db, &functools_module_name).unwrap(); assert_eq!( Some(&functools_module), - resolve_module(&db, functools_module_name).as_ref() + resolve_module(&db, &functools_module_name).as_ref() ); assert_eq!(&stdlib, functools_module.search_path()); @@ -848,7 +848,7 @@ mod tests { let existing_modules = create_module_names(&["asyncio", "functools", "xml.etree"]); for module_name in existing_modules { - let resolved_module = resolve_module(&db, module_name.clone()).unwrap_or_else(|| { + let resolved_module = resolve_module(&db, &module_name).unwrap_or_else(|| { panic!("Expected module {module_name} to exist in the mock stdlib") }); let search_path = resolved_module.search_path(); @@ -901,7 +901,7 @@ mod tests { for module_name in nonexisting_modules { assert!( - resolve_module(&db, module_name.clone()).is_none(), + resolve_module(&db, &module_name).is_none(), "Unexpectedly resolved a module for {module_name}" ); } @@ -944,7 +944,7 @@ mod tests { ]); for module_name in existing_modules { - let resolved_module = resolve_module(&db, module_name.clone()).unwrap_or_else(|| { + let resolved_module = resolve_module(&db, &module_name).unwrap_or_else(|| { panic!("Expected module {module_name} to exist in the mock stdlib") }); let search_path = resolved_module.search_path(); @@ -980,7 +980,7 @@ mod tests { let nonexisting_modules = create_module_names(&["importlib", "xml", "xml.etree"]); for module_name in nonexisting_modules { assert!( - resolve_module(&db, module_name.clone()).is_none(), + resolve_module(&db, &module_name).is_none(), "Unexpectedly resolved a module for {module_name}" ); } @@ -1002,11 +1002,11 @@ mod tests { .build(); let functools_module_name = ModuleName::new_static("functools").unwrap(); - let functools_module = resolve_module(&db, functools_module_name.clone()).unwrap(); + let functools_module = resolve_module(&db, &functools_module_name).unwrap(); assert_eq!( Some(&functools_module), - resolve_module(&db, functools_module_name).as_ref() + resolve_module(&db, &functools_module_name).as_ref() ); assert_eq!(&src, functools_module.search_path()); assert_eq!(ModuleKind::Module, functools_module.kind()); @@ -1026,7 +1026,7 @@ mod tests { .build(); let pydoc_data_topics_name = ModuleName::new_static("pydoc_data.topics").unwrap(); - let pydoc_data_topics = resolve_module(&db, pydoc_data_topics_name).unwrap(); + let pydoc_data_topics = resolve_module(&db, &pydoc_data_topics_name).unwrap(); assert_eq!("pydoc_data.topics", pydoc_data_topics.name()); assert_eq!(pydoc_data_topics.search_path(), &stdlib); @@ -1043,7 +1043,7 @@ mod tests { .build(); let foo_path = src.join("foo/__init__.py"); - let foo_module = resolve_module(&db, ModuleName::new_static("foo").unwrap()).unwrap(); + let foo_module = resolve_module(&db, &ModuleName::new_static("foo").unwrap()).unwrap(); assert_eq!("foo", foo_module.name()); assert_eq!(&src, foo_module.search_path()); @@ -1070,7 +1070,7 @@ mod tests { let TestCase { db, src, .. } = TestCaseBuilder::new().with_src_files(SRC).build(); - let foo_module = resolve_module(&db, ModuleName::new_static("foo").unwrap()).unwrap(); + let foo_module = resolve_module(&db, &ModuleName::new_static("foo").unwrap()).unwrap(); let foo_init_path = src.join("foo/__init__.py"); assert_eq!(&src, foo_module.search_path()); @@ -1098,11 +1098,11 @@ mod tests { let foo_bar_module_name = ModuleName::new_static("foo.bar").unwrap(); // `foo.py` takes priority over the `foo` namespace package - let foo_module = resolve_module(&db, foo_module_name.clone()).unwrap(); + let foo_module = resolve_module(&db, &foo_module_name).unwrap(); assert_eq!(foo_module.file().path(&db), &src.join("foo.py")); // `foo.bar` isn't recognised as a module - let foo_bar_module = resolve_module(&db, foo_bar_module_name.clone()); + let foo_bar_module = resolve_module(&db, &foo_bar_module_name); assert_eq!(foo_bar_module, None); } @@ -1112,7 +1112,7 @@ mod tests { let TestCase { db, src, .. } = TestCaseBuilder::new().with_src_files(SRC).build(); - let foo = resolve_module(&db, ModuleName::new_static("foo").unwrap()).unwrap(); + let foo = resolve_module(&db, &ModuleName::new_static("foo").unwrap()).unwrap(); let foo_stub = src.join("foo.pyi"); assert_eq!(&src, foo.search_path()); @@ -1136,7 +1136,7 @@ mod tests { let TestCase { db, src, .. } = TestCaseBuilder::new().with_src_files(SRC).build(); let baz_module = - resolve_module(&db, ModuleName::new_static("foo.bar.baz").unwrap()).unwrap(); + resolve_module(&db, &ModuleName::new_static("foo.bar.baz").unwrap()).unwrap(); let baz_path = src.join("foo/bar/baz.py"); assert_eq!(&src, baz_module.search_path()); @@ -1175,14 +1175,14 @@ mod tests { let one_module_name = ModuleName::new_static("parent.child.one").unwrap(); let one_module_path = FilePath::System(src.join("parent/child/one.py")); assert_eq!( - resolve_module(&db, one_module_name), + resolve_module(&db, &one_module_name), path_to_module(&db, &one_module_path) ); let two_module_name = ModuleName::new_static("parent.child.two").unwrap(); let two_module_path = FilePath::System(site_packages.join("parent/child/two.py")); assert_eq!( - resolve_module(&db, two_module_name), + resolve_module(&db, &two_module_name), path_to_module(&db, &two_module_path) ); } @@ -1215,12 +1215,12 @@ mod tests { let one_module_path = FilePath::System(src.join("parent/child/one.py")); let one_module_name = - resolve_module(&db, ModuleName::new_static("parent.child.one").unwrap()); + resolve_module(&db, &ModuleName::new_static("parent.child.one").unwrap()); assert_eq!(one_module_name, path_to_module(&db, &one_module_path)); assert_eq!( None, - resolve_module(&db, ModuleName::new_static("parent.child.two").unwrap()) + resolve_module(&db, &ModuleName::new_static("parent.child.two").unwrap()) ); } @@ -1236,7 +1236,7 @@ mod tests { .with_site_packages_files(&[("foo.py", "")]) .build(); - let foo_module = resolve_module(&db, ModuleName::new_static("foo").unwrap()).unwrap(); + let foo_module = resolve_module(&db, &ModuleName::new_static("foo").unwrap()).unwrap(); let foo_src_path = src.join("foo.py"); assert_eq!(&src, foo_module.search_path()); @@ -1301,8 +1301,8 @@ mod tests { ) .context("Invalid program settings")?; - let foo_module = resolve_module(&db, ModuleName::new_static("foo").unwrap()).unwrap(); - let bar_module = resolve_module(&db, ModuleName::new_static("bar").unwrap()).unwrap(); + let foo_module = resolve_module(&db, &ModuleName::new_static("foo").unwrap()).unwrap(); + let bar_module = resolve_module(&db, &ModuleName::new_static("bar").unwrap()).unwrap(); assert_ne!(foo_module, bar_module); @@ -1337,7 +1337,7 @@ mod tests { .build(); let foo_module_name = ModuleName::new_static("foo").unwrap(); - let foo_module = resolve_module(&db, foo_module_name.clone()).unwrap(); + let foo_module = resolve_module(&db, &foo_module_name).unwrap(); let bar_path = src.join("bar.py"); let bar = system_path_to_file(&db, &bar_path).expect("bar.py to exist"); @@ -1351,7 +1351,7 @@ mod tests { // Re-query the foo module. The foo module should still be cached because `bar.py` isn't relevant // for resolving `foo`. - let foo_module2 = resolve_module(&db, foo_module_name); + let foo_module2 = resolve_module(&db, &foo_module_name); assert!(!db .take_salsa_events() @@ -1368,14 +1368,14 @@ mod tests { let foo_path = src.join("foo.py"); let foo_module_name = ModuleName::new_static("foo").unwrap(); - assert_eq!(resolve_module(&db, foo_module_name.clone()), None); + assert_eq!(resolve_module(&db, &foo_module_name), None); // Now write the foo file db.write_file(&foo_path, "x = 1")?; let foo_file = system_path_to_file(&db, &foo_path).expect("foo.py to exist"); - let foo_module = resolve_module(&db, foo_module_name).expect("Foo module to resolve"); + let foo_module = resolve_module(&db, &foo_module_name).expect("Foo module to resolve"); assert_eq!(foo_file, foo_module.file()); Ok(()) @@ -1389,7 +1389,7 @@ mod tests { let TestCase { mut db, src, .. } = TestCaseBuilder::new().with_src_files(SRC).build(); let foo_module_name = ModuleName::new_static("foo").unwrap(); - let foo_module = resolve_module(&db, foo_module_name.clone()).expect("foo module to exist"); + let foo_module = resolve_module(&db, &foo_module_name).expect("foo module to exist"); let foo_init_path = src.join("foo/__init__.py"); assert_eq!(&foo_init_path, foo_module.file().path(&db)); @@ -1401,7 +1401,7 @@ mod tests { File::sync_path(&mut db, &foo_init_path); File::sync_path(&mut db, foo_init_path.parent().unwrap()); - let foo_module = resolve_module(&db, foo_module_name).expect("Foo module to resolve"); + let foo_module = resolve_module(&db, &foo_module_name).expect("Foo module to resolve"); assert_eq!(&src.join("foo.py"), foo_module.file().path(&db)); Ok(()) @@ -1427,7 +1427,7 @@ mod tests { let functools_module_name = ModuleName::new_static("functools").unwrap(); let stdlib_functools_path = stdlib.join("functools.pyi"); - let functools_module = resolve_module(&db, functools_module_name.clone()).unwrap(); + let functools_module = resolve_module(&db, &functools_module_name).unwrap(); assert_eq!(functools_module.search_path(), &stdlib); assert_eq!( Ok(functools_module.file()), @@ -1440,7 +1440,7 @@ mod tests { let site_packages_functools_path = site_packages.join("functools.py"); db.write_file(&site_packages_functools_path, "f: int") .unwrap(); - let functools_module = resolve_module(&db, functools_module_name.clone()).unwrap(); + let functools_module = resolve_module(&db, &functools_module_name).unwrap(); let events = db.take_salsa_events(); assert_function_query_was_not_run( &db, @@ -1473,7 +1473,7 @@ mod tests { .build(); let functools_module_name = ModuleName::new_static("functools").unwrap(); - let functools_module = resolve_module(&db, functools_module_name.clone()).unwrap(); + let functools_module = resolve_module(&db, &functools_module_name).unwrap(); assert_eq!(functools_module.search_path(), &stdlib); assert_eq!( Ok(functools_module.file()), @@ -1484,7 +1484,7 @@ mod tests { // since first-party files take higher priority in module resolution: let src_functools_path = src.join("functools.py"); db.write_file(&src_functools_path, "FOO: int").unwrap(); - let functools_module = resolve_module(&db, functools_module_name.clone()).unwrap(); + let functools_module = resolve_module(&db, &functools_module_name).unwrap(); assert_eq!(functools_module.search_path(), &src); assert_eq!( Ok(functools_module.file()), @@ -1515,7 +1515,7 @@ mod tests { let functools_module_name = ModuleName::new_static("functools").unwrap(); let src_functools_path = src.join("functools.py"); - let functools_module = resolve_module(&db, functools_module_name.clone()).unwrap(); + let functools_module = resolve_module(&db, &functools_module_name).unwrap(); assert_eq!(functools_module.search_path(), &src); assert_eq!( Ok(functools_module.file()), @@ -1528,7 +1528,7 @@ mod tests { .remove_file(&src_functools_path) .unwrap(); File::sync_path(&mut db, &src_functools_path); - let functools_module = resolve_module(&db, functools_module_name.clone()).unwrap(); + let functools_module = resolve_module(&db, &functools_module_name).unwrap(); assert_eq!(functools_module.search_path(), &stdlib); assert_eq!( Ok(functools_module.file()), @@ -1550,8 +1550,8 @@ mod tests { let foo_module_name = ModuleName::new_static("foo").unwrap(); let foo_bar_module_name = ModuleName::new_static("foo.bar").unwrap(); - let foo_module = resolve_module(&db, foo_module_name.clone()).unwrap(); - let foo_bar_module = resolve_module(&db, foo_bar_module_name.clone()).unwrap(); + let foo_module = resolve_module(&db, &foo_module_name).unwrap(); + let foo_bar_module = resolve_module(&db, &foo_bar_module_name).unwrap(); assert_eq!( foo_module.file().path(&db), @@ -1579,11 +1579,11 @@ mod tests { // Lines with leading whitespace in `.pth` files do not parse: let foo_module_name = ModuleName::new_static("foo").unwrap(); - assert_eq!(resolve_module(&db, foo_module_name), None); + assert_eq!(resolve_module(&db, &foo_module_name), None); // Lines with trailing whitespace in `.pth` files do: let bar_module_name = ModuleName::new_static("bar").unwrap(); - let bar_module = resolve_module(&db, bar_module_name.clone()).unwrap(); + let bar_module = resolve_module(&db, &bar_module_name).unwrap(); assert_eq!( bar_module.file().path(&db), &FilePath::system("/y/src/bar.py") @@ -1602,7 +1602,7 @@ mod tests { .build(); let foo_module_name = ModuleName::new_static("foo").unwrap(); - let foo_module = resolve_module(&db, foo_module_name.clone()).unwrap(); + let foo_module = resolve_module(&db, &foo_module_name).unwrap(); assert_eq!( foo_module.file().path(&db), @@ -1650,10 +1650,10 @@ not_a_directory let b_module_name = ModuleName::new_static("b").unwrap(); let spam_module_name = ModuleName::new_static("spam").unwrap(); - let foo_module = resolve_module(&db, foo_module_name.clone()).unwrap(); - let a_module = resolve_module(&db, a_module_name.clone()).unwrap(); - let b_module = resolve_module(&db, b_module_name.clone()).unwrap(); - let spam_module = resolve_module(&db, spam_module_name.clone()).unwrap(); + let foo_module = resolve_module(&db, &foo_module_name).unwrap(); + let a_module = resolve_module(&db, &a_module_name).unwrap(); + let b_module = resolve_module(&db, &b_module_name).unwrap(); + let spam_module = resolve_module(&db, &spam_module_name).unwrap(); assert_eq!( foo_module.file().path(&db), @@ -1681,14 +1681,14 @@ not_a_directory let foo_module_name = ModuleName::new_static("foo").unwrap(); let bar_module_name = ModuleName::new_static("bar").unwrap(); - let foo_module = resolve_module(&db, foo_module_name).unwrap(); + let foo_module = resolve_module(&db, &foo_module_name).unwrap(); assert_eq!( foo_module.file().path(&db), &FilePath::system("/x/src/foo.py") ); db.clear_salsa_events(); - let bar_module = resolve_module(&db, bar_module_name).unwrap(); + let bar_module = resolve_module(&db, &bar_module_name).unwrap(); assert_eq!( bar_module.file().path(&db), &FilePath::system("/y/src/bar.py") @@ -1713,7 +1713,7 @@ not_a_directory db.write_files(x_directory).unwrap(); let foo_module_name = ModuleName::new_static("foo").unwrap(); - let foo_module = resolve_module(&db, foo_module_name.clone()).unwrap(); + let foo_module = resolve_module(&db, &foo_module_name).unwrap(); assert_eq!( foo_module.file().path(&db), &FilePath::system("/x/src/foo.py") @@ -1725,7 +1725,7 @@ not_a_directory File::sync_path(&mut db, &site_packages.join("_foo.pth")); - assert_eq!(resolve_module(&db, foo_module_name.clone()), None); + assert_eq!(resolve_module(&db, &foo_module_name), None); } #[test] @@ -1740,7 +1740,7 @@ not_a_directory db.write_files(x_directory).unwrap(); let foo_module_name = ModuleName::new_static("foo").unwrap(); - let foo_module = resolve_module(&db, foo_module_name.clone()).unwrap(); + let foo_module = resolve_module(&db, &foo_module_name).unwrap(); let src_path = SystemPathBuf::from("/x/src"); assert_eq!( foo_module.file().path(&db), @@ -1753,7 +1753,7 @@ not_a_directory db.memory_file_system().remove_directory(&src_path).unwrap(); File::sync_path(&mut db, &src_path.join("foo.py")); File::sync_path(&mut db, &src_path); - assert_eq!(resolve_module(&db, foo_module_name.clone()), None); + assert_eq!(resolve_module(&db, &foo_module_name), None); } #[test] @@ -1812,7 +1812,7 @@ not_a_directory // The editable installs discovered from the `.pth` file in the first `site-packages` directory // take precedence over the second `site-packages` directory... let a_module_name = ModuleName::new_static("a").unwrap(); - let a_module = resolve_module(&db, a_module_name.clone()).unwrap(); + let a_module = resolve_module(&db, &a_module_name).unwrap(); assert_eq!(a_module.file().path(&db), &editable_install_location); db.memory_file_system() @@ -1823,7 +1823,7 @@ not_a_directory // ...But now that the `.pth` file in the first `site-packages` directory has been deleted, // the editable install no longer exists, so the module now resolves to the file in the // second `site-packages` directory - let a_module = resolve_module(&db, a_module_name).unwrap(); + let a_module = resolve_module(&db, &a_module_name).unwrap(); assert_eq!(a_module.file().path(&db), &system_site_packages_location); } } diff --git a/crates/red_knot_python_semantic/src/semantic_model.rs b/crates/red_knot_python_semantic/src/semantic_model.rs index 411d87b677..f4a66ef199 100644 --- a/crates/red_knot_python_semantic/src/semantic_model.rs +++ b/crates/red_knot_python_semantic/src/semantic_model.rs @@ -35,7 +35,7 @@ impl<'db> SemanticModel<'db> { line_index(self.db.upcast(), self.file) } - pub fn resolve_module(&self, module_name: ModuleName) -> Option { + pub fn resolve_module(&self, module_name: &ModuleName) -> Option { resolve_module(self.db, module_name) } diff --git a/crates/red_knot_python_semantic/src/stdlib.rs b/crates/red_knot_python_semantic/src/stdlib.rs index 87337055e2..08de7bb968 100644 --- a/crates/red_knot_python_semantic/src/stdlib.rs +++ b/crates/red_knot_python_semantic/src/stdlib.rs @@ -35,7 +35,7 @@ fn core_module_symbol_ty<'db>( core_module: CoreStdlibModule, symbol: &str, ) -> Type<'db> { - resolve_module(db, core_module.name()) + resolve_module(db, &core_module.name()) .map(|module| global_symbol_ty(db, module.file(), symbol)) .unwrap_or(Type::Unbound) } @@ -76,7 +76,7 @@ pub(crate) fn typing_extensions_symbol_ty<'db>(db: &'db dyn Db, symbol: &str) -> /// /// Can return `None` if a custom typeshed is used that is missing the core module in question. fn core_module_scope(db: &dyn Db, core_module: CoreStdlibModule) -> Option> { - resolve_module(db, core_module.name()).map(|module| global_scope(db, module.file())) + resolve_module(db, &core_module.name()).map(|module| global_scope(db, module.file())) } /// Get the `builtins` module scope. diff --git a/crates/red_knot_python_semantic/src/types.rs b/crates/red_knot_python_semantic/src/types.rs index f820331a21..46bae64542 100644 --- a/crates/red_knot_python_semantic/src/types.rs +++ b/crates/red_knot_python_semantic/src/types.rs @@ -791,14 +791,10 @@ impl<'db> Type<'db> { Type::IntLiteral(number) => Type::StringLiteral(StringLiteralType::new(db, { number.to_string().into_boxed_str() })), - Type::BooleanLiteral(true) => { - Type::StringLiteral(StringLiteralType::new(db, "True".into())) - } - Type::BooleanLiteral(false) => { - Type::StringLiteral(StringLiteralType::new(db, "False".into())) - } + Type::BooleanLiteral(true) => Type::StringLiteral(StringLiteralType::new(db, "True")), + Type::BooleanLiteral(false) => Type::StringLiteral(StringLiteralType::new(db, "False")), Type::StringLiteral(literal) => Type::StringLiteral(StringLiteralType::new(db, { - format!("'{}'", literal.value(db).escape_default()).into() + format!("'{}'", literal.value(db).escape_default()).into_boxed_str() })), Type::LiteralString => Type::LiteralString, // TODO: handle more complex types @@ -1532,20 +1528,16 @@ mod tests { Ty::Unknown => Type::Unknown, Ty::Any => Type::Any, Ty::IntLiteral(n) => Type::IntLiteral(n), - Ty::StringLiteral(s) => { - Type::StringLiteral(StringLiteralType::new(db, (*s).into())) - } + Ty::StringLiteral(s) => Type::StringLiteral(StringLiteralType::new(db, s)), Ty::BoolLiteral(b) => Type::BooleanLiteral(b), Ty::LiteralString => Type::LiteralString, - Ty::BytesLiteral(s) => { - Type::BytesLiteral(BytesLiteralType::new(db, s.as_bytes().into())) - } + Ty::BytesLiteral(s) => Type::BytesLiteral(BytesLiteralType::new(db, s.as_bytes())), Ty::BuiltinInstance(s) => builtins_symbol_ty(db, s).to_instance(db), Ty::Union(tys) => { UnionType::from_elements(db, tys.into_iter().map(|ty| ty.into_type(db))) } Ty::Tuple(tys) => { - let elements = tys.into_iter().map(|ty| ty.into_type(db)).collect(); + let elements: Box<_> = tys.into_iter().map(|ty| ty.into_type(db)).collect(); Type::Tuple(TupleType::new(db, elements)) } } diff --git a/crates/red_knot_python_semantic/src/types/builder.rs b/crates/red_knot_python_semantic/src/types/builder.rs index 4dbfa6326e..56b6d9a4a4 100644 --- a/crates/red_knot_python_semantic/src/types/builder.rs +++ b/crates/red_knot_python_semantic/src/types/builder.rs @@ -111,7 +111,7 @@ impl<'db> UnionBuilder<'db> { match self.elements.len() { 0 => Type::Never, 1 => self.elements[0], - _ => Type::Union(UnionType::new(self.db, self.elements.into())), + _ => Type::Union(UnionType::new(self.db, self.elements.into_boxed_slice())), } } } diff --git a/crates/red_knot_python_semantic/src/types/display.rs b/crates/red_knot_python_semantic/src/types/display.rs index 91a9e5381a..b362bd982f 100644 --- a/crates/red_knot_python_semantic/src/types/display.rs +++ b/crates/red_knot_python_semantic/src/types/display.rs @@ -341,12 +341,12 @@ mod tests { Type::Unknown, Type::IntLiteral(-1), global_symbol_ty(&db, mod_file, "A"), - Type::StringLiteral(StringLiteralType::new(&db, Box::from("A"))), - Type::BytesLiteral(BytesLiteralType::new(&db, Box::from([0]))), - Type::BytesLiteral(BytesLiteralType::new(&db, Box::from([7]))), + Type::StringLiteral(StringLiteralType::new(&db, "A")), + Type::BytesLiteral(BytesLiteralType::new(&db, [0u8].as_slice())), + Type::BytesLiteral(BytesLiteralType::new(&db, [7u8].as_slice())), Type::IntLiteral(0), Type::IntLiteral(1), - Type::StringLiteral(StringLiteralType::new(&db, Box::from("B"))), + Type::StringLiteral(StringLiteralType::new(&db, "B")), global_symbol_ty(&db, mod_file, "foo"), global_symbol_ty(&db, mod_file, "bar"), global_symbol_ty(&db, mod_file, "B"), diff --git a/crates/red_knot_python_semantic/src/types/infer.rs b/crates/red_knot_python_semantic/src/types/infer.rs index 4b1c420bb4..9d48eb347c 100644 --- a/crates/red_knot_python_semantic/src/types/infer.rs +++ b/crates/red_knot_python_semantic/src/types/infer.rs @@ -725,7 +725,7 @@ impl<'db> TypeInferenceBuilder<'db> { decorator_list, } = function; - let decorator_tys = decorator_list + let decorator_tys: Box<[Type]> = decorator_list .iter() .map(|decorator| self.infer_decorator(decorator)) .collect(); @@ -1415,7 +1415,7 @@ impl<'db> TypeInferenceBuilder<'db> { } = alias; let module_ty = if let Some(module_name) = ModuleName::new(name) { - if let Some(module) = self.module_ty_from_name(module_name) { + if let Some(module) = self.module_ty_from_name(&module_name) { module } else { self.unresolved_module_diagnostic(alias, 0, Some(name)); @@ -1501,7 +1501,7 @@ impl<'db> TypeInferenceBuilder<'db> { if module.kind().is_package() { level -= 1; } - let mut module_name = module.name().to_owned(); + let mut module_name = module.name().clone(); for _ in 0..level { module_name = module_name .parent() @@ -1553,7 +1553,7 @@ impl<'db> TypeInferenceBuilder<'db> { let module_ty = match module_name { Ok(name) => { - if let Some(ty) = self.module_ty_from_name(name) { + if let Some(ty) = self.module_ty_from_name(&name) { ty } else { self.unresolved_module_diagnostic(import_from, *level, module); @@ -1626,7 +1626,7 @@ impl<'db> TypeInferenceBuilder<'db> { } } - fn module_ty_from_name(&self, module_name: ModuleName) -> Option> { + fn module_ty_from_name(&self, module_name: &ModuleName) -> Option> { resolve_module(self.db, module_name).map(|module| Type::Module(module.file())) } @@ -1740,10 +1740,7 @@ impl<'db> TypeInferenceBuilder<'db> { fn infer_string_literal_expression(&mut self, literal: &ast::ExprStringLiteral) -> Type<'db> { if literal.value.len() <= Self::MAX_STRING_LITERAL_SIZE { - Type::StringLiteral(StringLiteralType::new( - self.db, - literal.value.to_str().into(), - )) + Type::StringLiteral(StringLiteralType::new(self.db, literal.value.to_str())) } else { Type::LiteralString } @@ -1753,7 +1750,7 @@ impl<'db> TypeInferenceBuilder<'db> { // TODO: ignoring r/R prefixes for now, should normalize bytes values Type::BytesLiteral(BytesLiteralType::new( self.db, - literal.value.bytes().collect(), + literal.value.bytes().collect::>(), )) } @@ -2402,7 +2399,7 @@ impl<'db> TypeInferenceBuilder<'db> { let rhs_value = rhs.value(self.db).as_ref(); if lhs_value.len() + rhs_value.len() <= Self::MAX_STRING_LITERAL_SIZE { Type::StringLiteral(StringLiteralType::new(self.db, { - (lhs_value + rhs_value).into() + (lhs_value + rhs_value).into_boxed_str() })) } else { Type::LiteralString @@ -2418,13 +2415,16 @@ impl<'db> TypeInferenceBuilder<'db> { (Type::StringLiteral(s), Type::IntLiteral(n), ast::Operator::Mult) | (Type::IntLiteral(n), Type::StringLiteral(s), ast::Operator::Mult) => { if n < 1 { - Type::StringLiteral(StringLiteralType::new(self.db, Box::default())) + Type::StringLiteral(StringLiteralType::new(self.db, "")) } else if let Ok(n) = usize::try_from(n) { if n.checked_mul(s.value(self.db).len()) .is_some_and(|new_length| new_length <= Self::MAX_STRING_LITERAL_SIZE) { let new_literal = s.value(self.db).repeat(n); - Type::StringLiteral(StringLiteralType::new(self.db, new_literal.into())) + Type::StringLiteral(StringLiteralType::new( + self.db, + new_literal.into_boxed_str(), + )) } else { Type::LiteralString } @@ -2436,7 +2436,7 @@ impl<'db> TypeInferenceBuilder<'db> { (Type::LiteralString, Type::IntLiteral(n), ast::Operator::Mult) | (Type::IntLiteral(n), Type::LiteralString, ast::Operator::Mult) => { if n < 1 { - Type::StringLiteral(StringLiteralType::new(self.db, Box::default())) + Type::StringLiteral(StringLiteralType::new(self.db, "")) } else { Type::LiteralString } diff --git a/crates/red_knot_workspace/src/lint.rs b/crates/red_knot_workspace/src/lint.rs index 71cafe3ce4..090e1fd5b6 100644 --- a/crates/red_knot_workspace/src/lint.rs +++ b/crates/red_knot_workspace/src/lint.rs @@ -136,7 +136,7 @@ fn lint_bad_override(context: &SemanticLintContext, class: &ast::StmtClassDef) { // TODO we should have a special marker on the real typing module (from typeshed) so if you // have your own "typing" module in your project, we don't consider it THE typing module (and // same for other stdlib modules that our lint rules care about) - let Some(typing) = semantic.resolve_module(ModuleName::new("typing").unwrap()) else { + let Some(typing) = semantic.resolve_module(&ModuleName::new("typing").unwrap()) else { return; }; diff --git a/crates/ruff_graph/src/resolver.rs b/crates/ruff_graph/src/resolver.rs index 646834801d..f5eb044020 100644 --- a/crates/ruff_graph/src/resolver.rs +++ b/crates/ruff_graph/src/resolver.rs @@ -19,18 +19,18 @@ impl<'a> Resolver<'a> { pub(crate) fn resolve(&self, import: CollectedImport) -> Option<&'a FilePath> { match import { CollectedImport::Import(import) => { - resolve_module(self.db, import).map(|module| module.file().path(self.db)) + resolve_module(self.db, &import).map(|module| module.file().path(self.db)) } CollectedImport::ImportFrom(import) => { // Attempt to resolve the member (e.g., given `from foo import bar`, look for `foo.bar`). let parent = import.parent(); - resolve_module(self.db, import) + resolve_module(self.db, &import) .map(|module| module.file().path(self.db)) .or_else(|| { // Attempt to resolve the module (e.g., given `from foo import bar`, look for `foo`). - resolve_module(self.db, parent?).map(|module| module.file().path(self.db)) + resolve_module(self.db, &parent?).map(|module| module.file().path(self.db)) }) } }