diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 00000000000..6313b56c578 --- /dev/null +++ b/.gitattributes @@ -0,0 +1 @@ +* text=auto eol=lf diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index c3e14d7f3ed..03ab9b2e40e 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -98,8 +98,8 @@ jobs: run: nox -s set-msrv-package-versions - if: inputs.rust != 'stable' - name: Ignore changed error messages when using trybuild - run: echo "TRYBUILD=overwrite" >> "$GITHUB_ENV" + name: Ignore changed error messages for ui tests (still run for coverage) + run: echo "UI_TEST=ignore" >> "$GITHUB_ENV" - uses: dorny/paths-filter@v4 if: ${{ inputs.rust == 'stable' && !startsWith(inputs.python-version, 'graalpy') }} diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 38a8e2bddee..117cb9273a4 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -378,7 +378,7 @@ jobs: env: CARGO_TARGET_X86_64_UNKNOWN_LINUX_GNU_RUNNER: valgrind --leak-check=no --error-exitcode=1 RUST_BACKTRACE: 1 - TRYBUILD: overwrite + UI_TEST: skip careful: if: ${{ contains(github.event.pull_request.labels.*.name, 'CI-build-full') || github.event_name != 'pull_request' }} @@ -400,7 +400,7 @@ jobs: - run: nox -s test-rust -- careful skip-full env: RUST_BACKTRACE: 1 - TRYBUILD: overwrite + UI_TEST: skip docsrs: if: ${{ contains(github.event.pull_request.labels.*.name, 'CI-build-full') || github.event_name != 'pull_request' }} diff --git a/Cargo.toml b/Cargo.toml index f9bc365d6c4..b78ad300ada 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -69,7 +69,6 @@ portable-atomic = "1.0" assert_approx_eq = "1.1.0" chrono = "0.4.25" chrono-tz = ">= 0.10, < 0.11" -trybuild = ">=1.0.115" proptest = { version = "1.0", default-features = false, features = ["std"] } send_wrapper = "0.6" serde = { version = "1.0", features = ["derive"] } @@ -80,6 +79,10 @@ tempfile = "3.12.0" static_assertions = "1.1.0" uuid = { version = "1.10.0", features = ["v4"] } parking_lot = { version = "0.12.3", features = ["arc_lock"] } +ui_test = "0.30.4" +regex = "1.12.3" +[target.'cfg(not(target_arch = "wasm32"))'.dev-dependencies] +ctrlc = "3.5.2" [build-dependencies] pyo3-build-config = { path = "pyo3-build-config", version = "=0.28.3", features = ["resolve-config"] } @@ -180,6 +183,7 @@ members = [ "pyo3-macros", "pyo3-macros-backend", "pyo3-introspection", + "tests/ui/base", "pytests", "examples", ] @@ -222,3 +226,8 @@ bare_urls = "warn" [lints] workspace = true + +[[test]] +name = "test_compile_error" +path = "tests/test_compile_error.rs" +harness = false diff --git a/Contributing.md b/Contributing.md index 5b07b36d2c6..3a742a96837 100644 --- a/Contributing.md +++ b/Contributing.md @@ -45,7 +45,7 @@ Use `nox -l` to list the full set of subcommands you can run. #### UI Tests -PyO3 uses [`trybuild`][trybuild] to develop UI tests to capture error messages from the Rust compiler for some of the macro functionality. +PyO3 uses [`ui_test`][ui_test] to develop UI tests to capture error messages from the Rust compiler for some of the macro functionality. The Rust compiler's error output differs depending on whether the `rust-src` component is installed. PyO3's CI has `rust-src` installed, so you need it locally for your UI test output to match: @@ -265,4 +265,4 @@ In the meanwhile, some of our maintainers have personal GitHub sponsorship pages [lychee]: https://github.com/lycheeverse/lychee [nox]: https://github.com/theacodes/nox [pipx]: https://pipx.pypa.io/stable/ -[trybuild]: https://github.com/dtolnay/trybuild +[ui_test]: https://github.com/oli-obk/ui_test diff --git a/noxfile.py b/noxfile.py index b7130b30d4c..6e40cd61e99 100644 --- a/noxfile.py +++ b/noxfile.py @@ -1418,7 +1418,7 @@ def check_feature_powerset(session: nox.Session): @nox.session(name="update-ui-tests", venv_backend="none") def update_ui_tests(session: nox.Session): env = os.environ.copy() - env["TRYBUILD"] = "overwrite" + env["UI_TEST"] = "bless" command = ["test", "--test", "test_compile_error"] _run_cargo(session, *command, env=env) _run_cargo(session, *command, "--features=full", env=env) diff --git a/tests/test_compile_error.rs b/tests/test_compile_error.rs index e5b646239d7..85605c53040 100644 --- a/tests/test_compile_error.rs +++ b/tests/test_compile_error.rs @@ -1,99 +1,272 @@ -#![cfg(feature = "macros")] - -#[cfg(not(target_arch = "wasm32"))] // Not possible to invoke compiler from wasm -#[test] -fn test_compile_errors() { - let t = trybuild::TestCases::new(); - - t.compile_fail("tests/ui/deprecated_pyfn.rs"); - #[cfg(not(feature = "experimental-inspect"))] - t.compile_fail("tests/ui/invalid_property_args.rs"); - t.compile_fail("tests/ui/invalid_proto_pymethods.rs"); - #[cfg(not(feature = "experimental-inspect"))] - #[cfg(not(all(Py_LIMITED_API, not(Py_3_10))))] // to avoid PyFunctionArgument for &str - t.compile_fail("tests/ui/invalid_pyclass_args.rs"); - t.compile_fail("tests/ui/invalid_pyclass_doc.rs"); - t.compile_fail("tests/ui/invalid_pyclass_enum.rs"); - t.compile_fail("tests/ui/invalid_pyclass_init.rs"); - t.compile_fail("tests/ui/invalid_pyclass_item.rs"); - #[cfg(Py_3_9)] - t.compile_fail("tests/ui/invalid_pyclass_generic.rs"); - #[cfg(Py_3_9)] - t.compile_fail("tests/ui/pyclass_generic_enum.rs"); - #[cfg(not(feature = "experimental-inspect"))] - #[cfg(not(all(Py_LIMITED_API, not(Py_3_10))))] // to avoid PyFunctionArgument for &str - t.compile_fail("tests/ui/invalid_pyfunction_argument.rs"); - t.compile_fail("tests/ui/invalid_pyfunction_definition.rs"); - t.compile_fail("tests/ui/invalid_pyfunction_signatures.rs"); - #[cfg(any(not(Py_LIMITED_API), Py_3_11))] - t.compile_fail("tests/ui/invalid_pymethods_buffer.rs"); - // The output is not stable across abi3 / not abi3 and features - #[cfg(all(not(Py_LIMITED_API), feature = "full"))] - t.compile_fail("tests/ui/invalid_pymethods_duplicates.rs"); - t.compile_fail("tests/ui/invalid_pymethod_enum.rs"); - t.compile_fail("tests/ui/invalid_pymethod_names.rs"); - t.compile_fail("tests/ui/invalid_pymodule_args.rs"); - t.compile_fail("tests/ui/invalid_pycallargs.rs"); - t.compile_fail("tests/ui/reject_generics.rs"); - t.compile_fail("tests/ui/invalid_closure.rs"); - t.compile_fail("tests/ui/pyclass_send.rs"); - #[cfg(not(feature = "experimental-inspect"))] - t.compile_fail("tests/ui/invalid_annotation.rs"); - #[cfg(not(feature = "experimental-inspect"))] - t.compile_fail("tests/ui/invalid_annotation_return.rs"); - t.compile_fail("tests/ui/invalid_argument_attributes.rs"); - t.compile_fail("tests/ui/invalid_intopy_derive.rs"); - #[cfg(not(windows))] - t.compile_fail("tests/ui/invalid_intopy_with.rs"); - t.compile_fail("tests/ui/invalid_frompy_derive.rs"); - t.compile_fail("tests/ui/static_ref.rs"); - t.compile_fail("tests/ui/wrong_aspyref_lifetimes.rs"); - #[cfg(not(feature = "uuid"))] - t.compile_fail("tests/ui/invalid_pyfunctions.rs"); - t.compile_fail("tests/ui/invalid_pymethods.rs"); - // output changes with async feature - #[cfg(all(not(Py_3_12), Py_LIMITED_API, feature = "experimental-async"))] - t.compile_fail("tests/ui/abi3_nativetype_inheritance.rs"); - #[cfg(not(feature = "experimental-async"))] - t.compile_fail("tests/ui/invalid_async.rs"); - t.compile_fail("tests/ui/invalid_intern_arg.rs"); - t.compile_fail("tests/ui/invalid_frozen_pyclass_borrow.rs"); - #[cfg(not(any(feature = "hashbrown", feature = "indexmap")))] - t.compile_fail("tests/ui/invalid_pymethod_receiver.rs"); - #[cfg(not(feature = "experimental-inspect"))] - t.compile_fail("tests/ui/missing_intopy.rs"); - // adding extra error conversion impls changes the output - #[cfg(not(any(windows, feature = "eyre", feature = "anyhow", Py_LIMITED_API)))] - t.compile_fail("tests/ui/invalid_result_conversion.rs"); - t.compile_fail("tests/ui/not_send.rs"); - t.compile_fail("tests/ui/not_send2.rs"); - t.compile_fail("tests/ui/get_set_all.rs"); - t.compile_fail("tests/ui/traverse.rs"); - t.compile_fail("tests/ui/invalid_pymodule_in_root.rs"); - t.compile_fail("tests/ui/invalid_pymodule_glob.rs"); - t.compile_fail("tests/ui/invalid_pymodule_trait.rs"); - t.compile_fail("tests/ui/invalid_pymodule_two_pymodule_init.rs"); - #[cfg(all(feature = "experimental-async", not(feature = "experimental-inspect")))] - #[cfg(any(not(Py_LIMITED_API), Py_3_10))] // to avoid PyFunctionArgument for &str - t.compile_fail("tests/ui/invalid_cancel_handle.rs"); - t.pass("tests/ui/pymodule_missing_docs.rs"); - #[cfg(not(any(Py_LIMITED_API, feature = "experimental-inspect")))] - t.pass("tests/ui/forbid_unsafe.rs"); - #[cfg(all(Py_LIMITED_API, not(Py_3_12), feature = "experimental-async"))] - // output changes with async feature - t.compile_fail("tests/ui/abi3_inheritance.rs"); - #[cfg(all(Py_LIMITED_API, not(Py_3_9)))] - t.compile_fail("tests/ui/abi3_weakref.rs"); - #[cfg(all(Py_LIMITED_API, not(Py_3_9)))] - t.compile_fail("tests/ui/abi3_dict.rs"); - #[cfg(not(feature = "experimental-inspect"))] - t.compile_fail("tests/ui/duplicate_pymodule_submodule.rs"); - #[cfg(all(not(Py_LIMITED_API), Py_3_11))] - t.compile_fail("tests/ui/invalid_base_class.rs"); - #[cfg(any(not(Py_3_10), all(not(Py_3_14), Py_LIMITED_API)))] - t.compile_fail("tests/ui/immutable_type.rs"); - t.pass("tests/ui/ambiguous_associated_items.rs"); - t.pass("tests/ui/pyclass_probe.rs"); - t.compile_fail("tests/ui/invalid_pyfunction_warn.rs"); - t.compile_fail("tests/ui/invalid_pymethods_warn.rs"); +#[cfg(all( + // Requires "macros" feature to actually do any meaningful testing + feature = "macros", + // Not possible to invoke compiler from wasm + not(target_arch = "wasm32") +))] +fn main() { + use std::{env::VarError, path::PathBuf}; + + use regex::bytes::Regex; + use ui_test::{run_tests, spanned::Span, Config, OptWithLine}; + + let mut config = Config::rustc("tests/ui"); + + // Various configurations of UI_TEST environment variable for different CI modes + match std::env::var("UI_TEST").as_deref() { + // Default is to run the test as normal, erroring if output is not as expected. + Err(VarError::NotPresent) => { + config.output_conflict_handling = error_on_output_conflict_normalized + } + // Used to update the output files to match expected output + Ok("bless") => config.output_conflict_handling = bless_output_files_normalized, + // This mode is useful for exercising coverage of the proc macros, e.g. on the + // nightly compiler and MSRV, where the output may differ from expected. + Ok("ignore") => { + // Ignore mismatches on stderr / stdout files + config.output_conflict_handling = ui_test::ignore_output_conflict; + + // This combination of settings helps ui test ignore the annotations on + // the test files themselves: + + // The annotations by default start with //~, changing this to a pattern + // which never appears in the files effectively means "ignore all annotations" + config.comment_start = "/*DISABLED*/"; + // Don't error if there are no annotations + config.comment_defaults.base().require_annotations = + OptWithLine::new(false, Span::default()); + // Don't error if the test "passes" because there were no annotations + config.comment_defaults.base().exit_status = OptWithLine::default(); + } + // Completely running the tests, e.g. under `cargo careful` there is some issue which + // doesn't seem worth understanding (we don't gain anything from extra assertions in + // the proc-macro code, which is all quite pedestrian). + Ok("skip") => return, + Err(e) => panic!("error reading UI_TEST environment variable: {e}"), + Ok(unknown) => panic!("invalid UI_TEST value: {unknown}"), + } + + config.bless_command = Some("UI_TEST=bless cargo test --test test_compile_error".into()); + + // There doesn't seem to be a good way to forward all these features automatically, + // so have to just list the relevant ones here. + let deps_features = [ + #[cfg(feature = "macros")] + "pyo3/macros".to_string(), + #[cfg(feature = "abi3")] + "pyo3/abi3".to_string(), + #[cfg(feature = "abi3-py38")] + "pyo3/abi3-py38".to_string(), + #[cfg(feature = "abi3-py39")] + "pyo3/abi3-py39".to_string(), + #[cfg(feature = "abi3-py310")] + "pyo3/abi3-py310".to_string(), + #[cfg(feature = "abi3-py311")] + "pyo3/abi3-py311".to_string(), + #[cfg(feature = "abi3-py312")] + "pyo3/abi3-py312".to_string(), + #[cfg(feature = "abi3-py313")] + "pyo3/abi3-py313".to_string(), + #[cfg(feature = "abi3-py314")] + "pyo3/abi3-py314".to_string(), + #[cfg(feature = "full")] + "pyo3/full".to_string(), + ]; + + let mut deps_cargo = ui_test::CommandBuilder::cargo(); + deps_cargo.args.push("--features".into()); + deps_cargo.args.push(deps_features.join(",").into()); + + config.comment_defaults.base().set_custom( + "dependencies", + ui_test::dependencies::DependencyBuilder { + crate_manifest_path: PathBuf::from( + env!("CARGO_MANIFEST_DIR").to_owned() + "/tests/ui/base/Cargo.toml", + ), + program: deps_cargo, + ..Default::default() + }, + ); + + if let Ok(target) = std::env::var("CARGO_BUILD_TARGET") { + config.target = Some(target); + } + + config + .comment_defaults + .base() + .compile_flags + .push("--diagnostic-width=140".into()); + + config.skip_files.extend([ + // not a test file, used to configure dependencies for the tests + "base/src/lib.rs".into(), + // similarly, just a component of `invalid_pymodule_in_root.rs` + "empty.rs".into(), + // abi3-only tests only need to check when the feature is unsupported + #[cfg(any(not(Py_LIMITED_API), Py_3_9))] + "abi3_dict".into(), + #[cfg(any(not(Py_LIMITED_API), Py_3_9))] + "abi3_weakref".into(), + #[cfg(any(not(Py_LIMITED_API), Py_3_12))] + "abi3_nativetype_inheritance".into(), + #[cfg(any(not(Py_LIMITED_API), Py_3_12))] + "abi3_inheritance".into(), + // this test doesn't work properly without the full API available + #[cfg(Py_LIMITED_API)] + "forbid_unsafe.rs".into(), + // buffer protocol only supported on 3.11+ with abi3 + #[cfg(all(Py_LIMITED_API, not(Py_3_11)))] + "buffer".into(), + // only needs to run on versions where `#[pyclass(immutable_type)]` is unsupported + #[cfg(any(Py_3_14, all(Py_3_10, not(Py_LIMITED_API))))] + "immutable_type.rs".into(), + // generic pyclasses only supported on 3.9+, doesn't fail gracefully on older versions + #[cfg(not(Py_3_9))] + "invalid_pyclass_generic.rs".into(), + // an extra "note" is emitted on abi3 + #[cfg(any(not(Py_LIMITED_API), not(Py_3_12)))] + "invalid_base_class.rs".into(), + #[cfg(all(Py_LIMITED_API, not(Py_3_10)))] + "invalid_pyfunction_argument.rs".into(), + #[cfg(all(Py_LIMITED_API, not(Py_3_10)))] + "invalid_pyclass_args.rs".into(), + // tests that async functions are rejected without the feature + #[cfg(feature = "experimental-async")] + "invalid_async.rs".into(), + // requires the async feature + #[cfg(not(feature = "experimental-async"))] + "invalid_cancel_handle.rs".into(), + ]); + + // differs on `experimental-inspect` feature + #[cfg(feature = "experimental-inspect")] + config.skip_files.extend([ + // extra error messages appear due to additional macro processing + // would be nice to somehow make this not a problem + "duplicate_pymodule_submodule.rs".into(), + "missing_intopy.rs".into(), + "invalid_pyclass_args.rs".into(), + "invalid_property_args.rs".into(), + "invalid_pyfunction_argument.rs".into(), + ]); + + config.comment_defaults.base().normalize_stderr.extend([ + // Normalize multiple trailing newlines to a single newline + (Regex::new("\n\n$").unwrap().into(), vec![b'\n']), + // Normalize counts of "and N others" in trait implementations + ( + Regex::new(r"and \d+ others").unwrap().into(), + b"and $$N others".to_vec(), + ), + // Some trait implementations which are only emitted with certain + // features enabled + ( + Regex::new(r"\n[ \t]*`i32` implements `From>`") + .unwrap() + .into(), + Vec::new(), + ), + ( + Regex::new(r"\n[ \t]*`String` implements `From`") + .unwrap() + .into(), + Vec::new(), + ), + ]); + + let abort_check = config.abort_check.clone(); + ctrlc::set_handler(move || abort_check.abort()).unwrap(); + + run_tests(config).unwrap(); } + +/// Strips line:col information from src file references in error messages. +/// +/// e.g. the following block: +/// +/// ``` +/// --> src/impl_/extract_argument.rs:226:8 +/// | +/// 220 | pub fn extract_argument<'a, 'holder, 'py, T, const IMPLEMENTS_FROMPYOBJECT: bool>( +/// | ---------------- required by a bound in this function +/// ... +/// 226 | T: PyFunctionArgument<'a, 'holder, 'py, IMPLEMENTS_FROMPYOBJECT>, +/// | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `extract_argument` +/// = note: required for `CancelHandle` to implement `FromPyObject<'_, '_>` +/// = note: required for `CancelHandle` to implement `pyo3::impl_::extract_argument::PyFunctionArgument<'_, '_, '_, true>` +/// ``` +/// +/// becomes: +/// +/// ``` +/// --> src/impl_/extract_argument.rs +/// | +/// | pub fn extract_argument<'a, 'holder, 'py, T, const IMPLEMENTS_FROMPYOBJECT: bool>( +/// | ---------------- required by a bound in this function +/// ... +/// | T: PyFunctionArgument<'a, 'holder, 'py, IMPLEMENTS_FROMPYOBJECT>, +/// | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `extract_argument` +/// = note: required for `CancelHandle` to implement `FromPyObject<'_, '_>` +/// = note: required for `CancelHandle` to implement `pyo3::impl_::extract_argument::PyFunctionArgument<'_, '_, '_, true>` +/// ``` +/// +/// Regex replacement via `ui_test`'s `normalize_stderr` can't express the transformation +/// we need here, so we write a custom wrapper which modifies the output before passing +/// to `ui_test`'s normal output handling machinery. +#[cfg(all(feature = "macros", not(target_arch = "wasm32")))] +fn normalize_src_blocks(output: &[u8]) -> Vec { + use std::sync::LazyLock; + + use regex::bytes::{Captures, Regex}; + + // Matches the full block which we want to replace. + // + // The first line with the src path is captured, and then all following lines starting with either a line number and `|` or just `...` + // are captured as the "listing". + static SRC_BLOCK: LazyLock = LazyLock::new(|| { + Regex::new( + r"\n[ \t]*--> (src/\S+?):\d+:\d+((?:\n[ \t]*\d*[ \t]*[|=][^\n]*|\n[ \t]*\.\.\.)+)", + ) + .unwrap() + }); + + // Matches a gutter line in the listing (potentially with a line number) + static GUTTER: LazyLock = + LazyLock::new(|| Regex::new(r"\n[ \t]*\d*[ \t]*([|=])").unwrap()); + + SRC_BLOCK + .replace_all(output, |captures: &Captures<'_>| { + // always normalize gutter to two spaces, arrow to one space, + // this leads to best stability + let mut out = b"\n --> ".to_vec(); + out.extend_from_slice(&captures[1]); + let listing = GUTTER.replace_all(&captures[2], b"\n $1"); + out.extend_from_slice(&listing); + out + }) + .into_owned() +} + +#[cfg(all(feature = "macros", not(target_arch = "wasm32")))] +fn error_on_output_conflict_normalized( + path: &std::path::Path, + output: &[u8], + errors: &mut Vec, + config: &ui_test::per_test_config::TestConfig, +) { + ui_test::error_on_output_conflict(path, &normalize_src_blocks(output), errors, config); +} + +#[cfg(all(feature = "macros", not(target_arch = "wasm32")))] +fn bless_output_files_normalized( + path: &std::path::Path, + output: &[u8], + errors: &mut Vec, + config: &ui_test::per_test_config::TestConfig, +) { + ui_test::bless_output_files(path, &normalize_src_blocks(output), errors, config); +} + +#[cfg(any(not(feature = "macros"), target_arch = "wasm32"))] +fn main() {} diff --git a/tests/ui/abi3_dict.rs b/tests/ui/abi3_dict.rs index 764a4d415a7..ac2c2daf0e3 100644 --- a/tests/ui/abi3_dict.rs +++ b/tests/ui/abi3_dict.rs @@ -1,7 +1,7 @@ -//! With abi3, dict not supported until python 3.9 or greater use pyo3::prelude::*; #[pyclass(dict)] +//~^ ERROR: `dict` requires Python >= 3.9 when using the `abi3` feature struct TestClass {} fn main() {} diff --git a/tests/ui/abi3_dict.stderr b/tests/ui/abi3_dict.stderr index 0bf4a04ae77..794260dee78 100644 --- a/tests/ui/abi3_dict.stderr +++ b/tests/ui/abi3_dict.stderr @@ -1,7 +1,11 @@ error[E0080]: evaluation panicked: `dict` requires Python >= 3.9 when using the `abi3` feature - --> tests/ui/abi3_dict.rs:4:11 + --> tests/ui/abi3_dict.rs:3:11 | -4 | #[pyclass(dict)] +3 | #[pyclass(dict)] | ^^^^ evaluation of `_::ASSERT_DICT_SUPPORTED` failed here | = note: this error originates in the attribute macro `pyclass` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/abi3_inheritance.rs b/tests/ui/abi3_inheritance.rs index 60972e4cf7a..e91303c31f6 100644 --- a/tests/ui/abi3_inheritance.rs +++ b/tests/ui/abi3_inheritance.rs @@ -2,6 +2,8 @@ use pyo3::exceptions::PyException; use pyo3::prelude::*; #[pyclass(extends=PyException)] +//~^ error: `PyException` cannot be subclassed +//~| error: `PyException` cannot be subclassed #[derive(Clone)] struct MyException { code: u32, diff --git a/tests/ui/abi3_inheritance.stderr b/tests/ui/abi3_inheritance.stderr index 5211488e738..ea3f82ce1c9 100644 --- a/tests/ui/abi3_inheritance.stderr +++ b/tests/ui/abi3_inheritance.stderr @@ -1,12 +1,12 @@ error[E0277]: pyclass `PyException` cannot be subclassed - --> tests/ui/abi3_inheritance.rs:4:1 - | -4 | #[pyclass(extends=PyException)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required for `#[pyclass(extends=PyException)]` - | - = help: the trait `pyo3::impl_::pyclass::PyClassBaseType` is not implemented for `PyException` - = note: `PyException` must have `#[pyclass(subclass)]` to be eligible for subclassing - = note: subclassing native types requires Python >= 3.12 when using the `abi3` feature + --> tests/ui/abi3_inheritance.rs:4:1 + | + 4 | #[pyclass(extends=PyException)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required for `#[pyclass(extends=PyException)]` + | + = help: the trait `pyo3::impl_::pyclass::PyClassBaseType` is not implemented for `PyException` + = note: `PyException` must have `#[pyclass(subclass)]` to be eligible for subclassing + = note: subclassing native types requires Python >= 3.12 when using the `abi3` feature help: the trait `pyo3::impl_::pyclass::PyClassBaseType` is implemented for `PyAny` --> src/types/any.rs | @@ -15,14 +15,14 @@ help: the trait `pyo3::impl_::pyclass::PyClassBaseType` is implemented for `PyAn = note: this error originates in the attribute macro `pyclass` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0277]: pyclass `PyException` cannot be subclassed - --> tests/ui/abi3_inheritance.rs:4:19 - | -4 | #[pyclass(extends=PyException)] - | ^^^^^^^^^^^ required for `#[pyclass(extends=PyException)]` - | - = help: the trait `pyo3::impl_::pyclass::PyClassBaseType` is not implemented for `PyException` - = note: `PyException` must have `#[pyclass(subclass)]` to be eligible for subclassing - = note: subclassing native types requires Python >= 3.12 when using the `abi3` feature + --> tests/ui/abi3_inheritance.rs:4:19 + | + 4 | #[pyclass(extends=PyException)] + | ^^^^^^^^^^^ required for `#[pyclass(extends=PyException)]` + | + = help: the trait `pyo3::impl_::pyclass::PyClassBaseType` is not implemented for `PyException` + = note: `PyException` must have `#[pyclass(subclass)]` to be eligible for subclassing + = note: subclassing native types requires Python >= 3.12 when using the `abi3` feature help: the trait `pyo3::impl_::pyclass::PyClassBaseType` is implemented for `PyAny` --> src/types/any.rs | @@ -42,3 +42,7 @@ warning: use of deprecated associated constant `pyo3::impl_::deprecated::HasAuto | = note: `#[warn(deprecated)]` on by default = note: this warning originates in the attribute macro `pyclass` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 2 previous errors; 1 warning emitted + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/abi3_nativetype_inheritance.rs b/tests/ui/abi3_nativetype_inheritance.rs index 80faff1b739..41db05ffef3 100644 --- a/tests/ui/abi3_nativetype_inheritance.rs +++ b/tests/ui/abi3_nativetype_inheritance.rs @@ -3,6 +3,8 @@ use pyo3::prelude::*; use pyo3::types::PyDict; #[pyclass(extends=PyDict)] +//~^ error: `PyDict` cannot be subclassed +//~| error: `PyDict` cannot be subclassed struct TestClass {} fn main() {} diff --git a/tests/ui/abi3_nativetype_inheritance.stderr b/tests/ui/abi3_nativetype_inheritance.stderr index e8801deb104..774c4df2261 100644 --- a/tests/ui/abi3_nativetype_inheritance.stderr +++ b/tests/ui/abi3_nativetype_inheritance.stderr @@ -1,12 +1,12 @@ error[E0277]: pyclass `PyDict` cannot be subclassed - --> tests/ui/abi3_nativetype_inheritance.rs:5:1 - | -5 | #[pyclass(extends=PyDict)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required for `#[pyclass(extends=PyDict)]` - | - = help: the trait `pyo3::impl_::pyclass::PyClassBaseType` is not implemented for `PyDict` - = note: `PyDict` must have `#[pyclass(subclass)]` to be eligible for subclassing - = note: subclassing native types requires Python >= 3.12 when using the `abi3` feature + --> tests/ui/abi3_nativetype_inheritance.rs:5:1 + | + 5 | #[pyclass(extends=PyDict)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required for `#[pyclass(extends=PyDict)]` + | + = help: the trait `pyo3::impl_::pyclass::PyClassBaseType` is not implemented for `PyDict` + = note: `PyDict` must have `#[pyclass(subclass)]` to be eligible for subclassing + = note: subclassing native types requires Python >= 3.12 when using the `abi3` feature help: the trait `pyo3::impl_::pyclass::PyClassBaseType` is implemented for `PyAny` --> src/types/any.rs | @@ -15,14 +15,14 @@ help: the trait `pyo3::impl_::pyclass::PyClassBaseType` is implemented for `PyAn = note: this error originates in the attribute macro `pyclass` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0277]: pyclass `PyDict` cannot be subclassed - --> tests/ui/abi3_nativetype_inheritance.rs:5:19 - | -5 | #[pyclass(extends=PyDict)] - | ^^^^^^ required for `#[pyclass(extends=PyDict)]` - | - = help: the trait `pyo3::impl_::pyclass::PyClassBaseType` is not implemented for `PyDict` - = note: `PyDict` must have `#[pyclass(subclass)]` to be eligible for subclassing - = note: subclassing native types requires Python >= 3.12 when using the `abi3` feature + --> tests/ui/abi3_nativetype_inheritance.rs:5:19 + | + 5 | #[pyclass(extends=PyDict)] + | ^^^^^^ required for `#[pyclass(extends=PyDict)]` + | + = help: the trait `pyo3::impl_::pyclass::PyClassBaseType` is not implemented for `PyDict` + = note: `PyDict` must have `#[pyclass(subclass)]` to be eligible for subclassing + = note: subclassing native types requires Python >= 3.12 when using the `abi3` feature help: the trait `pyo3::impl_::pyclass::PyClassBaseType` is implemented for `PyAny` --> src/types/any.rs | @@ -33,3 +33,7 @@ note: required by a bound in `pyo3::impl_::pyclass::PyClassImpl::BaseType` | | type BaseType: PyTypeInfo + PyClassBaseType; | ^^^^^^^^^^^^^^^ required by this bound in `PyClassImpl::BaseType` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/abi3_weakref.rs b/tests/ui/abi3_weakref.rs index f45b2258c96..0e0d8c736ce 100644 --- a/tests/ui/abi3_weakref.rs +++ b/tests/ui/abi3_weakref.rs @@ -1,7 +1,7 @@ -//! With abi3, weakref not supported until python 3.9 or greater use pyo3::prelude::*; #[pyclass(weakref)] +//~^ ERROR: `weakref` requires Python >= 3.9 when using the `abi3` feature struct TestClass {} fn main() {} diff --git a/tests/ui/abi3_weakref.stderr b/tests/ui/abi3_weakref.stderr index ff2e2222105..71e3ecd8ac5 100644 --- a/tests/ui/abi3_weakref.stderr +++ b/tests/ui/abi3_weakref.stderr @@ -1,7 +1,11 @@ error[E0080]: evaluation panicked: `weakref` requires Python >= 3.9 when using the `abi3` feature - --> tests/ui/abi3_weakref.rs:4:11 + --> tests/ui/abi3_weakref.rs:3:11 | -4 | #[pyclass(weakref)] +3 | #[pyclass(weakref)] | ^^^^^^^ evaluation of `_::ASSERT_WEAKREF_SUPPORTED` failed here | = note: this error originates in the attribute macro `pyclass` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/ambiguous_associated_items.rs b/tests/ui/ambiguous_associated_items.rs index e0e5075124a..bd905fab99f 100644 --- a/tests/ui/ambiguous_associated_items.rs +++ b/tests/ui/ambiguous_associated_items.rs @@ -1,3 +1,5 @@ +//@check-pass +#![allow(dead_code)] use pyo3::prelude::*; #[pyclass(eq)] diff --git a/tests/ui/base/Cargo.toml b/tests/ui/base/Cargo.toml new file mode 100644 index 00000000000..5eb03c07487 --- /dev/null +++ b/tests/ui/base/Cargo.toml @@ -0,0 +1,10 @@ +[package] +name = "pyo3_ui_tests" +version = "0.1.0" +edition = "2021" + +[dependencies] +pyo3 = { version = "0.28.2", default-features = false, path = "../../../" } + +[features] +macros = ["pyo3/macros"] diff --git a/tests/ui/base/src/lib.rs b/tests/ui/base/src/lib.rs new file mode 100644 index 00000000000..82f2639650c --- /dev/null +++ b/tests/ui/base/src/lib.rs @@ -0,0 +1,2 @@ +// Causes `ui_test` to build pyo3 as a dependency of the ui tests +extern crate pyo3; diff --git a/tests/ui/deprecated_pyfn.rs b/tests/ui/deprecated_pyfn.rs index 1c5edbafd31..fa0446c159f 100644 --- a/tests/ui/deprecated_pyfn.rs +++ b/tests/ui/deprecated_pyfn.rs @@ -5,6 +5,7 @@ use pyo3::prelude::*; #[pymodule] fn module_with_pyfn(m: &Bound<'_, PyModule>) -> PyResult<()> { #[pyfn(m)] +//~^ ERROR: use of deprecated constant `module_with_pyfn::PYFN_ATTRIBUTE`: `pyfn` will be removed in a future PyO3 version, use declarative `#[pymodule]` with `mod` instead fn foo() {} Ok(()) diff --git a/tests/ui/deprecated_pyfn.stderr b/tests/ui/deprecated_pyfn.stderr index c5dd0b3b4ac..9399a270e3d 100644 --- a/tests/ui/deprecated_pyfn.stderr +++ b/tests/ui/deprecated_pyfn.stderr @@ -9,3 +9,5 @@ note: the lint level is defined here | 1 | #![deny(deprecated)] | ^^^^^^^^^^ + +error: aborting due to 1 previous error diff --git a/tests/ui/duplicate_pymodule_submodule.rs b/tests/ui/duplicate_pymodule_submodule.rs index 774d3819645..be2f3815bdc 100644 --- a/tests/ui/duplicate_pymodule_submodule.rs +++ b/tests/ui/duplicate_pymodule_submodule.rs @@ -1,7 +1,8 @@ #[pyo3::pymodule] mod mymodule { - #[pyo3::pymodule(submodule)] - mod submod {} + #[pyo3::pymodule(submodule)] + mod submod {} + //~^ ERROR: `submodule` may only be specified once (it is implicitly always specified for nested modules) } fn main() {} diff --git a/tests/ui/duplicate_pymodule_submodule.stderr b/tests/ui/duplicate_pymodule_submodule.stderr index 284ef029c93..79e465f4b6b 100644 --- a/tests/ui/duplicate_pymodule_submodule.stderr +++ b/tests/ui/duplicate_pymodule_submodule.stderr @@ -1,5 +1,7 @@ error: `submodule` may only be specified once (it is implicitly always specified for nested modules) - --> tests/ui/duplicate_pymodule_submodule.rs:4:2 + --> tests/ui/duplicate_pymodule_submodule.rs:4:5 | 4 | mod submod {} | ^^^ + +error: aborting due to 1 previous error diff --git a/tests/ui/forbid_unsafe.rs b/tests/ui/forbid_unsafe.rs index 356326e65d3..9487b2b3247 100644 --- a/tests/ui/forbid_unsafe.rs +++ b/tests/ui/forbid_unsafe.rs @@ -1,9 +1,9 @@ +//@check-pass #![forbid(unsafe_code)] #![forbid(unsafe_op_in_unsafe_fn)] use pyo3::*; -#[expect(unexpected_cfgs)] #[path = "../../src/tests/hygiene/mod.rs"] mod hygiene; @@ -28,6 +28,7 @@ mod gh_4394 { pub struct Version; } +#[pymodule] mod from_py_with { use pyo3::prelude::*; use pyo3::types::PyBytes; diff --git a/tests/ui/get_set_all.rs b/tests/ui/get_set_all.rs index 20a5eca07bf..64723857d58 100644 --- a/tests/ui/get_set_all.rs +++ b/tests/ui/get_set_all.rs @@ -1,20 +1,24 @@ use pyo3::prelude::*; #[pyclass(set_all)] +//~^ ERROR: `set_all` on an unit struct does nothing, because unit structs have no fields struct Foo; #[pyclass(set_all)] struct Foo2{ #[pyo3(set)] +//~^ ERROR: useless `set` - the struct is already annotated with `set_all` field: u8, } #[pyclass(get_all)] +//~^ ERROR: `get_all` on an unit struct does nothing, because unit structs have no fields struct Foo3; #[pyclass(get_all)] struct Foo4{ #[pyo3(get)] +//~^ ERROR: useless `get` - the struct is already annotated with `get_all` field: u8, } diff --git a/tests/ui/get_set_all.stderr b/tests/ui/get_set_all.stderr index 607d5f96597..6b6f101df71 100644 --- a/tests/ui/get_set_all.stderr +++ b/tests/ui/get_set_all.stderr @@ -5,19 +5,21 @@ error: `set_all` on an unit struct does nothing, because unit structs have no fi | ^^^^^^^ error: useless `set` - the struct is already annotated with `set_all` - --> tests/ui/get_set_all.rs:8:12 + --> tests/ui/get_set_all.rs:9:12 | -8 | #[pyo3(set)] +9 | #[pyo3(set)] | ^^^ error: `get_all` on an unit struct does nothing, because unit structs have no fields - --> tests/ui/get_set_all.rs:12:11 + --> tests/ui/get_set_all.rs:14:11 | -12 | #[pyclass(get_all)] +14 | #[pyclass(get_all)] | ^^^^^^^ error: useless `get` - the struct is already annotated with `get_all` - --> tests/ui/get_set_all.rs:17:12 + --> tests/ui/get_set_all.rs:20:12 | -17 | #[pyo3(get)] +20 | #[pyo3(get)] | ^^^ + +error: aborting due to 4 previous errors diff --git a/tests/ui/immutable_type.rs b/tests/ui/immutable_type.rs index a311eb5b249..b8c5abc4f1c 100644 --- a/tests/ui/immutable_type.rs +++ b/tests/ui/immutable_type.rs @@ -1,6 +1,7 @@ -use pyo3::prelude::*; - -#[pyclass(immutable_type)] -struct ImmutableType {} - -fn main() {} +use pyo3::prelude::*; + +#[pyclass(immutable_type)] +//~^ ERROR: `immutable_type` requires Python >= 3.10 (or >= 3.14 when using the `abi3` feature) +struct ImmutableType {} + +fn main() {} diff --git a/tests/ui/immutable_type.stderr b/tests/ui/immutable_type.stderr index 04f09cbcdaf..6eba994c031 100644 --- a/tests/ui/immutable_type.stderr +++ b/tests/ui/immutable_type.stderr @@ -5,3 +5,7 @@ error[E0080]: evaluation panicked: `immutable_type` requires Python >= 3.10 (or | ^^^^^^^^^^^^^^ evaluation of `_::ASSERT_IMMUTABLE_SUPPORTED` failed here | = note: this error originates in the attribute macro `pyclass` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/invalid_argument_attributes.rs b/tests/ui/invalid_argument_attributes.rs index e4066e5fd9c..644f7d73972 100644 --- a/tests/ui/invalid_argument_attributes.rs +++ b/tests/ui/invalid_argument_attributes.rs @@ -2,18 +2,22 @@ use pyo3::prelude::*; #[pyfunction] fn invalid_attribute(#[pyo3(get)] _param: String) {} +//~^ ERROR: expected `cancel_handle` or `from_py_with` #[pyfunction] fn from_py_with_no_value(#[pyo3(from_py_with)] _param: String) {} +//~^ ERROR: expected `=` #[pyfunction] fn from_py_with_string(#[pyo3("from_py_with")] _param: String) {} +//~^ ERROR: expected `cancel_handle` or `from_py_with` #[pyfunction] fn from_py_with_value_not_found(#[pyo3(from_py_with = func)] _param: String) {} #[pyfunction] fn from_py_with_repeated(#[pyo3(from_py_with = func, from_py_with = func)] _param: String) {} +//~^ ERROR: `from_py_with` may only be specified once per argument fn bytes_from_py(bytes: &Bound<'_, pyo3::types::PyBytes>) -> Vec { bytes.as_bytes().to_vec() @@ -21,5 +25,6 @@ fn bytes_from_py(bytes: &Bound<'_, pyo3::types::PyBytes>) -> Vec { #[pyfunction] fn f(#[pyo3(from_py_with = "bytes_from_py")] _bytes: Vec) {} +//~^ ERROR: expected identifier fn main() {} diff --git a/tests/ui/invalid_argument_attributes.stderr b/tests/ui/invalid_argument_attributes.stderr index 8dc4a85d3d5..06214305174 100644 --- a/tests/ui/invalid_argument_attributes.stderr +++ b/tests/ui/invalid_argument_attributes.stderr @@ -5,25 +5,27 @@ error: expected `cancel_handle` or `from_py_with` | ^^^ error: expected `=` - --> tests/ui/invalid_argument_attributes.rs:7:45 + --> tests/ui/invalid_argument_attributes.rs:8:45 | -7 | fn from_py_with_no_value(#[pyo3(from_py_with)] _param: String) {} +8 | fn from_py_with_no_value(#[pyo3(from_py_with)] _param: String) {} | ^ error: expected `cancel_handle` or `from_py_with` - --> tests/ui/invalid_argument_attributes.rs:10:31 + --> tests/ui/invalid_argument_attributes.rs:12:31 | -10 | fn from_py_with_string(#[pyo3("from_py_with")] _param: String) {} +12 | fn from_py_with_string(#[pyo3("from_py_with")] _param: String) {} | ^^^^^^^^^^^^^^ error: `from_py_with` may only be specified once per argument - --> tests/ui/invalid_argument_attributes.rs:16:54 + --> tests/ui/invalid_argument_attributes.rs:19:54 | -16 | fn from_py_with_repeated(#[pyo3(from_py_with = func, from_py_with = func)] _param: String) {} +19 | fn from_py_with_repeated(#[pyo3(from_py_with = func, from_py_with = func)] _param: String) {} | ^^^^^^^^^^^^ error: expected identifier - --> tests/ui/invalid_argument_attributes.rs:23:28 + --> tests/ui/invalid_argument_attributes.rs:27:28 | -23 | fn f(#[pyo3(from_py_with = "bytes_from_py")] _bytes: Vec) {} +27 | fn f(#[pyo3(from_py_with = "bytes_from_py")] _bytes: Vec) {} | ^^^^^^^^^^^^^^^ + +error: aborting due to 5 previous errors diff --git a/tests/ui/invalid_async.rs b/tests/ui/invalid_async.rs index 2c7375fd2f9..915f30e35f1 100644 --- a/tests/ui/invalid_async.rs +++ b/tests/ui/invalid_async.rs @@ -2,6 +2,7 @@ use pyo3::prelude::*; #[pyfunction] async fn check(){} +//~^ ERROR: async functions are only supported with the `experimental-async` feature #[pyclass] pub(crate) struct AsyncRange { @@ -11,10 +12,12 @@ pub(crate) struct AsyncRange { #[pymethods] impl AsyncRange { async fn __anext__(mut _pyself: PyRefMut<'_, Self>) -> PyResult { +//~^ ERROR: async functions are only supported with the `experimental-async` feature Ok(0) } async fn foo(&self) {} +//~^ ERROR: async functions are only supported with the `experimental-async` feature } -fn main() {} \ No newline at end of file +fn main() {} diff --git a/tests/ui/invalid_async.stderr b/tests/ui/invalid_async.stderr index 0bf9f53f8c3..35649d07955 100644 --- a/tests/ui/invalid_async.stderr +++ b/tests/ui/invalid_async.stderr @@ -5,13 +5,15 @@ error: async functions are only supported with the `experimental-async` feature | ^^^^^ error: async functions are only supported with the `experimental-async` feature - --> tests/ui/invalid_async.rs:13:5 + --> tests/ui/invalid_async.rs:14:5 | -13 | async fn __anext__(mut _pyself: PyRefMut<'_, Self>) -> PyResult { +14 | async fn __anext__(mut _pyself: PyRefMut<'_, Self>) -> PyResult { | ^^^^^ error: async functions are only supported with the `experimental-async` feature - --> tests/ui/invalid_async.rs:17:5 + --> tests/ui/invalid_async.rs:19:5 | -17 | async fn foo(&self) {} +19 | async fn foo(&self) {} | ^^^^^ + +error: aborting due to 3 previous errors diff --git a/tests/ui/invalid_base_class.rs b/tests/ui/invalid_base_class.rs index 7433dcb2b96..560e7639706 100644 --- a/tests/ui/invalid_base_class.rs +++ b/tests/ui/invalid_base_class.rs @@ -2,6 +2,8 @@ use pyo3::prelude::*; use pyo3::types::PyBool; #[pyclass(extends=PyBool)] +//~^ ERROR: pyclass `PyBool` cannot be subclassed +//~| ERROR: pyclass `PyBool` cannot be subclassed struct ExtendsBool; fn main() {} diff --git a/tests/ui/invalid_base_class.stderr b/tests/ui/invalid_base_class.stderr index 453c87c5f8a..2759ef588fb 100644 --- a/tests/ui/invalid_base_class.stderr +++ b/tests/ui/invalid_base_class.stderr @@ -19,25 +19,29 @@ error[E0277]: pyclass `PyBool` cannot be subclassed = note: this error originates in the attribute macro `pyclass` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0277]: pyclass `PyBool` cannot be subclassed - --> tests/ui/invalid_base_class.rs:4:19 - | -4 | #[pyclass(extends=PyBool)] - | ^^^^^^ required for `#[pyclass(extends=PyBool)]` - | - = help: the trait `pyo3::impl_::pyclass::PyClassBaseType` is not implemented for `PyBool` - = note: `PyBool` must have `#[pyclass(subclass)]` to be eligible for subclassing - = help: the following other types implement trait `pyo3::impl_::pyclass::PyClassBaseType`: - PyAny - PyArithmeticError - PyAssertionError - PyAttributeError - PyBaseException - PyBaseExceptionGroup - PyBlockingIOError - PyBrokenPipeError - and $N others + --> tests/ui/invalid_base_class.rs:4:19 + | + 4 | #[pyclass(extends=PyBool)] + | ^^^^^^ required for `#[pyclass(extends=PyBool)]` + | + = help: the trait `pyo3::impl_::pyclass::PyClassBaseType` is not implemented for `PyBool` + = note: `PyBool` must have `#[pyclass(subclass)]` to be eligible for subclassing + = help: the following other types implement trait `pyo3::impl_::pyclass::PyClassBaseType`: + PyAny + PyArithmeticError + PyAssertionError + PyAttributeError + PyBaseException + PyBaseExceptionGroup + PyBlockingIOError + PyBrokenPipeError + and $N others note: required by a bound in `pyo3::impl_::pyclass::PyClassImpl::BaseType` --> src/impl_/pyclass.rs | | type BaseType: PyTypeInfo + PyClassBaseType; | ^^^^^^^^^^^^^^^ required by this bound in `PyClassImpl::BaseType` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/invalid_cancel_handle.rs b/tests/ui/invalid_cancel_handle.rs index b61397d4161..c04cb3ea71f 100644 --- a/tests/ui/invalid_cancel_handle.rs +++ b/tests/ui/invalid_cancel_handle.rs @@ -2,26 +2,35 @@ use pyo3::prelude::*; #[pyfunction] async fn cancel_handle_repeated(#[pyo3(cancel_handle, cancel_handle)] _param: String) {} +//~^ ERROR: `cancel_handle` may only be specified once per argument #[pyfunction] async fn cancel_handle_repeated2( #[pyo3(cancel_handle)] _param: String, #[pyo3(cancel_handle)] _param2: String, + //~^ ERROR: `cancel_handle` may only be specified once ) { } #[pyfunction] fn cancel_handle_synchronous(#[pyo3(cancel_handle)] _param: String) {} +//~^ ERROR: `cancel_handle` attribute can only be used with `async fn` #[pyfunction] +//~^ ERROR: mismatched types async fn cancel_handle_wrong_type(#[pyo3(cancel_handle)] _param: String) {} #[pyfunction] async fn missing_cancel_handle_attribute(_param: pyo3::coroutine::CancelHandle) {} +//~^ ERROR: `CancelHandle` cannot be used as a Python function argument +//~| ERROR: `CancelHandle` cannot be used as a Python function argument +//~| ERROR: `CancelHandle` cannot be used as a Python function argument +//~| ERROR: `CancelHandle` cannot be used as a Python function argument #[pyfunction] async fn cancel_handle_and_from_py_with( #[pyo3(cancel_handle, from_py_with = cancel_handle)] _param: pyo3::coroutine::CancelHandle, + //~^ ERROR: `from_py_with` and `cancel_handle` cannot be specified together ) { } diff --git a/tests/ui/invalid_cancel_handle.stderr b/tests/ui/invalid_cancel_handle.stderr index 8fdea4c951a..3f53f6543d6 100644 --- a/tests/ui/invalid_cancel_handle.stderr +++ b/tests/ui/invalid_cancel_handle.stderr @@ -5,93 +5,158 @@ error: `cancel_handle` may only be specified once per argument | ^^^^^^^^^^^^^ error: `cancel_handle` may only be specified once - --> tests/ui/invalid_cancel_handle.rs:9:28 - | -9 | #[pyo3(cancel_handle)] _param2: String, - | ^^^^^^^ + --> tests/ui/invalid_cancel_handle.rs:10:28 + | +10 | #[pyo3(cancel_handle)] _param2: String, + | ^^^^^^^ error: `cancel_handle` attribute can only be used with `async fn` - --> tests/ui/invalid_cancel_handle.rs:14:53 + --> tests/ui/invalid_cancel_handle.rs:16:53 | -14 | fn cancel_handle_synchronous(#[pyo3(cancel_handle)] _param: String) {} +16 | fn cancel_handle_synchronous(#[pyo3(cancel_handle)] _param: String) {} | ^^^^^^ error: `from_py_with` and `cancel_handle` cannot be specified together - --> tests/ui/invalid_cancel_handle.rs:24:12 + --> tests/ui/invalid_cancel_handle.rs:32:12 | -24 | #[pyo3(cancel_handle, from_py_with = cancel_handle)] _param: pyo3::coroutine::CancelHandle, +32 | #[pyo3(cancel_handle, from_py_with = cancel_handle)] _param: pyo3::coroutine::CancelHandle, | ^^^^^^^^^^^^^ +error[E0277]: `CancelHandle` cannot be used as a Python function argument + --> tests/ui/invalid_cancel_handle.rs:24:50 + | + 24 | async fn missing_cancel_handle_attribute(_param: pyo3::coroutine::CancelHandle) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `pyo3::impl_::extract_argument::PyFunctionArgument<'_, '_, '_, false>` is not implemented for `CancelHandle` + | + = note: implement `FromPyObject` to enable using `CancelHandle` as a function argument + = note: `Python<'py>` is also a valid argument type to pass the Python token into `#[pyfunction]`s and `#[pymethods]` +help: the following other types implement trait `pyo3::impl_::extract_argument::PyFunctionArgument<'a, 'holder, 'py, IMPLEMENTS_FROMPYOBJECT>` + --> src/impl_/extract_argument.rs + | + | / impl<'a, 'holder, 'py, T: 'a + 'py> PyFunctionArgument<'a, 'holder, 'py, false> + | | for &'holder Bound<'py, T> + | | where + | | T: PyTypeCheck, + | |___________________^ `&'holder pyo3::Bound<'py, T>` implements `pyo3::impl_::extract_argument::PyFunctionArgument<'a, 'holder, 'py, false>` +... + | / impl<'a, 'holder, 'py, T> PyFunctionArgument<'a, 'holder, 'py, false> for Option + | | where + | | T: PyFunctionArgument<'a, 'holder, 'py, false>, + | |___________________________________________________^ `Option` implements `pyo3::impl_::extract_argument::PyFunctionArgument<'a, 'holder, 'py, false>` +... + | impl<'a, 'holder, T: PyClass> PyFunctionArgument<'a, 'holder, '_, false> for &'holder T { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `&'holder T` implements `pyo3::impl_::extract_argument::PyFunctionArgument<'a, 'holder, '_, false>` +... + | / impl<'a, 'holder, T: PyClass> PyFunctionArgument<'a, 'holder, '_, false> + | | for &'holder mut T + | |______________________^ `&'holder mut T` implements `pyo3::impl_::extract_argument::PyFunctionArgument<'a, 'holder, '_, false>` + error[E0308]: mismatched types - --> tests/ui/invalid_cancel_handle.rs:16:1 + --> tests/ui/invalid_cancel_handle.rs:19:1 | -16 | #[pyfunction] +19 | #[pyfunction] | ^^^^^^^^^^^^^ | | | expected `String`, found `CancelHandle` | arguments to this function are incorrect | note: function defined here - --> tests/ui/invalid_cancel_handle.rs:17:10 + --> tests/ui/invalid_cancel_handle.rs:21:10 | -17 | async fn cancel_handle_wrong_type(#[pyo3(cancel_handle)] _param: String) {} +21 | async fn cancel_handle_wrong_type(#[pyo3(cancel_handle)] _param: String) {} | ^^^^^^^^^^^^^^^^^^^^^^^^ -------------- = note: this error originates in the attribute macro `pyfunction` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0277]: `CancelHandle` cannot be used as a Python function argument - --> tests/ui/invalid_cancel_handle.rs:20:50 - | -20 | async fn missing_cancel_handle_attribute(_param: pyo3::coroutine::CancelHandle) {} - | ^^^^ the trait `PyClass` is not implemented for `CancelHandle` - | - = note: implement `FromPyObject` to enable using `CancelHandle` as a function argument - = note: `Python<'py>` is also a valid argument type to pass the Python token into `#[pyfunction]`s and `#[pymethods]` - = help: the trait `PyClass` is implemented for `pyo3::coroutine::Coroutine` - = note: required for `CancelHandle` to implement `FromPyObject<'_, '_>` - = note: required for `CancelHandle` to implement `PyFunctionArgument<'_, '_, '_, true>` -note: required by a bound in `extract_argument` - --> src/impl_/extract_argument.rs - | - | pub fn extract_argument<'a, 'holder, 'py, T, const IMPLEMENTS_FROMPYOBJECT: bool>( - | ---------------- required by a bound in this function + --> tests/ui/invalid_cancel_handle.rs:24:50 + | + 24 | async fn missing_cancel_handle_attribute(_param: pyo3::coroutine::CancelHandle) {} + | ^^^^ the trait `pyo3::PyClass` is not implemented for `CancelHandle` + | + = note: implement `FromPyObject` to enable using `CancelHandle` as a function argument + = note: `Python<'py>` is also a valid argument type to pass the Python token into `#[pyfunction]`s and `#[pymethods]` +help: the trait `pyo3::PyClass` is implemented for `pyo3::coroutine::Coroutine` + --> src/coroutine.rs + | + | #[pyclass(crate = "crate")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: required for `CancelHandle` to implement `FromPyObject<'_, '_>` + = note: required for `CancelHandle` to implement `pyo3::impl_::extract_argument::PyFunctionArgument<'_, '_, '_, true>` +note: required by a bound in `pyo3::impl_::extract_argument::extract_argument` + --> src/impl_/extract_argument.rs + | + | pub fn extract_argument<'a, 'holder, 'py, T, const IMPLEMENTS_FROMPYOBJECT: bool>( + | ---------------- required by a bound in this function ... - | T: PyFunctionArgument<'a, 'holder, 'py, IMPLEMENTS_FROMPYOBJECT>, - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `extract_argument` + | T: PyFunctionArgument<'a, 'holder, 'py, IMPLEMENTS_FROMPYOBJECT>, + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `extract_argument` + = note: this error originates in the attribute macro `pyclass` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0277]: `CancelHandle` cannot be used as a Python function argument - --> tests/ui/invalid_cancel_handle.rs:20:50 - | -20 | async fn missing_cancel_handle_attribute(_param: pyo3::coroutine::CancelHandle) {} - | ^^^^ the trait `Clone` is not implemented for `CancelHandle` - | - = note: implement `FromPyObject` to enable using `CancelHandle` as a function argument - = note: `Python<'py>` is also a valid argument type to pass the Python token into `#[pyfunction]`s and `#[pymethods]` - = help: the following other types implement trait `PyFunctionArgument<'a, 'holder, 'py, IMPLEMENTS_FROMPYOBJECT>`: - `&'a pyo3::Bound<'py, T>` implements `PyFunctionArgument<'a, '_, 'py, false>` - `&'holder T` implements `PyFunctionArgument<'a, 'holder, '_, false>` - `&'holder mut T` implements `PyFunctionArgument<'a, 'holder, '_, false>` - `Option` implements `PyFunctionArgument<'a, 'holder, 'py, false>` - = note: required for `CancelHandle` to implement `FromPyObject<'_, '_>` - = note: required for `CancelHandle` to implement `PyFunctionArgument<'_, '_, '_, true>` -note: required by a bound in `extract_argument` - --> src/impl_/extract_argument.rs - | - | pub fn extract_argument<'a, 'holder, 'py, T, const IMPLEMENTS_FROMPYOBJECT: bool>( - | ---------------- required by a bound in this function + --> tests/ui/invalid_cancel_handle.rs:24:50 + | + 24 | async fn missing_cancel_handle_attribute(_param: pyo3::coroutine::CancelHandle) {} + | ^^^^ the trait `Clone` is not implemented for `CancelHandle` + | + = note: implement `FromPyObject` to enable using `CancelHandle` as a function argument + = note: `Python<'py>` is also a valid argument type to pass the Python token into `#[pyfunction]`s and `#[pymethods]` +help: the following other types implement trait `pyo3::impl_::extract_argument::PyFunctionArgument<'a, 'holder, 'py, IMPLEMENTS_FROMPYOBJECT>` + --> src/impl_/extract_argument.rs + | + | / impl<'a, 'holder, 'py, T: 'a + 'py> PyFunctionArgument<'a, 'holder, 'py, false> + | | for &'holder Bound<'py, T> + | | where + | | T: PyTypeCheck, + | |___________________^ `&'holder pyo3::Bound<'py, T>` implements `pyo3::impl_::extract_argument::PyFunctionArgument<'a, 'holder, 'py, false>` +... + | / impl<'a, 'holder, 'py, T> PyFunctionArgument<'a, 'holder, 'py, false> for Option + | | where + | | T: PyFunctionArgument<'a, 'holder, 'py, false>, + | |___________________________________________________^ `Option` implements `pyo3::impl_::extract_argument::PyFunctionArgument<'a, 'holder, 'py, false>` +... + | impl<'a, 'holder, T: PyClass> PyFunctionArgument<'a, 'holder, '_, false> for &'holder T { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `&'holder T` implements `pyo3::impl_::extract_argument::PyFunctionArgument<'a, 'holder, '_, false>` +... + | / impl<'a, 'holder, T: PyClass> PyFunctionArgument<'a, 'holder, '_, false> + | | for &'holder mut T + | |______________________^ `&'holder mut T` implements `pyo3::impl_::extract_argument::PyFunctionArgument<'a, 'holder, '_, false>` + = note: required for `CancelHandle` to implement `FromPyObject<'_, '_>` + = note: required for `CancelHandle` to implement `pyo3::impl_::extract_argument::PyFunctionArgument<'_, '_, '_, true>` +note: required by a bound in `pyo3::impl_::extract_argument::extract_argument` + --> src/impl_/extract_argument.rs + | + | pub fn extract_argument<'a, 'holder, 'py, T, const IMPLEMENTS_FROMPYOBJECT: bool>( + | ---------------- required by a bound in this function ... - | T: PyFunctionArgument<'a, 'holder, 'py, IMPLEMENTS_FROMPYOBJECT>, - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `extract_argument` + | T: PyFunctionArgument<'a, 'holder, 'py, IMPLEMENTS_FROMPYOBJECT>, + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `extract_argument` error[E0277]: `CancelHandle` cannot be used as a Python function argument - --> tests/ui/invalid_cancel_handle.rs:20:50 - | -20 | async fn missing_cancel_handle_attribute(_param: pyo3::coroutine::CancelHandle) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `PyFunctionArgument<'_, '_, '_, false>` is not implemented for `CancelHandle` - | - = note: implement `FromPyObject` to enable using `CancelHandle` as a function argument - = note: `Python<'py>` is also a valid argument type to pass the Python token into `#[pyfunction]`s and `#[pymethods]` - = help: the following other types implement trait `PyFunctionArgument<'a, 'holder, 'py, IMPLEMENTS_FROMPYOBJECT>`: - `&'a pyo3::Bound<'py, T>` implements `PyFunctionArgument<'a, '_, 'py, false>` - `&'holder T` implements `PyFunctionArgument<'a, 'holder, '_, false>` - `&'holder mut T` implements `PyFunctionArgument<'a, 'holder, '_, false>` - `Option` implements `PyFunctionArgument<'a, 'holder, 'py, false>` + --> tests/ui/invalid_cancel_handle.rs:24:50 + | + 24 | async fn missing_cancel_handle_attribute(_param: pyo3::coroutine::CancelHandle) {} + | ^^^^ the trait `pyo3::impl_::pyclass::ExtractPyClassWithClone` is not implemented for `CancelHandle` + | + = note: implement `FromPyObject` to enable using `CancelHandle` as a function argument + = note: `Python<'py>` is also a valid argument type to pass the Python token into `#[pyfunction]`s and `#[pymethods]` +help: the trait `pyo3::impl_::pyclass::ExtractPyClassWithClone` is implemented for `pyo3::coroutine::Coroutine` + --> src/coroutine.rs + | + | #[pyclass(crate = "crate")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: required for `CancelHandle` to implement `FromPyObject<'_, '_>` + = note: required for `CancelHandle` to implement `pyo3::impl_::extract_argument::PyFunctionArgument<'_, '_, '_, true>` +note: required by a bound in `pyo3::impl_::extract_argument::extract_argument` + --> src/impl_/extract_argument.rs + | + | pub fn extract_argument<'a, 'holder, 'py, T, const IMPLEMENTS_FROMPYOBJECT: bool>( + | ---------------- required by a bound in this function +... + | T: PyFunctionArgument<'a, 'holder, 'py, IMPLEMENTS_FROMPYOBJECT>, + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `extract_argument` + = note: this error originates in the attribute macro `pyclass` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 9 previous errors + +Some errors have detailed explanations: E0277, E0308. +For more information about an error, try `rustc --explain E0277`. diff --git a/tests/ui/invalid_closure.rs b/tests/ui/invalid_closure.rs index 6dd7d508703..feb64c561b4 100644 --- a/tests/ui/invalid_closure.rs +++ b/tests/ui/invalid_closure.rs @@ -5,6 +5,7 @@ fn main() { let fun: Py = Python::attach(|py| { let local_data = vec![0, 1, 2, 3, 4]; let ref_: &[u8] = &local_data; +//~^ ERROR: `local_data` does not live long enough let closure_fn = |_args: &Bound<'_, PyTuple>, _kwargs: Option<&Bound<'_, PyDict>>| -> PyResult<()> { diff --git a/tests/ui/invalid_closure.stderr b/tests/ui/invalid_closure.stderr index d7fb9bbd04d..6e499efedde 100644 --- a/tests/ui/invalid_closure.stderr +++ b/tests/ui/invalid_closure.stderr @@ -6,14 +6,18 @@ error[E0597]: `local_data` does not live long enough 7 | let ref_: &[u8] = &local_data; | ^^^^^^^^^^^ borrowed value does not live long enough ... -14 | PyCFunction::new_closure(py, None, None, closure_fn) +15 | PyCFunction::new_closure(py, None, None, closure_fn) | ---------------------------------------------------- argument requires that `local_data` is borrowed for `'static` ... -17 | }); +18 | }); | - `local_data` dropped here while still borrowed | note: requirement that the value outlives `'static` introduced here - --> src/types/function.rs - | - | F: Fn(&Bound<'_, PyTuple>, Option<&Bound<'_, PyDict>>) -> R + Send + 'static, - | ^^^^^^^ + --> src/types/function.rs + | + | F: Fn(&Bound<'_, PyTuple>, Option<&Bound<'_, PyDict>>) -> R + Send + 'static, + | ^^^^^^^ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0597`. diff --git a/tests/ui/invalid_frompy_derive.rs b/tests/ui/invalid_frompy_derive.rs index b6682345d9a..8d6e6b94d9d 100644 --- a/tests/ui/invalid_frompy_derive.rs +++ b/tests/ui/invalid_frompy_derive.rs @@ -2,37 +2,45 @@ use pyo3::FromPyObject; #[derive(FromPyObject)] struct Foo(); +//~^ ERROR: cannot derive FromPyObject for empty structs and variants #[derive(FromPyObject)] struct Foo2 {} +//~^ ERROR: cannot derive FromPyObject for empty structs and variants #[derive(FromPyObject)] enum EmptyEnum {} +//~^ ERROR: cannot derive FromPyObject for empty enum #[derive(FromPyObject)] enum EnumWithEmptyTupleVar { EmptyTuple(), + //~^ ERROR: cannot derive FromPyObject for empty structs and variants Valid(String), } #[derive(FromPyObject)] enum EnumWithEmptyStructVar { EmptyStruct {}, + //~^ ERROR: cannot derive FromPyObject for empty structs and variants Valid(String), } #[derive(FromPyObject)] #[pyo3(transparent)] struct EmptyTransparentTup(); +//~^ ERROR: cannot derive FromPyObject for empty structs and variants #[derive(FromPyObject)] #[pyo3(transparent)] struct EmptyTransparentStruct {} +//~^ ERROR: cannot derive FromPyObject for empty structs and variants #[derive(FromPyObject)] enum EnumWithTransparentEmptyTupleVar { #[pyo3(transparent)] EmptyTuple(), + //~^ ERROR: cannot derive FromPyObject for empty structs and variants Valid(String), } @@ -40,16 +48,19 @@ enum EnumWithTransparentEmptyTupleVar { enum EnumWithTransparentEmptyStructVar { #[pyo3(transparent)] EmptyStruct {}, + //~^ ERROR: cannot derive FromPyObject for empty structs and variants Valid(String), } #[derive(FromPyObject)] #[pyo3(transparent)] struct TransparentTupTooManyFields(String, String); +//~^ ERROR: transparent structs and variants can only have 1 field #[derive(FromPyObject)] #[pyo3(transparent)] struct TransparentStructTooManyFields { + //~^ ERROR: transparent structs and variants can only have 1 field foo: String, bar: String, } @@ -58,6 +69,7 @@ struct TransparentStructTooManyFields { enum EnumWithTransparentTupleTooMany { #[pyo3(transparent)] EmptyTuple(String, String), + //~^ ERROR: transparent structs and variants can only have 1 field Valid(String), } @@ -65,6 +77,7 @@ enum EnumWithTransparentTupleTooMany { enum EnumWithTransparentStructTooMany { #[pyo3(transparent)] EmptyStruct { + //~^ ERROR: transparent structs and variants can only have 1 field foo: String, bar: String, }, @@ -74,59 +87,69 @@ enum EnumWithTransparentStructTooMany { #[derive(FromPyObject)] struct UnknownAttribute { #[pyo3(attr)] + //~^ ERROR: expected one of: `attribute`, `item`, `from_py_with`, `into_py_with`, `default` a: String, } #[derive(FromPyObject)] struct InvalidAttributeArg { #[pyo3(attribute(1))] + //~^ ERROR: expected string literal a: String, } #[derive(FromPyObject)] struct TooManyAttributeArgs { #[pyo3(attribute("a", "b"))] + //~^ ERROR: expected at most one argument: `attribute` or `attribute("name")` a: String, } #[derive(FromPyObject)] struct EmptyAttributeArg { #[pyo3(attribute(""))] + //~^ ERROR: attribute name cannot be empty a: String, } #[derive(FromPyObject)] struct NoAttributeArg { #[pyo3(attribute())] + //~^ ERROR: unexpected end of input, expected string literal a: String, } #[derive(FromPyObject)] struct TooManyitemArgs { #[pyo3(item("a", "b"))] + //~^ ERROR: expected at most one argument: `item` or `item(key)` a: String, } #[derive(FromPyObject)] struct NoItemArg { #[pyo3(item())] + //~^ ERROR: unexpected end of input, expected literal a: String, } #[derive(FromPyObject)] struct ItemAndAttribute { #[pyo3(item, attribute)] + //~^ ERROR: only one of `attribute` or `item` can be provided a: String, } #[derive(FromPyObject)] #[pyo3(unknown = "should not work")] +//~^ ERROR: expected one of: `transparent`, `from_item_all`, `annotation`, `crate`, `rename_all` struct UnknownContainerAttr { a: String, } #[derive(FromPyObject)] #[pyo3(annotation = "should not work")] +//~^ ERROR: `annotation` is unsupported for structs struct AnnotationOnStruct { a: String, } @@ -134,21 +157,25 @@ struct AnnotationOnStruct { #[derive(FromPyObject)] enum InvalidAnnotatedEnum { #[pyo3(annotation = 1)] + //~^ ERROR: expected string literal Foo(String), } #[derive(FromPyObject)] enum TooManyLifetimes<'a, 'b> { + //~^ ERROR: FromPyObject can be derived with at most one lifetime parameter Foo(&'a str), Bar(&'b str), } #[derive(FromPyObject)] union Union { + //~^ ERROR: #[derive(FromPyObject)] is not supported for unions a: usize, } #[derive(FromPyObject)] +//~^ ERROR: cannot derive FromPyObject for empty structs and variants enum UnitEnum { Unit, } @@ -156,6 +183,7 @@ enum UnitEnum { #[derive(FromPyObject)] struct InvalidFromPyWith { #[pyo3(from_py_with)] + //~^ ERROR: expected `=` field: String, } @@ -167,12 +195,14 @@ struct InvalidFromPyWithNotFound { #[derive(FromPyObject)] struct InvalidTupleGetter(#[pyo3(item("foo"))] String); +//~^ ERROR: `getter` is not permitted on tuple struct elements. #[derive(FromPyObject)] #[pyo3(transparent)] struct InvalidTransparentWithGetter { #[pyo3(item("foo"))] field: String, + //~^ ERROR: `transparent` structs may not have a `getter` for the inner field } #[derive(FromPyObject)] @@ -184,16 +214,19 @@ struct FromItemAllOnTuple(String); #[pyo3(transparent)] struct FromItemAllWithTransparent { field: String, + //~^ ERROR: `transparent` structs may not have a `getter` for the inner field } #[derive(FromPyObject)] #[pyo3(from_item_all, from_item_all)] +//~^ ERROR: `from_item_all` may only be specified once struct MultipleFromItemAll { field: String, } #[derive(FromPyObject)] #[pyo3(from_item_all)] +//~^ ERROR: Useless `item` - the struct is already annotated with `from_item_all` struct UselessItemAttr { #[pyo3(item)] field: String, @@ -201,6 +234,7 @@ struct UselessItemAttr { #[derive(FromPyObject)] #[pyo3(from_item_all)] +//~^ ERROR: The struct is already annotated with `from_item_all`, `attribute` is not allowed struct FromItemAllConflictAttr { #[pyo3(attribute)] field: String, @@ -208,6 +242,7 @@ struct FromItemAllConflictAttr { #[derive(FromPyObject)] #[pyo3(from_item_all)] +//~^ ERROR: The struct is already annotated with `from_item_all`, `attribute` is not allowed struct FromItemAllConflictAttrWithArgs { #[pyo3(attribute("f"))] field: String, @@ -215,6 +250,7 @@ struct FromItemAllConflictAttrWithArgs { #[derive(FromPyObject)] struct StructWithOnlyDefaultValues { + //~^ ERROR: cannot derive FromPyObject for structs and variants with only default values #[pyo3(default)] field: String, } @@ -222,6 +258,7 @@ struct StructWithOnlyDefaultValues { #[derive(FromPyObject)] enum EnumVariantWithOnlyDefaultValues { Foo { + //~^ ERROR: cannot derive FromPyObject for structs and variants with only default values #[pyo3(default)] field: String, }, @@ -229,25 +266,30 @@ enum EnumVariantWithOnlyDefaultValues { #[derive(FromPyObject)] struct NamedTuplesWithDefaultValues(#[pyo3(default)] String); +//~^ ERROR: `default` is not permitted on tuple struct elements. #[derive(FromPyObject)] #[pyo3(rename_all = "camelCase", rename_all = "kebab-case")] +//~^ ERROR: `rename_all` may only be specified once struct MultipleRenames { snake_case: String, } #[derive(FromPyObject)] #[pyo3(rename_all = "camelCase")] +//~^ ERROR: `rename_all` is useless on tuple structs and variants. struct RenameAllTuple(String); #[derive(FromPyObject)] enum RenameAllEnum { #[pyo3(rename_all = "camelCase")] + //~^ ERROR: `rename_all` is useless on tuple structs and variants. Tuple(String), } #[derive(FromPyObject)] #[pyo3(transparent, rename_all = "camelCase")] +//~^ ERROR: `rename_all` is not permitted on `transparent` structs and variants struct RenameAllTransparent { inner: String, } @@ -256,6 +298,7 @@ struct RenameAllTransparent { #[pyo3(rename_all = "camelCase")] enum UselessRenameAllEnum { #[pyo3(rename_all = "camelCase")] + //~^ ERROR: Useless variant `rename_all` - enum is already annotated with `rename_all Tuple { inner_field: String }, } diff --git a/tests/ui/invalid_frompy_derive.stderr b/tests/ui/invalid_frompy_derive.stderr index 00222304b0c..3fa386d5178 100644 --- a/tests/ui/invalid_frompy_derive.stderr +++ b/tests/ui/invalid_frompy_derive.stderr @@ -5,271 +5,277 @@ error: cannot derive FromPyObject for empty structs and variants | ^^ error: cannot derive FromPyObject for empty structs and variants - --> tests/ui/invalid_frompy_derive.rs:7:13 + --> tests/ui/invalid_frompy_derive.rs:8:13 | -7 | struct Foo2 {} +8 | struct Foo2 {} | ^^ error: cannot derive FromPyObject for empty enum - --> tests/ui/invalid_frompy_derive.rs:10:6 + --> tests/ui/invalid_frompy_derive.rs:12:6 | -10 | enum EmptyEnum {} +12 | enum EmptyEnum {} | ^^^^^^^^^ error: cannot derive FromPyObject for empty structs and variants - --> tests/ui/invalid_frompy_derive.rs:14:15 + --> tests/ui/invalid_frompy_derive.rs:17:15 | -14 | EmptyTuple(), +17 | EmptyTuple(), | ^^ error: cannot derive FromPyObject for empty structs and variants - --> tests/ui/invalid_frompy_derive.rs:20:17 + --> tests/ui/invalid_frompy_derive.rs:24:17 | -20 | EmptyStruct {}, +24 | EmptyStruct {}, | ^^ error: cannot derive FromPyObject for empty structs and variants - --> tests/ui/invalid_frompy_derive.rs:26:27 + --> tests/ui/invalid_frompy_derive.rs:31:27 | -26 | struct EmptyTransparentTup(); +31 | struct EmptyTransparentTup(); | ^^ error: cannot derive FromPyObject for empty structs and variants - --> tests/ui/invalid_frompy_derive.rs:30:31 + --> tests/ui/invalid_frompy_derive.rs:36:31 | -30 | struct EmptyTransparentStruct {} +36 | struct EmptyTransparentStruct {} | ^^ error: cannot derive FromPyObject for empty structs and variants - --> tests/ui/invalid_frompy_derive.rs:35:15 + --> tests/ui/invalid_frompy_derive.rs:42:15 | -35 | EmptyTuple(), +42 | EmptyTuple(), | ^^ error: cannot derive FromPyObject for empty structs and variants - --> tests/ui/invalid_frompy_derive.rs:42:17 + --> tests/ui/invalid_frompy_derive.rs:50:17 | -42 | EmptyStruct {}, +50 | EmptyStruct {}, | ^^ error: transparent structs and variants can only have 1 field - --> tests/ui/invalid_frompy_derive.rs:48:35 + --> tests/ui/invalid_frompy_derive.rs:57:35 | -48 | struct TransparentTupTooManyFields(String, String); +57 | struct TransparentTupTooManyFields(String, String); | ^^^^^^^^^^^^^^^^ error: transparent structs and variants can only have 1 field - --> tests/ui/invalid_frompy_derive.rs:52:39 + --> tests/ui/invalid_frompy_derive.rs:62:39 | -52 | struct TransparentStructTooManyFields { +62 | struct TransparentStructTooManyFields { | _______________________________________^ -53 | | foo: String, -54 | | bar: String, -55 | | } +63 | | +64 | | foo: String, +65 | | bar: String, +66 | | } | |_^ error: transparent structs and variants can only have 1 field - --> tests/ui/invalid_frompy_derive.rs:60:15 + --> tests/ui/invalid_frompy_derive.rs:71:15 | -60 | EmptyTuple(String, String), +71 | EmptyTuple(String, String), | ^^^^^^^^^^^^^^^^ error: transparent structs and variants can only have 1 field - --> tests/ui/invalid_frompy_derive.rs:67:17 + --> tests/ui/invalid_frompy_derive.rs:79:17 | -67 | EmptyStruct { +79 | EmptyStruct { | _________________^ -68 | | foo: String, -69 | | bar: String, -70 | | }, +80 | | +81 | | foo: String, +82 | | bar: String, +83 | | }, | |_____^ error: expected one of: `attribute`, `item`, `from_py_with`, `into_py_with`, `default` - --> tests/ui/invalid_frompy_derive.rs:76:12 + --> tests/ui/invalid_frompy_derive.rs:89:12 | -76 | #[pyo3(attr)] +89 | #[pyo3(attr)] | ^^^^ error: expected string literal - --> tests/ui/invalid_frompy_derive.rs:82:22 + --> tests/ui/invalid_frompy_derive.rs:96:22 | -82 | #[pyo3(attribute(1))] +96 | #[pyo3(attribute(1))] | ^ error: expected at most one argument: `attribute` or `attribute("name")` - --> tests/ui/invalid_frompy_derive.rs:88:25 - | -88 | #[pyo3(attribute("a", "b"))] - | ^ + --> tests/ui/invalid_frompy_derive.rs:103:25 + | +103 | #[pyo3(attribute("a", "b"))] + | ^ error: attribute name cannot be empty - --> tests/ui/invalid_frompy_derive.rs:94:22 - | -94 | #[pyo3(attribute(""))] - | ^^ + --> tests/ui/invalid_frompy_derive.rs:110:22 + | +110 | #[pyo3(attribute(""))] + | ^^ error: unexpected end of input, expected string literal - --> tests/ui/invalid_frompy_derive.rs:100:22 + --> tests/ui/invalid_frompy_derive.rs:117:22 | -100 | #[pyo3(attribute())] +117 | #[pyo3(attribute())] | ^ error: expected at most one argument: `item` or `item(key)` - --> tests/ui/invalid_frompy_derive.rs:106:20 + --> tests/ui/invalid_frompy_derive.rs:124:20 | -106 | #[pyo3(item("a", "b"))] +124 | #[pyo3(item("a", "b"))] | ^ error: unexpected end of input, expected literal - --> tests/ui/invalid_frompy_derive.rs:112:17 + --> tests/ui/invalid_frompy_derive.rs:131:17 | -112 | #[pyo3(item())] +131 | #[pyo3(item())] | ^ error: only one of `attribute` or `item` can be provided - --> tests/ui/invalid_frompy_derive.rs:118:18 + --> tests/ui/invalid_frompy_derive.rs:138:18 | -118 | #[pyo3(item, attribute)] +138 | #[pyo3(item, attribute)] | ^^^^^^^^^ error: expected one of: `transparent`, `from_item_all`, `annotation`, `crate`, `rename_all` - --> tests/ui/invalid_frompy_derive.rs:123:8 + --> tests/ui/invalid_frompy_derive.rs:144:8 | -123 | #[pyo3(unknown = "should not work")] +144 | #[pyo3(unknown = "should not work")] | ^^^^^^^ error: `annotation` is unsupported for structs - --> tests/ui/invalid_frompy_derive.rs:129:21 + --> tests/ui/invalid_frompy_derive.rs:151:21 | -129 | #[pyo3(annotation = "should not work")] +151 | #[pyo3(annotation = "should not work")] | ^^^^^^^^^^^^^^^^^ error: expected string literal - --> tests/ui/invalid_frompy_derive.rs:136:25 + --> tests/ui/invalid_frompy_derive.rs:159:25 | -136 | #[pyo3(annotation = 1)] +159 | #[pyo3(annotation = 1)] | ^ error: FromPyObject can be derived with at most one lifetime parameter - --> tests/ui/invalid_frompy_derive.rs:141:22 + --> tests/ui/invalid_frompy_derive.rs:165:22 | -141 | enum TooManyLifetimes<'a, 'b> { +165 | enum TooManyLifetimes<'a, 'b> { | ^ error: #[derive(FromPyObject)] is not supported for unions - --> tests/ui/invalid_frompy_derive.rs:147:1 + --> tests/ui/invalid_frompy_derive.rs:172:1 | -147 | union Union { +172 | union Union { | ^^^^^ error: cannot derive FromPyObject for empty structs and variants - --> tests/ui/invalid_frompy_derive.rs:151:10 + --> tests/ui/invalid_frompy_derive.rs:177:10 | -151 | #[derive(FromPyObject)] +177 | #[derive(FromPyObject)] | ^^^^^^^^^^^^ | = note: this error originates in the derive macro `FromPyObject` (in Nightly builds, run with -Z macro-backtrace for more info) error: expected `=` - --> tests/ui/invalid_frompy_derive.rs:158:24 + --> tests/ui/invalid_frompy_derive.rs:185:24 | -158 | #[pyo3(from_py_with)] +185 | #[pyo3(from_py_with)] | ^ error: `getter` is not permitted on tuple struct elements. - --> tests/ui/invalid_frompy_derive.rs:169:27 + --> tests/ui/invalid_frompy_derive.rs:197:27 | -169 | struct InvalidTupleGetter(#[pyo3(item("foo"))] String); +197 | struct InvalidTupleGetter(#[pyo3(item("foo"))] String); | ^ error: `transparent` structs may not have a `getter` for the inner field - --> tests/ui/invalid_frompy_derive.rs:175:5 + --> tests/ui/invalid_frompy_derive.rs:204:5 | -175 | field: String, +204 | field: String, | ^^^^^ error: `transparent` structs may not have a `getter` for the inner field - --> tests/ui/invalid_frompy_derive.rs:186:5 + --> tests/ui/invalid_frompy_derive.rs:216:5 | -186 | field: String, +216 | field: String, | ^^^^^ error: `from_item_all` may only be specified once - --> tests/ui/invalid_frompy_derive.rs:190:23 + --> tests/ui/invalid_frompy_derive.rs:221:23 | -190 | #[pyo3(from_item_all, from_item_all)] +221 | #[pyo3(from_item_all, from_item_all)] | ^^^^^^^^^^^^^ error: Useless `item` - the struct is already annotated with `from_item_all` - --> tests/ui/invalid_frompy_derive.rs:196:8 + --> tests/ui/invalid_frompy_derive.rs:228:8 | -196 | #[pyo3(from_item_all)] +228 | #[pyo3(from_item_all)] | ^^^^^^^^^^^^^ error: The struct is already annotated with `from_item_all`, `attribute` is not allowed - --> tests/ui/invalid_frompy_derive.rs:203:8 + --> tests/ui/invalid_frompy_derive.rs:236:8 | -203 | #[pyo3(from_item_all)] +236 | #[pyo3(from_item_all)] | ^^^^^^^^^^^^^ error: The struct is already annotated with `from_item_all`, `attribute` is not allowed - --> tests/ui/invalid_frompy_derive.rs:210:8 + --> tests/ui/invalid_frompy_derive.rs:244:8 | -210 | #[pyo3(from_item_all)] +244 | #[pyo3(from_item_all)] | ^^^^^^^^^^^^^ error: cannot derive FromPyObject for structs and variants with only default values - --> tests/ui/invalid_frompy_derive.rs:217:36 + --> tests/ui/invalid_frompy_derive.rs:252:36 | -217 | struct StructWithOnlyDefaultValues { +252 | struct StructWithOnlyDefaultValues { | ____________________________________^ -218 | | #[pyo3(default)] -219 | | field: String, -220 | | } +253 | | +254 | | #[pyo3(default)] +255 | | field: String, +256 | | } | |_^ error: cannot derive FromPyObject for structs and variants with only default values - --> tests/ui/invalid_frompy_derive.rs:224:9 + --> tests/ui/invalid_frompy_derive.rs:260:9 | -224 | Foo { +260 | Foo { | _________^ -225 | | #[pyo3(default)] -226 | | field: String, -227 | | }, +261 | | +262 | | #[pyo3(default)] +263 | | field: String, +264 | | }, | |_____^ error: `default` is not permitted on tuple struct elements. - --> tests/ui/invalid_frompy_derive.rs:231:37 + --> tests/ui/invalid_frompy_derive.rs:268:37 | -231 | struct NamedTuplesWithDefaultValues(#[pyo3(default)] String); +268 | struct NamedTuplesWithDefaultValues(#[pyo3(default)] String); | ^ error: `rename_all` may only be specified once - --> tests/ui/invalid_frompy_derive.rs:234:34 + --> tests/ui/invalid_frompy_derive.rs:272:34 | -234 | #[pyo3(rename_all = "camelCase", rename_all = "kebab-case")] +272 | #[pyo3(rename_all = "camelCase", rename_all = "kebab-case")] | ^^^^^^^^^^ error: `rename_all` is useless on tuple structs and variants. - --> tests/ui/invalid_frompy_derive.rs:240:8 + --> tests/ui/invalid_frompy_derive.rs:279:8 | -240 | #[pyo3(rename_all = "camelCase")] +279 | #[pyo3(rename_all = "camelCase")] | ^^^^^^^^^^ error: `rename_all` is useless on tuple structs and variants. - --> tests/ui/invalid_frompy_derive.rs:245:12 + --> tests/ui/invalid_frompy_derive.rs:285:12 | -245 | #[pyo3(rename_all = "camelCase")] +285 | #[pyo3(rename_all = "camelCase")] | ^^^^^^^^^^ error: `rename_all` is not permitted on `transparent` structs and variants - --> tests/ui/invalid_frompy_derive.rs:250:21 + --> tests/ui/invalid_frompy_derive.rs:291:21 | -250 | #[pyo3(transparent, rename_all = "camelCase")] +291 | #[pyo3(transparent, rename_all = "camelCase")] | ^^^^^^^^^^ error: Useless variant `rename_all` - enum is already annotated with `rename_all - --> tests/ui/invalid_frompy_derive.rs:258:12 + --> tests/ui/invalid_frompy_derive.rs:300:12 | -258 | #[pyo3(rename_all = "camelCase")] +300 | #[pyo3(rename_all = "camelCase")] | ^^^^^^^^^^ + +error: aborting due to 43 previous errors diff --git a/tests/ui/invalid_frozen_pyclass_borrow.rs b/tests/ui/invalid_frozen_pyclass_borrow.rs index 6379a8707c5..2b710a4b265 100644 --- a/tests/ui/invalid_frozen_pyclass_borrow.rs +++ b/tests/ui/invalid_frozen_pyclass_borrow.rs @@ -7,12 +7,15 @@ pub struct Foo { } #[pymethods] +//~^ ERROR: type mismatch resolving `::Frozen == False` impl Foo { fn mut_method(&mut self) {} +//~^ ERROR: type mismatch resolving `::Frozen == False` } fn borrow_mut_fails(foo: Py, py: Python) { let borrow = foo.bind(py).borrow_mut(); +//~^ ERROR: type mismatch resolving `::Frozen == False` } #[pyclass(subclass)] @@ -23,19 +26,23 @@ struct ImmutableChild; fn borrow_mut_of_child_fails(child: Py, py: Python) { let borrow = child.bind(py).borrow_mut(); +//~^ ERROR: type mismatch resolving `::Frozen == False` } fn py_get_of_mutable_class_fails(class: Py) { class.get(); +//~^ ERROR: type mismatch resolving `::Frozen == True` } fn pyclass_get_of_mutable_class_fails(class: &Bound<'_, MutableBase>) { class.get(); +//~^ ERROR: type mismatch resolving `::Frozen == True` } #[pyclass(frozen)] pub struct SetOnFrozenClass { #[pyo3(set)] +//~^ ERROR: cannot use `#[pyo3(set)]` on a `frozen` class field: u32, } diff --git a/tests/ui/invalid_frozen_pyclass_borrow.stderr b/tests/ui/invalid_frozen_pyclass_borrow.stderr index d049ab98f8d..4b48202e3d5 100644 --- a/tests/ui/invalid_frozen_pyclass_borrow.stderr +++ b/tests/ui/invalid_frozen_pyclass_borrow.stderr @@ -1,38 +1,38 @@ error: cannot use `#[pyo3(set)]` on a `frozen` class - --> tests/ui/invalid_frozen_pyclass_borrow.rs:38:12 + --> tests/ui/invalid_frozen_pyclass_borrow.rs:44:12 | -38 | #[pyo3(set)] +44 | #[pyo3(set)] | ^^^ error[E0271]: type mismatch resolving `::Frozen == False` - --> tests/ui/invalid_frozen_pyclass_borrow.rs:11:19 - | -11 | fn mut_method(&mut self) {} - | ^ type mismatch resolving `::Frozen == False` - | + --> tests/ui/invalid_frozen_pyclass_borrow.rs:12:19 + | + 12 | fn mut_method(&mut self) {} + | ^ type mismatch resolving `::Frozen == False` + | note: expected this to be `pyo3::pyclass::boolean_struct::False` - --> tests/ui/invalid_frozen_pyclass_borrow.rs:3:1 - | - 3 | #[pyclass(frozen)] - | ^^^^^^^^^^^^^^^^^^ + --> tests/ui/invalid_frozen_pyclass_borrow.rs:3:1 + | + 3 | #[pyclass(frozen)] + | ^^^^^^^^^^^^^^^^^^ note: required by a bound in `pyo3::impl_::extract_argument::extract_pyclass_ref_mut` - --> src/impl_/extract_argument.rs - | - | pub fn extract_pyclass_ref_mut<'a, 'holder, T: PyClass>( - | ^^^^^^^^^^^^^^ required by this bound in `extract_pyclass_ref_mut` - = note: this error originates in the attribute macro `pyclass` (in Nightly builds, run with -Z macro-backtrace for more info) + --> src/impl_/extract_argument.rs + | + | pub fn extract_pyclass_ref_mut<'a, 'holder, T: PyClass>( + | ^^^^^^^^^^^^^^ required by this bound in `extract_pyclass_ref_mut` + = note: this error originates in the attribute macro `pyclass` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0271]: type mismatch resolving `::Frozen == False` - --> tests/ui/invalid_frozen_pyclass_borrow.rs:9:1 - | -9 | #[pymethods] - | ^^^^^^^^^^^^ type mismatch resolving `::Frozen == False` - | + --> tests/ui/invalid_frozen_pyclass_borrow.rs:9:1 + | + 9 | #[pymethods] + | ^^^^^^^^^^^^ type mismatch resolving `::Frozen == False` + | note: expected this to be `pyo3::pyclass::boolean_struct::False` - --> tests/ui/invalid_frozen_pyclass_borrow.rs:3:1 - | -3 | #[pyclass(frozen)] - | ^^^^^^^^^^^^^^^^^^ + --> tests/ui/invalid_frozen_pyclass_borrow.rs:3:1 + | + 3 | #[pyclass(frozen)] + | ^^^^^^^^^^^^^^^^^^ note: required by a bound in `PyClassGuardMut` --> src/pyclass/guard.rs | @@ -41,85 +41,89 @@ note: required by a bound in `PyClassGuardMut` = note: this error originates in the attribute macro `pymethods` which comes from the expansion of the attribute macro `pyclass` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0271]: type mismatch resolving `::Frozen == False` - --> tests/ui/invalid_frozen_pyclass_borrow.rs:15:31 - | -15 | let borrow = foo.bind(py).borrow_mut(); - | ^^^^^^^^^^ type mismatch resolving `::Frozen == False` - | + --> tests/ui/invalid_frozen_pyclass_borrow.rs:17:31 + | + 17 | let borrow = foo.bind(py).borrow_mut(); + | ^^^^^^^^^^ type mismatch resolving `::Frozen == False` + | note: expected this to be `pyo3::pyclass::boolean_struct::False` - --> tests/ui/invalid_frozen_pyclass_borrow.rs:3:1 - | - 3 | #[pyclass(frozen)] - | ^^^^^^^^^^^^^^^^^^ + --> tests/ui/invalid_frozen_pyclass_borrow.rs:3:1 + | + 3 | #[pyclass(frozen)] + | ^^^^^^^^^^^^^^^^^^ note: required by a bound in `pyo3::Bound::<'py, T>::borrow_mut` - --> src/instance.rs - | - | pub fn borrow_mut(&self) -> PyRefMut<'py, T> - | ---------- required by a bound in this associated function - | where - | T: PyClass, - | ^^^^^^^^^^^^^^ required by this bound in `Bound::<'py, T>::borrow_mut` - = note: this error originates in the attribute macro `pyclass` (in Nightly builds, run with -Z macro-backtrace for more info) + --> src/instance.rs + | + | pub fn borrow_mut(&self) -> PyRefMut<'py, T> + | ---------- required by a bound in this associated function + | where + | T: PyClass, + | ^^^^^^^^^^^^^^ required by this bound in `Bound::<'py, T>::borrow_mut` + = note: this error originates in the attribute macro `pyclass` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0271]: type mismatch resolving `::Frozen == False` - --> tests/ui/invalid_frozen_pyclass_borrow.rs:25:33 - | -25 | let borrow = child.bind(py).borrow_mut(); - | ^^^^^^^^^^ type mismatch resolving `::Frozen == False` - | + --> tests/ui/invalid_frozen_pyclass_borrow.rs:28:33 + | + 28 | let borrow = child.bind(py).borrow_mut(); + | ^^^^^^^^^^ type mismatch resolving `::Frozen == False` + | note: expected this to be `pyo3::pyclass::boolean_struct::False` - --> tests/ui/invalid_frozen_pyclass_borrow.rs:21:1 - | -21 | #[pyclass(frozen, extends = MutableBase)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + --> tests/ui/invalid_frozen_pyclass_borrow.rs:24:1 + | + 24 | #[pyclass(frozen, extends = MutableBase)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ note: required by a bound in `pyo3::Bound::<'py, T>::borrow_mut` - --> src/instance.rs - | - | pub fn borrow_mut(&self) -> PyRefMut<'py, T> - | ---------- required by a bound in this associated function - | where - | T: PyClass, - | ^^^^^^^^^^^^^^ required by this bound in `Bound::<'py, T>::borrow_mut` - = note: this error originates in the attribute macro `pyclass` (in Nightly builds, run with -Z macro-backtrace for more info) + --> src/instance.rs + | + | pub fn borrow_mut(&self) -> PyRefMut<'py, T> + | ---------- required by a bound in this associated function + | where + | T: PyClass, + | ^^^^^^^^^^^^^^ required by this bound in `Bound::<'py, T>::borrow_mut` + = note: this error originates in the attribute macro `pyclass` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0271]: type mismatch resolving `::Frozen == True` - --> tests/ui/invalid_frozen_pyclass_borrow.rs:29:11 - | -29 | class.get(); - | ^^^ type mismatch resolving `::Frozen == True` - | + --> tests/ui/invalid_frozen_pyclass_borrow.rs:33:11 + | + 33 | class.get(); + | ^^^ type mismatch resolving `::Frozen == True` + | note: expected this to be `pyo3::pyclass::boolean_struct::True` - --> tests/ui/invalid_frozen_pyclass_borrow.rs:18:1 - | -18 | #[pyclass(subclass)] - | ^^^^^^^^^^^^^^^^^^^^ + --> tests/ui/invalid_frozen_pyclass_borrow.rs:21:1 + | + 21 | #[pyclass(subclass)] + | ^^^^^^^^^^^^^^^^^^^^ note: required by a bound in `pyo3::Py::::get` - --> src/instance.rs - | - | pub fn get(&self) -> &T - | --- required by a bound in this associated function - | where - | T: PyClass + Sync, - | ^^^^^^^^^^^^^ required by this bound in `Py::::get` - = note: this error originates in the attribute macro `pyclass` (in Nightly builds, run with -Z macro-backtrace for more info) + --> src/instance.rs + | + | pub fn get(&self) -> &T + | --- required by a bound in this associated function + | where + | T: PyClass + Sync, + | ^^^^^^^^^^^^^ required by this bound in `Py::::get` + = note: this error originates in the attribute macro `pyclass` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0271]: type mismatch resolving `::Frozen == True` - --> tests/ui/invalid_frozen_pyclass_borrow.rs:33:11 - | -33 | class.get(); - | ^^^ type mismatch resolving `::Frozen == True` - | + --> tests/ui/invalid_frozen_pyclass_borrow.rs:38:11 + | + 38 | class.get(); + | ^^^ type mismatch resolving `::Frozen == True` + | note: expected this to be `pyo3::pyclass::boolean_struct::True` - --> tests/ui/invalid_frozen_pyclass_borrow.rs:18:1 - | -18 | #[pyclass(subclass)] - | ^^^^^^^^^^^^^^^^^^^^ + --> tests/ui/invalid_frozen_pyclass_borrow.rs:21:1 + | + 21 | #[pyclass(subclass)] + | ^^^^^^^^^^^^^^^^^^^^ note: required by a bound in `pyo3::Bound::<'py, T>::get` - --> src/instance.rs - | - | pub fn get(&self) -> &T - | --- required by a bound in this associated function - | where - | T: PyClass + Sync, - | ^^^^^^^^^^^^^ required by this bound in `Bound::<'py, T>::get` - = note: this error originates in the attribute macro `pyclass` (in Nightly builds, run with -Z macro-backtrace for more info) + --> src/instance.rs + | + | pub fn get(&self) -> &T + | --- required by a bound in this associated function + | where + | T: PyClass + Sync, + | ^^^^^^^^^^^^^ required by this bound in `Bound::<'py, T>::get` + = note: this error originates in the attribute macro `pyclass` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 7 previous errors + +For more information about this error, try `rustc --explain E0271`. diff --git a/tests/ui/invalid_intern_arg.rs b/tests/ui/invalid_intern_arg.rs index a90dbdd351a..7c4ca90e123 100644 --- a/tests/ui/invalid_intern_arg.rs +++ b/tests/ui/invalid_intern_arg.rs @@ -3,4 +3,6 @@ use pyo3::Python; fn main() { let _foo = if true { "foo" } else { "bar" }; Python::attach(|py| py.import(pyo3::intern!(py, _foo)).unwrap()); +//~^ ERROR: attempt to use a non-constant value in a constant +//~| ERROR: lifetime may not live long enough } diff --git a/tests/ui/invalid_intern_arg.stderr b/tests/ui/invalid_intern_arg.stderr index 7d6d524fb92..e684353092d 100644 --- a/tests/ui/invalid_intern_arg.stderr +++ b/tests/ui/invalid_intern_arg.stderr @@ -1,14 +1,14 @@ error[E0435]: attempt to use a non-constant value in a constant - --> tests/ui/invalid_intern_arg.rs:5:53 - | -5 | Python::attach(|py| py.import(pyo3::intern!(py, _foo)).unwrap()); - | ^^^^ non-constant value - | + --> tests/ui/invalid_intern_arg.rs:5:53 + | + 5 | Python::attach(|py| py.import(pyo3::intern!(py, _foo)).unwrap()); + | ^^^^ non-constant value + | help: consider using `let` instead of `static` --> src/sync.rs | - - static INTERNED: $crate::sync::Interned = $crate::sync::Interned::new($text); - + let INTERNED: $crate::sync::Interned = $crate::sync::Interned::new($text); +232 - static INTERNED: $crate::sync::Interned = $crate::sync::Interned::new($text); +232 + let INTERNED: $crate::sync::Interned = $crate::sync::Interned::new($text); | error: lifetime may not live long enough @@ -19,3 +19,7 @@ error: lifetime may not live long enough | | | | | return type of closure is pyo3::Bound<'2, PyModule> | has type `Python<'1>` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0435`. diff --git a/tests/ui/invalid_intopy_derive.rs b/tests/ui/invalid_intopy_derive.rs index 5d65e36bfcb..a18b5ae6c93 100644 --- a/tests/ui/invalid_intopy_derive.rs +++ b/tests/ui/invalid_intopy_derive.rs @@ -2,37 +2,45 @@ use pyo3::{IntoPyObject, IntoPyObjectRef}; #[derive(IntoPyObject, IntoPyObjectRef)] struct Foo(); +//~^ ERROR: cannot derive `IntoPyObject` for empty structs #[derive(IntoPyObject, IntoPyObjectRef)] struct Foo2 {} +//~^ ERROR: cannot derive `IntoPyObject` for empty structs #[derive(IntoPyObject, IntoPyObjectRef)] enum EmptyEnum {} +//~^ ERROR: cannot derive `IntoPyObject` for empty enum #[derive(IntoPyObject, IntoPyObjectRef)] enum EnumWithEmptyTupleVar { EmptyTuple(), +//~^ ERROR: cannot derive `IntoPyObject` for empty variants Valid(String), } #[derive(IntoPyObject, IntoPyObjectRef)] enum EnumWithEmptyStructVar { EmptyStruct {}, +//~^ ERROR: cannot derive `IntoPyObject` for empty variants Valid(String), } #[derive(IntoPyObject, IntoPyObjectRef)] #[pyo3(transparent)] struct EmptyTransparentTup(); +//~^ ERROR: cannot derive `IntoPyObject` for empty structs #[derive(IntoPyObject, IntoPyObjectRef)] #[pyo3(transparent)] struct EmptyTransparentStruct {} +//~^ ERROR: cannot derive `IntoPyObject` for empty structs #[derive(IntoPyObject, IntoPyObjectRef)] enum EnumWithTransparentEmptyTupleVar { #[pyo3(transparent)] EmptyTuple(), +//~^ ERROR: cannot derive `IntoPyObject` for empty variants Valid(String), } @@ -40,16 +48,19 @@ enum EnumWithTransparentEmptyTupleVar { enum EnumWithTransparentEmptyStructVar { #[pyo3(transparent)] EmptyStruct {}, +//~^ ERROR: cannot derive `IntoPyObject` for empty variants Valid(String), } #[derive(IntoPyObject, IntoPyObjectRef)] #[pyo3(transparent)] struct TransparentTupTooManyFields(String, String); +//~^ ERROR: transparent structs and variants can only have 1 field #[derive(IntoPyObject, IntoPyObjectRef)] #[pyo3(transparent)] struct TransparentStructTooManyFields { +//~^ ERROR: transparent structs and variants can only have 1 field foo: String, bar: String, } @@ -58,6 +69,7 @@ struct TransparentStructTooManyFields { enum EnumWithTransparentTupleTooMany { #[pyo3(transparent)] EmptyTuple(String, String), +//~^ ERROR: transparent structs and variants can only have 1 field Valid(String), } @@ -65,6 +77,7 @@ enum EnumWithTransparentTupleTooMany { enum EnumWithTransparentStructTooMany { #[pyo3(transparent)] EmptyStruct { +//~^ ERROR: transparent structs and variants can only have 1 field foo: String, bar: String, }, @@ -73,25 +86,30 @@ enum EnumWithTransparentStructTooMany { #[derive(IntoPyObject, IntoPyObjectRef)] #[pyo3(unknown = "should not work")] +//~^ ERROR: expected one of: `transparent`, `from_item_all`, `annotation`, `crate`, `rename_all` struct UnknownContainerAttr { a: String, } #[derive(IntoPyObject, IntoPyObjectRef)] union Union { +//~^ ERROR: #[derive(`IntoPyObject`)] is not supported for unions a: usize, } #[derive(IntoPyObject, IntoPyObjectRef)] enum UnitEnum { Unit, +//~^ ERROR: cannot derive `IntoPyObject` for empty variants } #[derive(IntoPyObject, IntoPyObjectRef)] struct TupleAttribute(#[pyo3(attribute)] String, usize); +//~^ ERROR: `item` and `attribute` are not permitted on tuple struct elements. #[derive(IntoPyObject, IntoPyObjectRef)] struct TupleItem(#[pyo3(item)] String, usize); +//~^ ERROR: `item` and `attribute` are not permitted on tuple struct elements. #[derive(IntoPyObject, IntoPyObjectRef)] struct StructAttribute { @@ -103,6 +121,7 @@ struct StructAttribute { #[pyo3(transparent)] struct StructTransparentItem { #[pyo3(item)] +//~^ ERROR: `transparent` structs may not have `item` nor `attribute` for the inner field foo: String, } @@ -110,6 +129,7 @@ struct StructTransparentItem { #[pyo3(transparent)] struct StructTransparentIntoPyWith { #[pyo3(into_py_with = into)] +//~^ ERROR: `into_py_with` is not permitted on `transparent` structs or variants foo: String, } @@ -117,16 +137,19 @@ struct StructTransparentIntoPyWith { #[pyo3(transparent)] struct StructTransparentIntoPyWithRef { #[pyo3(into_py_with = into_ref)] +//~^ ERROR: `into_py_with` is not permitted on `transparent` structs or variants foo: String, } #[derive(IntoPyObject)] #[pyo3(transparent)] struct TupleTransparentIntoPyWith(#[pyo3(into_py_with = into)] String); +//~^ ERROR: `into_py_with` is not permitted on `transparent` structs #[derive(IntoPyObject)] enum EnumTupleIntoPyWith { TransparentTuple(#[pyo3(into_py_with = into)] usize), +//~^ ERROR: `into_py_with` is not permitted on `transparent` structs } #[derive(IntoPyObject)] @@ -134,23 +157,27 @@ enum EnumStructIntoPyWith { #[pyo3(transparent)] TransparentStruct { #[pyo3(into_py_with = into)] +//~^ ERROR: `into_py_with` is not permitted on `transparent` structs or variants a: usize, }, } #[derive(IntoPyObject, IntoPyObjectRef)] #[pyo3(transparent, rename_all = "camelCase")] +//~^ ERROR: `rename_all` is not permitted on `transparent` structs and variants struct StructTransparentRenameAll { foo_bar: String, } #[derive(IntoPyObject, IntoPyObjectRef)] #[pyo3(rename_all = "camelCase")] +//~^ ERROR: `rename_all` is useless on tuple structs and variants. struct StructTupleRenameAll(String, usize); #[derive(IntoPyObject, IntoPyObjectRef)] enum EnumTransparentVariantRenameAll { #[pyo3(rename_all = "camelCase")] +//~^ ERROR: `rename_all` is not permitted on `transparent` structs and variants #[pyo3(transparent)] Variant { foo: String }, } @@ -158,11 +185,13 @@ enum EnumTransparentVariantRenameAll { #[derive(IntoPyObject, IntoPyObjectRef)] enum EnumTupleVariantRenameAll { #[pyo3(rename_all = "camelCase")] +//~^ ERROR: `rename_all` is useless on tuple structs and variants. Variant(String, usize), } #[derive(IntoPyObject, IntoPyObjectRef)] #[pyo3(rename_all = "camelCase")] +//~^ ERROR: `rename_all` is not supported at top level for enums enum EnumTopRenameAll { Variant { foo: String }, } diff --git a/tests/ui/invalid_intopy_derive.stderr b/tests/ui/invalid_intopy_derive.stderr index 518066f3460..8a9b30025df 100644 --- a/tests/ui/invalid_intopy_derive.stderr +++ b/tests/ui/invalid_intopy_derive.stderr @@ -5,177 +5,181 @@ error: cannot derive `IntoPyObject` for empty structs | ^^ error: cannot derive `IntoPyObject` for empty structs - --> tests/ui/invalid_intopy_derive.rs:7:13 + --> tests/ui/invalid_intopy_derive.rs:8:13 | -7 | struct Foo2 {} +8 | struct Foo2 {} | ^^ error: cannot derive `IntoPyObject` for empty enum - --> tests/ui/invalid_intopy_derive.rs:10:6 + --> tests/ui/invalid_intopy_derive.rs:12:6 | -10 | enum EmptyEnum {} +12 | enum EmptyEnum {} | ^^^^^^^^^ error: cannot derive `IntoPyObject` for empty variants - --> tests/ui/invalid_intopy_derive.rs:14:5 + --> tests/ui/invalid_intopy_derive.rs:17:5 | -14 | EmptyTuple(), +17 | EmptyTuple(), | ^^^^^^^^^^ error: cannot derive `IntoPyObject` for empty variants - --> tests/ui/invalid_intopy_derive.rs:20:5 + --> tests/ui/invalid_intopy_derive.rs:24:5 | -20 | EmptyStruct {}, +24 | EmptyStruct {}, | ^^^^^^^^^^^ error: cannot derive `IntoPyObject` for empty structs - --> tests/ui/invalid_intopy_derive.rs:26:27 + --> tests/ui/invalid_intopy_derive.rs:31:27 | -26 | struct EmptyTransparentTup(); +31 | struct EmptyTransparentTup(); | ^^ error: cannot derive `IntoPyObject` for empty structs - --> tests/ui/invalid_intopy_derive.rs:30:31 + --> tests/ui/invalid_intopy_derive.rs:36:31 | -30 | struct EmptyTransparentStruct {} +36 | struct EmptyTransparentStruct {} | ^^ error: cannot derive `IntoPyObject` for empty variants - --> tests/ui/invalid_intopy_derive.rs:35:5 + --> tests/ui/invalid_intopy_derive.rs:42:5 | -35 | EmptyTuple(), +42 | EmptyTuple(), | ^^^^^^^^^^ error: cannot derive `IntoPyObject` for empty variants - --> tests/ui/invalid_intopy_derive.rs:42:5 + --> tests/ui/invalid_intopy_derive.rs:50:5 | -42 | EmptyStruct {}, +50 | EmptyStruct {}, | ^^^^^^^^^^^ error: transparent structs and variants can only have 1 field - --> tests/ui/invalid_intopy_derive.rs:48:35 + --> tests/ui/invalid_intopy_derive.rs:57:35 | -48 | struct TransparentTupTooManyFields(String, String); +57 | struct TransparentTupTooManyFields(String, String); | ^^^^^^^^^^^^^^^^ error: transparent structs and variants can only have 1 field - --> tests/ui/invalid_intopy_derive.rs:52:39 + --> tests/ui/invalid_intopy_derive.rs:62:39 | -52 | struct TransparentStructTooManyFields { +62 | struct TransparentStructTooManyFields { | _______________________________________^ -53 | | foo: String, -54 | | bar: String, -55 | | } +63 | | +64 | | foo: String, +65 | | bar: String, +66 | | } | |_^ error: transparent structs and variants can only have 1 field - --> tests/ui/invalid_intopy_derive.rs:60:15 + --> tests/ui/invalid_intopy_derive.rs:71:15 | -60 | EmptyTuple(String, String), +71 | EmptyTuple(String, String), | ^^^^^^^^^^^^^^^^ error: transparent structs and variants can only have 1 field - --> tests/ui/invalid_intopy_derive.rs:67:17 + --> tests/ui/invalid_intopy_derive.rs:79:17 | -67 | EmptyStruct { +79 | EmptyStruct { | _________________^ -68 | | foo: String, -69 | | bar: String, -70 | | }, +80 | | +81 | | foo: String, +82 | | bar: String, +83 | | }, | |_____^ error: expected one of: `transparent`, `from_item_all`, `annotation`, `crate`, `rename_all` - --> tests/ui/invalid_intopy_derive.rs:75:8 + --> tests/ui/invalid_intopy_derive.rs:88:8 | -75 | #[pyo3(unknown = "should not work")] +88 | #[pyo3(unknown = "should not work")] | ^^^^^^^ error: #[derive(`IntoPyObject`)] is not supported for unions - --> tests/ui/invalid_intopy_derive.rs:81:1 + --> tests/ui/invalid_intopy_derive.rs:95:1 | -81 | union Union { +95 | union Union { | ^^^^^ error: cannot derive `IntoPyObject` for empty variants - --> tests/ui/invalid_intopy_derive.rs:87:5 - | -87 | Unit, - | ^^^^ + --> tests/ui/invalid_intopy_derive.rs:102:5 + | +102 | Unit, + | ^^^^ error: `item` and `attribute` are not permitted on tuple struct elements. - --> tests/ui/invalid_intopy_derive.rs:91:30 - | -91 | struct TupleAttribute(#[pyo3(attribute)] String, usize); - | ^^^^^^^^^ + --> tests/ui/invalid_intopy_derive.rs:107:30 + | +107 | struct TupleAttribute(#[pyo3(attribute)] String, usize); + | ^^^^^^^^^ error: `item` and `attribute` are not permitted on tuple struct elements. - --> tests/ui/invalid_intopy_derive.rs:94:25 - | -94 | struct TupleItem(#[pyo3(item)] String, usize); - | ^^^^ + --> tests/ui/invalid_intopy_derive.rs:111:25 + | +111 | struct TupleItem(#[pyo3(item)] String, usize); + | ^^^^ error: `transparent` structs may not have `item` nor `attribute` for the inner field - --> tests/ui/invalid_intopy_derive.rs:105:12 + --> tests/ui/invalid_intopy_derive.rs:123:12 | -105 | #[pyo3(item)] +123 | #[pyo3(item)] | ^^^^ error: `into_py_with` is not permitted on `transparent` structs or variants - --> tests/ui/invalid_intopy_derive.rs:112:12 + --> tests/ui/invalid_intopy_derive.rs:131:12 | -112 | #[pyo3(into_py_with = into)] +131 | #[pyo3(into_py_with = into)] | ^^^^^^^^^^^^ error: `into_py_with` is not permitted on `transparent` structs or variants - --> tests/ui/invalid_intopy_derive.rs:119:12 + --> tests/ui/invalid_intopy_derive.rs:139:12 | -119 | #[pyo3(into_py_with = into_ref)] +139 | #[pyo3(into_py_with = into_ref)] | ^^^^^^^^^^^^ error: `into_py_with` is not permitted on `transparent` structs - --> tests/ui/invalid_intopy_derive.rs:125:42 + --> tests/ui/invalid_intopy_derive.rs:146:42 | -125 | struct TupleTransparentIntoPyWith(#[pyo3(into_py_with = into)] String); +146 | struct TupleTransparentIntoPyWith(#[pyo3(into_py_with = into)] String); | ^^^^^^^^^^^^ error: `into_py_with` is not permitted on `transparent` structs - --> tests/ui/invalid_intopy_derive.rs:129:29 + --> tests/ui/invalid_intopy_derive.rs:151:29 | -129 | TransparentTuple(#[pyo3(into_py_with = into)] usize), +151 | TransparentTuple(#[pyo3(into_py_with = into)] usize), | ^^^^^^^^^^^^ error: `into_py_with` is not permitted on `transparent` structs or variants - --> tests/ui/invalid_intopy_derive.rs:136:16 + --> tests/ui/invalid_intopy_derive.rs:159:16 | -136 | #[pyo3(into_py_with = into)] +159 | #[pyo3(into_py_with = into)] | ^^^^^^^^^^^^ error: `rename_all` is not permitted on `transparent` structs and variants - --> tests/ui/invalid_intopy_derive.rs:142:21 + --> tests/ui/invalid_intopy_derive.rs:166:21 | -142 | #[pyo3(transparent, rename_all = "camelCase")] +166 | #[pyo3(transparent, rename_all = "camelCase")] | ^^^^^^^^^^ error: `rename_all` is useless on tuple structs and variants. - --> tests/ui/invalid_intopy_derive.rs:148:8 + --> tests/ui/invalid_intopy_derive.rs:173:8 | -148 | #[pyo3(rename_all = "camelCase")] +173 | #[pyo3(rename_all = "camelCase")] | ^^^^^^^^^^ error: `rename_all` is not permitted on `transparent` structs and variants - --> tests/ui/invalid_intopy_derive.rs:153:12 + --> tests/ui/invalid_intopy_derive.rs:179:12 | -153 | #[pyo3(rename_all = "camelCase")] +179 | #[pyo3(rename_all = "camelCase")] | ^^^^^^^^^^ error: `rename_all` is useless on tuple structs and variants. - --> tests/ui/invalid_intopy_derive.rs:160:12 + --> tests/ui/invalid_intopy_derive.rs:187:12 | -160 | #[pyo3(rename_all = "camelCase")] +187 | #[pyo3(rename_all = "camelCase")] | ^^^^^^^^^^ error: `rename_all` is not supported at top level for enums - --> tests/ui/invalid_intopy_derive.rs:165:8 + --> tests/ui/invalid_intopy_derive.rs:193:8 | -165 | #[pyo3(rename_all = "camelCase")] +193 | #[pyo3(rename_all = "camelCase")] | ^^^^^^^^^^ + +error: aborting due to 29 previous errors diff --git a/tests/ui/invalid_intopy_with.rs b/tests/ui/invalid_intopy_with.rs index 7cc910f57d8..d15d6642370 100644 --- a/tests/ui/invalid_intopy_with.rs +++ b/tests/ui/invalid_intopy_with.rs @@ -3,6 +3,8 @@ use pyo3::{IntoPyObject, IntoPyObjectRef}; #[derive(IntoPyObject, IntoPyObjectRef)] struct InvalidIntoPyWithFn { #[pyo3(into_py_with = into)] +//~^ ERROR: mismatched types +//~| ERROR: mismatched types inner: String, } diff --git a/tests/ui/invalid_intopy_with.stderr b/tests/ui/invalid_intopy_with.stderr index bfa3e6ec274..f0d6a80c250 100644 --- a/tests/ui/invalid_intopy_with.stderr +++ b/tests/ui/invalid_intopy_with.stderr @@ -7,8 +7,8 @@ error[E0308]: mismatched types 5 | #[pyo3(into_py_with = into)] | ^^^^ expected fn pointer, found fn item | - = note: expected fn pointer `for<'a> fn(Cow<'a, _>, Python<'py>) -> Result, PyErr>` - found fn item `for<'a> fn(String, Python<'a>) -> Result, PyErr> {into}` + = note: expected fn pointer `for<'a> fn(Cow<'a, _>, Python<'py>) -> Result, _>` + found fn item `for<'a> fn(String, Python<'a>) -> Result, _> {into}` error[E0308]: mismatched types --> tests/ui/invalid_intopy_with.rs:5:27 @@ -19,5 +19,9 @@ error[E0308]: mismatched types 5 | #[pyo3(into_py_with = into)] | ^^^^ expected fn pointer, found fn item | - = note: expected fn pointer `for<'a> fn(Cow<'a, _>, Python<'py>) -> Result, PyErr>` - found fn item `for<'a> fn(String, Python<'a>) -> Result, PyErr> {into}` + = note: expected fn pointer `for<'a> fn(Cow<'a, _>, Python<'py>) -> Result, _>` + found fn item `for<'a> fn(String, Python<'a>) -> Result, _> {into}` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/invalid_property_args.rs b/tests/ui/invalid_property_args.rs index f35367df7aa..0560ef3ae81 100644 --- a/tests/ui/invalid_property_args.rs +++ b/tests/ui/invalid_property_args.rs @@ -7,6 +7,7 @@ struct ClassWithGetter {} impl ClassWithGetter { #[getter] fn getter_with_arg(&self, _py: Python<'_>, _index: u32) {} +//~^ ERROR: getter function can only have one argument (of type pyo3::Python) } #[pyclass] @@ -16,33 +17,41 @@ struct ClassWithSetter {} impl ClassWithSetter { #[setter] fn setter_with_no_arg(&mut self, _py: Python<'_>) {} +//~^ ERROR: setter function expected to have one argument } #[pymethods] impl ClassWithSetter { #[setter] fn setter_with_too_many_args(&mut self, _py: Python<'_>, _foo: u32, _bar: u32) {} +//~^ ERROR: setter function can have at most two arguments ([pyo3::Python,] and value) } #[pyclass] struct TupleGetterSetterNoName(#[pyo3(get, set)] i32); +//~^ ERROR: `get` and `set` with tuple struct fields require `name` #[pyclass] struct MultipleGet(#[pyo3(get, get)] i32); +//~^ ERROR: `get` may only be specified once #[pyclass] struct MultipleSet(#[pyo3(set, set)] i32); +//~^ ERROR: `set` may only be specified once #[pyclass] struct MultipleName(#[pyo3(name = "foo", name = "bar")] i32); +//~^ ERROR: `name` may only be specified once #[pyclass] struct NameWithoutGetSet(#[pyo3(name = "value")] i32); +//~^ ERROR: `name` is useless without `get` or `set` #[pyclass] struct InvalidGetterType { #[pyo3(get)] value: ::std::marker::PhantomData, +//~^ ERROR: `PhantomData` cannot be converted to a Python object } fn main() {} diff --git a/tests/ui/invalid_property_args.stderr b/tests/ui/invalid_property_args.stderr index 6e1d7282ede..75b71a530ef 100644 --- a/tests/ui/invalid_property_args.stderr +++ b/tests/ui/invalid_property_args.stderr @@ -5,71 +5,75 @@ error: getter function can only have one argument (of type pyo3::Python) | ^^^ error: setter function expected to have one argument - --> tests/ui/invalid_property_args.rs:18:8 + --> tests/ui/invalid_property_args.rs:19:8 | -18 | fn setter_with_no_arg(&mut self, _py: Python<'_>) {} +19 | fn setter_with_no_arg(&mut self, _py: Python<'_>) {} | ^^^^^^^^^^^^^^^^^^ error: setter function can have at most two arguments ([pyo3::Python,] and value) - --> tests/ui/invalid_property_args.rs:24:79 + --> tests/ui/invalid_property_args.rs:26:79 | -24 | fn setter_with_too_many_args(&mut self, _py: Python<'_>, _foo: u32, _bar: u32) {} +26 | fn setter_with_too_many_args(&mut self, _py: Python<'_>, _foo: u32, _bar: u32) {} | ^^^ error: `get` and `set` with tuple struct fields require `name` - --> tests/ui/invalid_property_args.rs:28:50 + --> tests/ui/invalid_property_args.rs:31:50 | -28 | struct TupleGetterSetterNoName(#[pyo3(get, set)] i32); +31 | struct TupleGetterSetterNoName(#[pyo3(get, set)] i32); | ^^^ error: `get` may only be specified once - --> tests/ui/invalid_property_args.rs:31:32 + --> tests/ui/invalid_property_args.rs:35:32 | -31 | struct MultipleGet(#[pyo3(get, get)] i32); +35 | struct MultipleGet(#[pyo3(get, get)] i32); | ^^^ error: `set` may only be specified once - --> tests/ui/invalid_property_args.rs:34:32 + --> tests/ui/invalid_property_args.rs:39:32 | -34 | struct MultipleSet(#[pyo3(set, set)] i32); +39 | struct MultipleSet(#[pyo3(set, set)] i32); | ^^^ error: `name` may only be specified once - --> tests/ui/invalid_property_args.rs:37:42 + --> tests/ui/invalid_property_args.rs:43:42 | -37 | struct MultipleName(#[pyo3(name = "foo", name = "bar")] i32); +43 | struct MultipleName(#[pyo3(name = "foo", name = "bar")] i32); | ^^^^ error: `name` is useless without `get` or `set` - --> tests/ui/invalid_property_args.rs:40:33 + --> tests/ui/invalid_property_args.rs:47:33 | -40 | struct NameWithoutGetSet(#[pyo3(name = "value")] i32); +47 | struct NameWithoutGetSet(#[pyo3(name = "value")] i32); | ^^^^^^^^^^^^^^ error[E0277]: `PhantomData` cannot be converted to a Python object - --> tests/ui/invalid_property_args.rs:45:12 - | -45 | value: ::std::marker::PhantomData, - | ^ required by `#[pyo3(get)]` to create a readable property from a field of type `PhantomData` - | - = help: the trait `IntoPyObject<'_>` is not implemented for `PhantomData` - = note: implement `IntoPyObject` for `&PhantomData` or `IntoPyObject + Clone` for `PhantomData` to define the conversion - = help: the following other types implement trait `IntoPyObject<'py>`: - &&'a T - &&OsStr - &&Path - &&str - &'a (T0, T1) - &'a (T0, T1, T2) - &'a (T0, T1, T2, T3) - &'a (T0, T1, T2, T3, T4) - and $N others - = note: required for `PhantomData` to implement `for<'py> pyo3::impl_::pyclass::PyO3GetField<'py>` + --> tests/ui/invalid_property_args.rs:53:12 + | + 53 | value: ::std::marker::PhantomData, + | ^ required by `#[pyo3(get)]` to create a readable property from a field of type `PhantomData` + | + = help: the trait `IntoPyObject<'_>` is not implemented for `PhantomData` + = note: implement `IntoPyObject` for `&PhantomData` or `IntoPyObject + Clone` for `PhantomData` to define the conversion + = help: the following other types implement trait `IntoPyObject<'py>`: + &&'a T + &&OsStr + &&Path + &&str + &'a (T0, T1) + &'a (T0, T1, T2) + &'a (T0, T1, T2, T3) + &'a (T0, T1, T2, T3, T4) + and $N others + = note: required for `PhantomData` to implement `for<'py> pyo3::impl_::pyclass::PyO3GetField<'py>` note: required by a bound in `pyo3::impl_::pyclass::PyClassGetterGenerator::::generate` - --> src/impl_/pyclass.rs - | - | pub const fn generate(&self, name: &'static CStr, doc: Option<&'static CStr>) -> PyMethodDefType - | -------- required by a bound in this associated function + --> src/impl_/pyclass.rs + | + | pub const fn generate(&self, name: &'static CStr, doc: Option<&'static CStr>) -> PyMethodDefType + | -------- required by a bound in this associated function ... - | for<'py> FieldT: PyO3GetField<'py>, - | ^^^^^^^^^^^^^^^^^ required by this bound in `PyClassGetterGenerator::::generate` + | for<'py> FieldT: PyO3GetField<'py>, + | ^^^^^^^^^^^^^^^^^ required by this bound in `PyClassGetterGenerator::::generate` + +error: aborting due to 9 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/invalid_proto_pymethods.rs b/tests/ui/invalid_proto_pymethods.rs index c40790c3168..aa4fff2c380 100644 --- a/tests/ui/invalid_proto_pymethods.rs +++ b/tests/ui/invalid_proto_pymethods.rs @@ -17,6 +17,7 @@ struct MyClass {} impl MyClass { #[pyo3(name = "__truediv__")] fn truediv_expects_one_argument(&self) -> PyResult<()> { +//~^ ERROR: Expected 1 arguments, got 0 Ok(()) } } @@ -25,6 +26,7 @@ impl MyClass { impl MyClass { #[pyo3(name = "__truediv__")] fn truediv_expects_one_argument_py(&self, _py: Python<'_>) -> PyResult<()> { +//~^ ERROR: Expected 1 arguments, got 0 Ok(()) } } @@ -36,6 +38,7 @@ impl MyClass { #[pymethods] impl MyClass { #[pyo3(name = "__bool__", signature = ())] +//~^ ERROR: `signature` cannot be used with magic method `__bool__` fn signature_is_forbidden(&self) -> bool { true } @@ -44,6 +47,7 @@ impl MyClass { #[pymethods] impl MyClass { #[pyo3(name = "__bool__", text_signature = "")] +//~^ ERROR: `text_signature` cannot be used with magic method `__bool__` fn text_signature_is_forbidden(&self) -> bool { true } @@ -53,6 +57,9 @@ impl MyClass { struct EqAndRichcmp; #[pymethods] +//~^ ERROR: duplicate definitions with name `__pymethod___richcmp____` +//~| ERROR: multiple applicable items in scope +//~| ERROR: multiple applicable items in scope impl EqAndRichcmp { fn __eq__(&self, _other: &Self) -> bool { true diff --git a/tests/ui/invalid_proto_pymethods.stderr b/tests/ui/invalid_proto_pymethods.stderr index feec5192ed2..b8ee7b33d4e 100644 --- a/tests/ui/invalid_proto_pymethods.stderr +++ b/tests/ui/invalid_proto_pymethods.stderr @@ -5,27 +5,27 @@ error: Expected 1 arguments, got 0 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: Expected 1 arguments, got 0 - --> tests/ui/invalid_proto_pymethods.rs:27:8 + --> tests/ui/invalid_proto_pymethods.rs:28:8 | -27 | fn truediv_expects_one_argument_py(&self, _py: Python<'_>) -> PyResult<()> { +28 | fn truediv_expects_one_argument_py(&self, _py: Python<'_>) -> PyResult<()> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: `signature` cannot be used with magic method `__bool__` - --> tests/ui/invalid_proto_pymethods.rs:38:31 + --> tests/ui/invalid_proto_pymethods.rs:40:31 | -38 | #[pyo3(name = "__bool__", signature = ())] +40 | #[pyo3(name = "__bool__", signature = ())] | ^^^^^^^^^ error: `text_signature` cannot be used with magic method `__bool__` - --> tests/ui/invalid_proto_pymethods.rs:46:31 + --> tests/ui/invalid_proto_pymethods.rs:49:31 | -46 | #[pyo3(name = "__bool__", text_signature = "")] +49 | #[pyo3(name = "__bool__", text_signature = "")] | ^^^^^^^^^^^^^^ error[E0592]: duplicate definitions with name `__pymethod___richcmp____` - --> tests/ui/invalid_proto_pymethods.rs:55:1 + --> tests/ui/invalid_proto_pymethods.rs:59:1 | -55 | #[pymethods] +59 | #[pymethods] | ^^^^^^^^^^^^ | | | duplicate definitions for `__pymethod___richcmp____` @@ -34,37 +34,42 @@ error[E0592]: duplicate definitions with name `__pymethod___richcmp____` = note: this error originates in the macro `::pyo3::impl_::pyclass::generate_pyclass_richcompare_slot` which comes from the expansion of the attribute macro `pymethods` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0034]: multiple applicable items in scope - --> tests/ui/invalid_proto_pymethods.rs:55:1 + --> tests/ui/invalid_proto_pymethods.rs:59:1 | -55 | #[pymethods] +59 | #[pymethods] | ^^^^^^^^^^^^ multiple `__pymethod___richcmp____` found | note: candidate #1 is defined in an impl for the type `EqAndRichcmp` - --> tests/ui/invalid_proto_pymethods.rs:55:1 + --> tests/ui/invalid_proto_pymethods.rs:59:1 | -55 | #[pymethods] +59 | #[pymethods] | ^^^^^^^^^^^^ note: candidate #2 is defined in an impl for the type `EqAndRichcmp` - --> tests/ui/invalid_proto_pymethods.rs:55:1 + --> tests/ui/invalid_proto_pymethods.rs:59:1 | -55 | #[pymethods] +59 | #[pymethods] | ^^^^^^^^^^^^ = note: this error originates in the attribute macro `pymethods` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0034]: multiple applicable items in scope - --> tests/ui/invalid_proto_pymethods.rs:55:1 + --> tests/ui/invalid_proto_pymethods.rs:59:1 | -55 | #[pymethods] +59 | #[pymethods] | ^^^^^^^^^^^^ multiple `__pymethod___richcmp____` found | note: candidate #1 is defined in an impl for the type `EqAndRichcmp` - --> tests/ui/invalid_proto_pymethods.rs:55:1 + --> tests/ui/invalid_proto_pymethods.rs:59:1 | -55 | #[pymethods] +59 | #[pymethods] | ^^^^^^^^^^^^ note: candidate #2 is defined in an impl for the type `EqAndRichcmp` - --> tests/ui/invalid_proto_pymethods.rs:55:1 + --> tests/ui/invalid_proto_pymethods.rs:59:1 | -55 | #[pymethods] +59 | #[pymethods] | ^^^^^^^^^^^^ = note: this error originates in the macro `::pyo3::impl_::pyclass::generate_pyclass_richcompare_slot` which comes from the expansion of the attribute macro `pymethods` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 7 previous errors + +Some errors have detailed explanations: E0034, E0592. +For more information about an error, try `rustc --explain E0034`. diff --git a/tests/ui/invalid_pycallargs.rs b/tests/ui/invalid_pycallargs.rs index e3af53d29c2..7feef5205c1 100644 --- a/tests/ui/invalid_pycallargs.rs +++ b/tests/ui/invalid_pycallargs.rs @@ -1,8 +1,9 @@ -use pyo3::prelude::*; - -fn main() { - Python::attach(|py| { - let any = py.None().into_bound(py); - any.call1("foo"); - }) -} +use pyo3::prelude::*; + +fn main() { + Python::attach(|py| { + let any = py.None().into_bound(py); + any.call1("foo"); +//~^ ERROR: `&str` cannot used as a Python `call` argument + }) +} diff --git a/tests/ui/invalid_pycallargs.stderr b/tests/ui/invalid_pycallargs.stderr index 3cd4410f6e9..de1b0fb82f2 100644 --- a/tests/ui/invalid_pycallargs.stderr +++ b/tests/ui/invalid_pycallargs.stderr @@ -1,24 +1,24 @@ error[E0277]: `&str` cannot used as a Python `call` argument - --> tests/ui/invalid_pycallargs.rs:6:19 - | -6 | any.call1("foo"); - | ----- ^^^^^ the trait `PyCallArgs<'_>` is not implemented for `&str` - | | - | required by a bound introduced by this call - | - = note: `PyCallArgs` is implemented for Rust tuples, `Bound<'py, PyTuple>` and `Py` - = note: if your type is convertible to `PyTuple` via `IntoPyObject`, call `.into_pyobject(py)` manually - = note: if you meant to pass the type as a single argument, wrap it in a 1-tuple, `(,)` - = help: the following other types implement trait `PyCallArgs<'py>`: - &'a (T0, T1) - &'a (T0, T1, T2) - &'a (T0, T1, T2, T3) - &'a (T0, T1, T2, T3, T4) - &'a (T0, T1, T2, T3, T4, T5) - &'a (T0, T1, T2, T3, T4, T5, T6) - &'a (T0, T1, T2, T3, T4, T5, T6, T7) - &'a (T0, T1, T2, T3, T4, T5, T6, T7, T8) - and $N others + --> tests/ui/invalid_pycallargs.rs:6:19 + | + 6 | any.call1("foo"); + | ----- ^^^^^ the trait `PyCallArgs<'_>` is not implemented for `&str` + | | + | required by a bound introduced by this call + | + = note: `PyCallArgs` is implemented for Rust tuples, `Bound<'py, PyTuple>` and `Py` + = note: if your type is convertible to `PyTuple` via `IntoPyObject`, call `.into_pyobject(py)` manually + = note: if you meant to pass the type as a single argument, wrap it in a 1-tuple, `(,)` + = help: the following other types implement trait `PyCallArgs<'py>`: + &'a (T0, T1) + &'a (T0, T1, T2) + &'a (T0, T1, T2, T3) + &'a (T0, T1, T2, T3, T4) + &'a (T0, T1, T2, T3, T4, T5) + &'a (T0, T1, T2, T3, T4, T5, T6) + &'a (T0, T1, T2, T3, T4, T5, T6, T7) + &'a (T0, T1, T2, T3, T4, T5, T6, T7, T8) + and $N others note: required by a bound in `call1` --> src/types/any.rs | @@ -28,6 +28,10 @@ note: required by a bound in `call1` | A: PyCallArgs<'py>; | ^^^^^^^^^^^^^^^ required by this bound in `PyAnyMethods::call1` help: use a unary tuple instead - | -6 | any.call1(("foo",)); - | + ++ + | + 6 | any.call1(("foo",)); + | + ++ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/invalid_pyclass_args.rs b/tests/ui/invalid_pyclass_args.rs index 49af59b070d..47caf8b511f 100644 --- a/tests/ui/invalid_pyclass_args.rs +++ b/tests/ui/invalid_pyclass_args.rs @@ -2,43 +2,58 @@ use pyo3::prelude::*; use std::fmt::{Display, Formatter}; #[pyclass(extend=pyo3::types::PyDict)] +//~^ ERROR: expected one of: `crate`, `dict`, `eq`, `eq_int`, `extends`, `freelist`, `frozen`, `get_all`, `hash`, `immutable_type`, `mapping`, `module`, `name`, `ord`, `rename_all`, `sequence`, `set_all`, `new`, `str`, `subclass`, `unsendable`, `weakref`, `generic`, `from_py_object`, `skip_from_py_object` struct TypoIntheKey {} #[pyclass(extends = "PyDict")] +//~^ ERROR: expected identifier struct InvalidExtends {} #[pyclass(name = m::MyClass)] +//~^ ERROR: expected string literal struct InvalidName {} #[pyclass(name = "Custom Name")] +//~^ ERROR: expected a single identifier in double quotes struct InvalidName2 {} #[pyclass(name = CustomName)] +//~^ ERROR: expected string literal struct DeprecatedName {} #[pyclass(rename_all = camelCase)] +//~^ ERROR: expected string literal struct InvalidRenamingRule {} #[pyclass(rename_all = "Camel-Case")] +//~^ ERROR: expected a valid renaming rule, possible values are: "camelCase", "kebab-case", "lowercase", "PascalCase", "SCREAMING-KEBAB-CASE", "SCREAMING_SNAKE_CASE", "snake_case", "UPPERCASE" struct InvalidRenamingRule2 {} #[pyclass(module = my_module)] +//~^ ERROR: expected string literal struct InvalidModule {} #[pyclass(weakrev)] +//~^ ERROR: expected one of: `crate`, `dict`, `eq`, `eq_int`, `extends`, `freelist`, `frozen`, `get_all`, `hash`, `immutable_type`, `mapping`, `module`, `name`, `ord`, `rename_all`, `sequence`, `set_all`, `new`, `str`, `subclass`, `unsendable`, `weakref`, `generic`, `from_py_object`, `skip_from_py_object` struct InvalidArg {} #[pyclass(mapping, sequence)] struct CannotBeMappingAndSequence {} +//~^ ERROR: a `#[pyclass]` cannot be both a `mapping` and a `sequence` #[pyclass(eq)] +//~^ ERROR: binary operation `==` cannot be applied to type `&EqOptRequiresEq` +//~| ERROR: binary operation `!=` cannot be applied to type `&EqOptRequiresEq` struct EqOptRequiresEq {} #[pyclass(eq)] +//~^ ERROR: duplicate definitions with name `__pymethod___richcmp____` +//~| ERROR: multiple applicable items in scope #[derive(PartialEq)] struct EqOptAndManualRichCmp {} #[pymethods] +//~^ ERROR: multiple applicable items in scope impl EqOptAndManualRichCmp { fn __richcmp__( &self, @@ -51,21 +66,28 @@ impl EqOptAndManualRichCmp { } #[pyclass(eq_int)] +//~^ ERROR: `eq_int` can only be used on simple enums. struct NoEqInt {} #[pyclass(frozen, eq, hash)] +//~^ ERROR: the trait bound `HashOptRequiresHash: Hash` is not satisfied #[derive(PartialEq)] struct HashOptRequiresHash; #[pyclass(hash)] +//~^ ERROR: The `hash` option requires the `frozen` option. +//~| ERROR: The `hash` option requires the `eq` option. #[derive(Hash)] struct HashWithoutFrozenAndEq; #[pyclass(frozen, eq, hash)] +//~^ ERROR: duplicate definitions with name `__pymethod___hash____` +//~| ERROR: multiple applicable items in scope #[derive(PartialEq, Hash)] struct HashOptAndManualHash {} #[pymethods] +//~^ ERROR: multiple applicable items in scope impl HashOptAndManualHash { fn __hash__(&self) -> u64 { todo!() @@ -73,6 +95,7 @@ impl HashOptAndManualHash { } #[pyclass(ord)] +//~^ ERROR: The `ord` option requires the `eq` option. struct InvalidOrderedStruct { inner: i32, } @@ -80,13 +103,18 @@ struct InvalidOrderedStruct { #[pyclass] struct MultipleErrors { #[pyo3(foo)] + //~^ ERROR: expected one of: `get`, `set`, `name` #[pyo3(blah)] + //~^ ERROR: expected one of: `get`, `set`, `name` x: i32, #[pyo3(pop)] + //~^ ERROR: expected one of: `get`, `set`, `name` y: i32, } #[pyclass(str)] +//~^ ERROR: duplicate definitions with name `__pymethod___str____` +//~| ERROR: multiple applicable items in scope struct StrOptAndManualStr {} impl Display for StrOptAndManualStr { @@ -96,6 +124,7 @@ impl Display for StrOptAndManualStr { } #[pymethods] +//~^ ERROR: multiple applicable items in scope impl StrOptAndManualStr { fn __str__(&self) -> String { todo!() @@ -103,14 +132,17 @@ impl StrOptAndManualStr { } #[pyclass(str = "{")] +//~^ ERROR: invalid format string: expected `}` but string was terminated #[derive(PartialEq)] struct Coord(u32, u32, u32); #[pyclass(str = "{$}")] +//~^ ERROR: invalid format string: expected `}`, found `$` #[derive(PartialEq)] struct Coord2(u32, u32, u32); #[pyclass(str = "X: {aaaa}, Y: {y}, Z: {z}", skip_from_py_object)] +//~^ ERROR: no field `aaaa` on type `&Point` #[derive(PartialEq, Eq, Clone, PartialOrd)] pub struct Point { x: i32, @@ -119,6 +151,7 @@ pub struct Point { } #[pyclass(str = "X: {x}, Y: {y}}}, Z: {zzz}", skip_from_py_object)] +//~^ ERROR: no field `zzz` on type `&Point2` #[derive(PartialEq, Eq, Clone, PartialOrd)] pub struct Point2 { x: i32, @@ -127,27 +160,32 @@ pub struct Point2 { } #[pyclass(str = "{0}, {162543}, {2}")] +//~^ ERROR: no field `162543` on type `&Coord3` #[derive(PartialEq)] struct Coord3(u32, u32, u32); #[pyclass(name = "aaa", str = "unsafe: {unsafe_variable}")] +//~^ ERROR: The format string syntax is incompatible with any renaming via `name` or `rename_all` struct StructRenamingWithStrFormatter { #[pyo3(name = "unsafe", get, set)] unsafe_variable: usize, } #[pyclass(name = "aaa", str = "unsafe: {unsafe_variable}")] +//~^ ERROR: The format string syntax is incompatible with any renaming via `name` or `rename_all` struct StructRenamingWithStrFormatter2 { unsafe_variable: usize, } #[pyclass(str = "unsafe: {unsafe_variable}")] +//~^ ERROR: The format string syntax is incompatible with any renaming via `name` or `rename_all` struct StructRenamingWithStrFormatter3 { #[pyo3(name = "unsafe", get, set)] unsafe_variable: usize, } #[pyclass(rename_all = "SCREAMING_SNAKE_CASE", str = "{a_a}, {b_b}, {c_d_e}")] +//~^ ERROR: The format string syntax is incompatible with any renaming via `name` or `rename_all` struct RenameAllVariantsStruct { a_a: u32, b_b: u32, @@ -155,6 +193,7 @@ struct RenameAllVariantsStruct { } #[pyclass(str = "{:?}")] +//~^ ERROR: No member found, you must provide a named or positionally specified member. #[derive(Debug)] struct StructWithNoMember { a: String, @@ -162,6 +201,7 @@ struct StructWithNoMember { } #[pyclass(str = "{}")] +//~^ ERROR: No member found, you must provide a named or positionally specified member. #[derive(Debug)] struct StructWithNoMember2 { a: String, @@ -169,6 +209,7 @@ struct StructWithNoMember2 { } #[pyclass(eq, str = "Stuff...")] +//~^ ERROR: The format string syntax cannot be used with enums #[derive(Debug, PartialEq)] pub enum MyEnumInvalidStrFmt { Variant, @@ -182,12 +223,14 @@ impl Display for MyEnumInvalidStrFmt { } #[pyclass(from_py_object, skip_from_py_object)] +//~^ ERROR: `skip_from_py_object` and `from_py_object` are mutually exclusive struct StructTooManyFromPyObject { a: String, b: String, } #[pyclass(from_py_object)] +//~^ ERROR: the trait bound `StructFromPyObjectNoClone: Clone` is not satisfied struct StructFromPyObjectNoClone { a: String, b: String, @@ -203,14 +246,21 @@ struct StructImplicitFromPyObjectDeprecated { #[pyclass(new = "from_fields")] struct NonPythonField { field: Box, + //~^ ERROR: `Box` cannot be used as a Python function argument + //~| ERROR: `Box` cannot be used as a Python function argument + //~| ERROR: the trait bound `dyn std::error::Error + Send + Sync: Clone` is not satisfied } #[pyclass(new = "from_fields")] +//~^ ERROR: conflicting implementations of trait `pyo3::impl_::pyclass::doc::PyClassNewTextSignature` for type `NewFromFieldsWithManualNew` +//~| ERROR: duplicate definitions with name `__pymethod___new____` +//~| ERROR: multiple applicable items in scope struct NewFromFieldsWithManualNew { field: i32, } #[pymethods] +//~^ ERROR: multiple applicable items in scope impl NewFromFieldsWithManualNew { #[new] fn new(field: i32) -> Self { diff --git a/tests/ui/invalid_pyclass_args.stderr b/tests/ui/invalid_pyclass_args.stderr index 90a909b6a8e..6b5b34ebb3d 100644 --- a/tests/ui/invalid_pyclass_args.stderr +++ b/tests/ui/invalid_pyclass_args.stderr @@ -5,105 +5,105 @@ error: expected one of: `crate`, `dict`, `eq`, `eq_int`, `extends`, `freelist`, | ^^^^^^ error: expected identifier - --> tests/ui/invalid_pyclass_args.rs:7:21 + --> tests/ui/invalid_pyclass_args.rs:8:21 | -7 | #[pyclass(extends = "PyDict")] +8 | #[pyclass(extends = "PyDict")] | ^^^^^^^^ error: expected string literal - --> tests/ui/invalid_pyclass_args.rs:10:18 + --> tests/ui/invalid_pyclass_args.rs:12:18 | -10 | #[pyclass(name = m::MyClass)] +12 | #[pyclass(name = m::MyClass)] | ^ error: expected a single identifier in double quotes - --> tests/ui/invalid_pyclass_args.rs:13:18 + --> tests/ui/invalid_pyclass_args.rs:16:18 | -13 | #[pyclass(name = "Custom Name")] +16 | #[pyclass(name = "Custom Name")] | ^^^^^^^^^^^^^ error: expected string literal - --> tests/ui/invalid_pyclass_args.rs:16:18 + --> tests/ui/invalid_pyclass_args.rs:20:18 | -16 | #[pyclass(name = CustomName)] +20 | #[pyclass(name = CustomName)] | ^^^^^^^^^^ error: expected string literal - --> tests/ui/invalid_pyclass_args.rs:19:24 + --> tests/ui/invalid_pyclass_args.rs:24:24 | -19 | #[pyclass(rename_all = camelCase)] +24 | #[pyclass(rename_all = camelCase)] | ^^^^^^^^^ error: expected a valid renaming rule, possible values are: "camelCase", "kebab-case", "lowercase", "PascalCase", "SCREAMING-KEBAB-CASE", "SCREAMING_SNAKE_CASE", "snake_case", "UPPERCASE" - --> tests/ui/invalid_pyclass_args.rs:22:24 + --> tests/ui/invalid_pyclass_args.rs:28:24 | -22 | #[pyclass(rename_all = "Camel-Case")] +28 | #[pyclass(rename_all = "Camel-Case")] | ^^^^^^^^^^^^ error: expected string literal - --> tests/ui/invalid_pyclass_args.rs:25:20 + --> tests/ui/invalid_pyclass_args.rs:32:20 | -25 | #[pyclass(module = my_module)] +32 | #[pyclass(module = my_module)] | ^^^^^^^^^ error: expected one of: `crate`, `dict`, `eq`, `eq_int`, `extends`, `freelist`, `frozen`, `get_all`, `hash`, `immutable_type`, `mapping`, `module`, `name`, `ord`, `rename_all`, `sequence`, `set_all`, `new`, `str`, `subclass`, `unsendable`, `weakref`, `generic`, `from_py_object`, `skip_from_py_object` - --> tests/ui/invalid_pyclass_args.rs:28:11 + --> tests/ui/invalid_pyclass_args.rs:36:11 | -28 | #[pyclass(weakrev)] +36 | #[pyclass(weakrev)] | ^^^^^^^ error: a `#[pyclass]` cannot be both a `mapping` and a `sequence` - --> tests/ui/invalid_pyclass_args.rs:32:8 + --> tests/ui/invalid_pyclass_args.rs:41:8 | -32 | struct CannotBeMappingAndSequence {} +41 | struct CannotBeMappingAndSequence {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error: `eq_int` can only be used on simple enums. - --> tests/ui/invalid_pyclass_args.rs:53:11 + --> tests/ui/invalid_pyclass_args.rs:68:11 | -53 | #[pyclass(eq_int)] +68 | #[pyclass(eq_int)] | ^^^^^^ error: The `hash` option requires the `frozen` option. - --> tests/ui/invalid_pyclass_args.rs:60:11 + --> tests/ui/invalid_pyclass_args.rs:77:11 | -60 | #[pyclass(hash)] +77 | #[pyclass(hash)] | ^^^^ error: The `hash` option requires the `eq` option. - --> tests/ui/invalid_pyclass_args.rs:60:11 + --> tests/ui/invalid_pyclass_args.rs:77:11 | -60 | #[pyclass(hash)] +77 | #[pyclass(hash)] | ^^^^ error: The `ord` option requires the `eq` option. - --> tests/ui/invalid_pyclass_args.rs:75:11 + --> tests/ui/invalid_pyclass_args.rs:97:11 | -75 | #[pyclass(ord)] +97 | #[pyclass(ord)] | ^^^ error: expected one of: `get`, `set`, `name` - --> tests/ui/invalid_pyclass_args.rs:82:12 - | -82 | #[pyo3(foo)] - | ^^^ + --> tests/ui/invalid_pyclass_args.rs:105:12 + | +105 | #[pyo3(foo)] + | ^^^ error: expected one of: `get`, `set`, `name` - --> tests/ui/invalid_pyclass_args.rs:83:12 - | -83 | #[pyo3(blah)] - | ^^^^ + --> tests/ui/invalid_pyclass_args.rs:107:12 + | +107 | #[pyo3(blah)] + | ^^^^ error: expected one of: `get`, `set`, `name` - --> tests/ui/invalid_pyclass_args.rs:85:12 - | -85 | #[pyo3(pop)] - | ^^^ + --> tests/ui/invalid_pyclass_args.rs:110:12 + | +110 | #[pyo3(pop)] + | ^^^ error: invalid format string: expected `}` but string was terminated - --> tests/ui/invalid_pyclass_args.rs:105:19 + --> tests/ui/invalid_pyclass_args.rs:134:19 | -105 | #[pyclass(str = "{")] +134 | #[pyclass(str = "{")] | -^ expected `}` in format string | | | because of this opening brace @@ -111,9 +111,9 @@ error: invalid format string: expected `}` but string was terminated = note: if you intended to print `{`, you can escape it using `{{` error: invalid format string: expected `}`, found `$` - --> tests/ui/invalid_pyclass_args.rs:109:19 + --> tests/ui/invalid_pyclass_args.rs:139:19 | -109 | #[pyclass(str = "{$}")] +139 | #[pyclass(str = "{$}")] | -^ expected `}` in format string | | | because of this opening brace @@ -121,312 +121,312 @@ error: invalid format string: expected `}`, found `$` = note: if you intended to print `{`, you can escape it using `{{` error: The format string syntax is incompatible with any renaming via `name` or `rename_all` - --> tests/ui/invalid_pyclass_args.rs:133:31 + --> tests/ui/invalid_pyclass_args.rs:167:31 | -133 | #[pyclass(name = "aaa", str = "unsafe: {unsafe_variable}")] +167 | #[pyclass(name = "aaa", str = "unsafe: {unsafe_variable}")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: The format string syntax is incompatible with any renaming via `name` or `rename_all` - --> tests/ui/invalid_pyclass_args.rs:139:31 + --> tests/ui/invalid_pyclass_args.rs:174:31 | -139 | #[pyclass(name = "aaa", str = "unsafe: {unsafe_variable}")] +174 | #[pyclass(name = "aaa", str = "unsafe: {unsafe_variable}")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: The format string syntax is incompatible with any renaming via `name` or `rename_all` - --> tests/ui/invalid_pyclass_args.rs:144:17 + --> tests/ui/invalid_pyclass_args.rs:180:17 | -144 | #[pyclass(str = "unsafe: {unsafe_variable}")] +180 | #[pyclass(str = "unsafe: {unsafe_variable}")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: The format string syntax is incompatible with any renaming via `name` or `rename_all` - --> tests/ui/invalid_pyclass_args.rs:150:54 + --> tests/ui/invalid_pyclass_args.rs:187:54 | -150 | #[pyclass(rename_all = "SCREAMING_SNAKE_CASE", str = "{a_a}, {b_b}, {c_d_e}")] +187 | #[pyclass(rename_all = "SCREAMING_SNAKE_CASE", str = "{a_a}, {b_b}, {c_d_e}")] | ^^^^^^^^^^^^^^^^^^^^^^^ error: No member found, you must provide a named or positionally specified member. - --> tests/ui/invalid_pyclass_args.rs:157:17 + --> tests/ui/invalid_pyclass_args.rs:195:17 | -157 | #[pyclass(str = "{:?}")] +195 | #[pyclass(str = "{:?}")] | ^^^^^^ error: No member found, you must provide a named or positionally specified member. - --> tests/ui/invalid_pyclass_args.rs:164:17 + --> tests/ui/invalid_pyclass_args.rs:203:17 | -164 | #[pyclass(str = "{}")] +203 | #[pyclass(str = "{}")] | ^^^^ error: The format string syntax cannot be used with enums - --> tests/ui/invalid_pyclass_args.rs:171:21 + --> tests/ui/invalid_pyclass_args.rs:211:21 | -171 | #[pyclass(eq, str = "Stuff...")] +211 | #[pyclass(eq, str = "Stuff...")] | ^^^^^^^^^^ error: `skip_from_py_object` and `from_py_object` are mutually exclusive - --> tests/ui/invalid_pyclass_args.rs:184:27 + --> tests/ui/invalid_pyclass_args.rs:225:27 | -184 | #[pyclass(from_py_object, skip_from_py_object)] +225 | #[pyclass(from_py_object, skip_from_py_object)] | ^^^^^^^^^^^^^^^^^^^ error[E0277]: the trait bound `StructFromPyObjectNoClone: Clone` is not satisfied - --> tests/ui/invalid_pyclass_args.rs:190:11 + --> tests/ui/invalid_pyclass_args.rs:232:11 | -190 | #[pyclass(from_py_object)] +232 | #[pyclass(from_py_object)] | ^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `StructFromPyObjectNoClone` | = help: see issue #48214 help: consider annotating `StructFromPyObjectNoClone` with `#[derive(Clone)]` | -191 + #[derive(Clone)] -192 | struct StructFromPyObjectNoClone { +234 + #[derive(Clone)] +235 | struct StructFromPyObjectNoClone { | error[E0119]: conflicting implementations of trait `pyo3::impl_::pyclass::doc::PyClassNewTextSignature` for type `NewFromFieldsWithManualNew` - --> tests/ui/invalid_pyclass_args.rs:213:1 + --> tests/ui/invalid_pyclass_args.rs:262:1 | -208 | #[pyclass(new = "from_fields")] +254 | #[pyclass(new = "from_fields")] | ------------------------------- first implementation here ... -213 | #[pymethods] +262 | #[pymethods] | ^^^^^^^^^^^^ conflicting implementation for `NewFromFieldsWithManualNew` | = note: this error originates in the attribute macro `pymethods` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0592]: duplicate definitions with name `__pymethod___richcmp____` - --> tests/ui/invalid_pyclass_args.rs:37:1 + --> tests/ui/invalid_pyclass_args.rs:49:1 | -37 | #[pyclass(eq)] +49 | #[pyclass(eq)] | ^^^^^^^^^^^^^^ duplicate definitions for `__pymethod___richcmp____` ... -41 | #[pymethods] +55 | #[pymethods] | ------------ other definition for `__pymethod___richcmp____` | = note: this error originates in the attribute macro `pyclass` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0592]: duplicate definitions with name `__pymethod___hash____` - --> tests/ui/invalid_pyclass_args.rs:64:1 + --> tests/ui/invalid_pyclass_args.rs:83:1 | -64 | #[pyclass(frozen, eq, hash)] +83 | #[pyclass(frozen, eq, hash)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ duplicate definitions for `__pymethod___hash____` ... -68 | #[pymethods] +89 | #[pymethods] | ------------ other definition for `__pymethod___hash____` | = note: this error originates in the attribute macro `pyclass` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0592]: duplicate definitions with name `__pymethod___str____` - --> tests/ui/invalid_pyclass_args.rs:89:1 - | -89 | #[pyclass(str)] - | ^^^^^^^^^^^^^^^ duplicate definitions for `__pymethod___str____` + --> tests/ui/invalid_pyclass_args.rs:115:1 + | +115 | #[pyclass(str)] + | ^^^^^^^^^^^^^^^ duplicate definitions for `__pymethod___str____` ... -98 | #[pymethods] - | ------------ other definition for `__pymethod___str____` - | - = note: this error originates in the attribute macro `pyclass` (in Nightly builds, run with -Z macro-backtrace for more info) +126 | #[pymethods] + | ------------ other definition for `__pymethod___str____` + | + = note: this error originates in the attribute macro `pyclass` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0592]: duplicate definitions with name `__pymethod___new____` - --> tests/ui/invalid_pyclass_args.rs:208:1 + --> tests/ui/invalid_pyclass_args.rs:254:1 | -208 | #[pyclass(new = "from_fields")] +254 | #[pyclass(new = "from_fields")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ duplicate definitions for `__pymethod___new____` ... -213 | #[pymethods] +262 | #[pymethods] | ------------ other definition for `__pymethod___new____` | = note: this error originates in the attribute macro `pyclass` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0369]: binary operation `==` cannot be applied to type `&EqOptRequiresEq` - --> tests/ui/invalid_pyclass_args.rs:34:11 + --> tests/ui/invalid_pyclass_args.rs:44:11 | -34 | #[pyclass(eq)] +44 | #[pyclass(eq)] | ^^ | note: an implementation of `PartialEq` might be missing for `EqOptRequiresEq` - --> tests/ui/invalid_pyclass_args.rs:35:1 + --> tests/ui/invalid_pyclass_args.rs:47:1 | -35 | struct EqOptRequiresEq {} +47 | struct EqOptRequiresEq {} | ^^^^^^^^^^^^^^^^^^^^^^ must implement `PartialEq` help: consider annotating `EqOptRequiresEq` with `#[derive(PartialEq)]` | -35 + #[derive(PartialEq)] -36 | struct EqOptRequiresEq {} +47 + #[derive(PartialEq)] +48 | struct EqOptRequiresEq {} | error[E0369]: binary operation `!=` cannot be applied to type `&EqOptRequiresEq` - --> tests/ui/invalid_pyclass_args.rs:34:11 + --> tests/ui/invalid_pyclass_args.rs:44:11 | -34 | #[pyclass(eq)] +44 | #[pyclass(eq)] | ^^ | note: an implementation of `PartialEq` might be missing for `EqOptRequiresEq` - --> tests/ui/invalid_pyclass_args.rs:35:1 + --> tests/ui/invalid_pyclass_args.rs:47:1 | -35 | struct EqOptRequiresEq {} +47 | struct EqOptRequiresEq {} | ^^^^^^^^^^^^^^^^^^^^^^ must implement `PartialEq` help: consider annotating `EqOptRequiresEq` with `#[derive(PartialEq)]` | -35 + #[derive(PartialEq)] -36 | struct EqOptRequiresEq {} +47 + #[derive(PartialEq)] +48 | struct EqOptRequiresEq {} | error[E0034]: multiple applicable items in scope - --> tests/ui/invalid_pyclass_args.rs:37:1 + --> tests/ui/invalid_pyclass_args.rs:49:1 | -37 | #[pyclass(eq)] +49 | #[pyclass(eq)] | ^^^^^^^^^^^^^^ multiple `__pymethod___richcmp____` found | note: candidate #1 is defined in an impl for the type `EqOptAndManualRichCmp` - --> tests/ui/invalid_pyclass_args.rs:37:1 + --> tests/ui/invalid_pyclass_args.rs:49:1 | -37 | #[pyclass(eq)] +49 | #[pyclass(eq)] | ^^^^^^^^^^^^^^ note: candidate #2 is defined in an impl for the type `EqOptAndManualRichCmp` - --> tests/ui/invalid_pyclass_args.rs:41:1 + --> tests/ui/invalid_pyclass_args.rs:55:1 | -41 | #[pymethods] +55 | #[pymethods] | ^^^^^^^^^^^^ = note: this error originates in the attribute macro `pyclass` which comes from the expansion of the attribute macro `pymethods` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0034]: multiple applicable items in scope - --> tests/ui/invalid_pyclass_args.rs:41:1 + --> tests/ui/invalid_pyclass_args.rs:55:1 | -41 | #[pymethods] +55 | #[pymethods] | ^^^^^^^^^^^^ multiple `__pymethod___richcmp____` found | note: candidate #1 is defined in an impl for the type `EqOptAndManualRichCmp` - --> tests/ui/invalid_pyclass_args.rs:37:1 + --> tests/ui/invalid_pyclass_args.rs:49:1 | -37 | #[pyclass(eq)] +49 | #[pyclass(eq)] | ^^^^^^^^^^^^^^ note: candidate #2 is defined in an impl for the type `EqOptAndManualRichCmp` - --> tests/ui/invalid_pyclass_args.rs:41:1 + --> tests/ui/invalid_pyclass_args.rs:55:1 | -41 | #[pymethods] +55 | #[pymethods] | ^^^^^^^^^^^^ = note: this error originates in the attribute macro `pymethods` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0277]: the trait bound `HashOptRequiresHash: Hash` is not satisfied - --> tests/ui/invalid_pyclass_args.rs:56:23 + --> tests/ui/invalid_pyclass_args.rs:72:23 | -56 | #[pyclass(frozen, eq, hash)] +72 | #[pyclass(frozen, eq, hash)] | ^^^^ the trait `Hash` is not implemented for `HashOptRequiresHash` | help: consider annotating `HashOptRequiresHash` with `#[derive(Hash)]` | -58 + #[derive(Hash)] -59 | struct HashOptRequiresHash; +75 + #[derive(Hash)] +76 | struct HashOptRequiresHash; | error[E0034]: multiple applicable items in scope - --> tests/ui/invalid_pyclass_args.rs:64:1 + --> tests/ui/invalid_pyclass_args.rs:83:1 | -64 | #[pyclass(frozen, eq, hash)] +83 | #[pyclass(frozen, eq, hash)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ multiple `__pymethod___hash____` found | note: candidate #1 is defined in an impl for the type `HashOptAndManualHash` - --> tests/ui/invalid_pyclass_args.rs:64:1 + --> tests/ui/invalid_pyclass_args.rs:83:1 | -64 | #[pyclass(frozen, eq, hash)] +83 | #[pyclass(frozen, eq, hash)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ note: candidate #2 is defined in an impl for the type `HashOptAndManualHash` - --> tests/ui/invalid_pyclass_args.rs:68:1 + --> tests/ui/invalid_pyclass_args.rs:89:1 | -68 | #[pymethods] +89 | #[pymethods] | ^^^^^^^^^^^^ = note: this error originates in the attribute macro `pyclass` which comes from the expansion of the attribute macro `pymethods` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0034]: multiple applicable items in scope - --> tests/ui/invalid_pyclass_args.rs:68:1 + --> tests/ui/invalid_pyclass_args.rs:89:1 | -68 | #[pymethods] +89 | #[pymethods] | ^^^^^^^^^^^^ multiple `__pymethod___hash____` found | note: candidate #1 is defined in an impl for the type `HashOptAndManualHash` - --> tests/ui/invalid_pyclass_args.rs:64:1 + --> tests/ui/invalid_pyclass_args.rs:83:1 | -64 | #[pyclass(frozen, eq, hash)] +83 | #[pyclass(frozen, eq, hash)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ note: candidate #2 is defined in an impl for the type `HashOptAndManualHash` - --> tests/ui/invalid_pyclass_args.rs:68:1 + --> tests/ui/invalid_pyclass_args.rs:89:1 | -68 | #[pymethods] +89 | #[pymethods] | ^^^^^^^^^^^^ = note: this error originates in the attribute macro `pymethods` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0034]: multiple applicable items in scope - --> tests/ui/invalid_pyclass_args.rs:89:1 - | -89 | #[pyclass(str)] - | ^^^^^^^^^^^^^^^ multiple `__pymethod___str____` found - | + --> tests/ui/invalid_pyclass_args.rs:115:1 + | +115 | #[pyclass(str)] + | ^^^^^^^^^^^^^^^ multiple `__pymethod___str____` found + | note: candidate #1 is defined in an impl for the type `StrOptAndManualStr` - --> tests/ui/invalid_pyclass_args.rs:89:1 - | -89 | #[pyclass(str)] - | ^^^^^^^^^^^^^^^ + --> tests/ui/invalid_pyclass_args.rs:115:1 + | +115 | #[pyclass(str)] + | ^^^^^^^^^^^^^^^ note: candidate #2 is defined in an impl for the type `StrOptAndManualStr` - --> tests/ui/invalid_pyclass_args.rs:98:1 - | -98 | #[pymethods] - | ^^^^^^^^^^^^ - = note: this error originates in the attribute macro `pyclass` which comes from the expansion of the attribute macro `pymethods` (in Nightly builds, run with -Z macro-backtrace for more info) + --> tests/ui/invalid_pyclass_args.rs:126:1 + | +126 | #[pymethods] + | ^^^^^^^^^^^^ + = note: this error originates in the attribute macro `pyclass` which comes from the expansion of the attribute macro `pymethods` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0034]: multiple applicable items in scope - --> tests/ui/invalid_pyclass_args.rs:98:1 - | -98 | #[pymethods] - | ^^^^^^^^^^^^ multiple `__pymethod___str____` found - | + --> tests/ui/invalid_pyclass_args.rs:126:1 + | +126 | #[pymethods] + | ^^^^^^^^^^^^ multiple `__pymethod___str____` found + | note: candidate #1 is defined in an impl for the type `StrOptAndManualStr` - --> tests/ui/invalid_pyclass_args.rs:89:1 - | -89 | #[pyclass(str)] - | ^^^^^^^^^^^^^^^ + --> tests/ui/invalid_pyclass_args.rs:115:1 + | +115 | #[pyclass(str)] + | ^^^^^^^^^^^^^^^ note: candidate #2 is defined in an impl for the type `StrOptAndManualStr` - --> tests/ui/invalid_pyclass_args.rs:98:1 - | -98 | #[pymethods] - | ^^^^^^^^^^^^ - = note: this error originates in the attribute macro `pymethods` (in Nightly builds, run with -Z macro-backtrace for more info) + --> tests/ui/invalid_pyclass_args.rs:126:1 + | +126 | #[pymethods] + | ^^^^^^^^^^^^ + = note: this error originates in the attribute macro `pymethods` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0609]: no field `aaaa` on type `&Point` - --> tests/ui/invalid_pyclass_args.rs:113:17 + --> tests/ui/invalid_pyclass_args.rs:144:17 | -113 | #[pyclass(str = "X: {aaaa}, Y: {y}, Z: {z}", skip_from_py_object)] +144 | #[pyclass(str = "X: {aaaa}, Y: {y}, Z: {z}", skip_from_py_object)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ unknown field | = note: available fields are: `x`, `y`, `z` error[E0609]: no field `zzz` on type `&Point2` - --> tests/ui/invalid_pyclass_args.rs:121:17 + --> tests/ui/invalid_pyclass_args.rs:153:17 | -121 | #[pyclass(str = "X: {x}, Y: {y}}}, Z: {zzz}", skip_from_py_object)] +153 | #[pyclass(str = "X: {x}, Y: {y}}}, Z: {zzz}", skip_from_py_object)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unknown field | = note: available fields are: `x`, `y`, `z` error[E0609]: no field `162543` on type `&Coord3` - --> tests/ui/invalid_pyclass_args.rs:129:17 + --> tests/ui/invalid_pyclass_args.rs:162:17 | -129 | #[pyclass(str = "{0}, {162543}, {2}")] +162 | #[pyclass(str = "{0}, {162543}, {2}")] | ^^^^^^^^^^^^^^^^^^^^ unknown field | = note: available fields are: `0`, `1`, `2` warning: use of deprecated associated constant `pyo3::impl_::deprecated::HasAutomaticFromPyObject::::MSG`: The `FromPyObject` implementation for `#[pyclass]` types which implement `Clone` is changing to an opt-in option. Use `#[pyclass(from_py_object)]` to opt-in to the `FromPyObject` derive now, or `#[pyclass(skip_from_py_object)]` to skip the `FromPyObject` implementation. - --> tests/ui/invalid_pyclass_args.rs:196:1 + --> tests/ui/invalid_pyclass_args.rs:239:1 | -196 | #[pyclass] +239 | #[pyclass] | ^^^^^^^^^^ | = note: `#[warn(deprecated)]` on by default = note: this warning originates in the attribute macro `pyclass` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0277]: `Box` cannot be used as a Python function argument - --> tests/ui/invalid_pyclass_args.rs:205:12 + --> tests/ui/invalid_pyclass_args.rs:248:12 | -205 | field: Box, +248 | field: Box, | ^^^ the trait `PyClass` is not implemented for `Box` | = note: implement `FromPyObject` to enable using `Box` as a function argument @@ -444,18 +444,18 @@ error[E0277]: `Box` cannot be used as a Pyt = note: required for `Box` to implement `pyo3::FromPyObject<'_, '_>` = note: required for `Box` to implement `pyo3::impl_::extract_argument::PyFunctionArgument<'_, '_, '_, true>` note: required by a bound in `pyo3::impl_::extract_argument::extract_argument` - --> src/impl_/extract_argument.rs - | - | pub fn extract_argument<'a, 'holder, 'py, T, const IMPLEMENTS_FROMPYOBJECT: bool>( - | ---------------- required by a bound in this function + --> src/impl_/extract_argument.rs + | + | pub fn extract_argument<'a, 'holder, 'py, T, const IMPLEMENTS_FROMPYOBJECT: bool>( + | ---------------- required by a bound in this function ... - | T: PyFunctionArgument<'a, 'holder, 'py, IMPLEMENTS_FROMPYOBJECT>, - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `extract_argument` + | T: PyFunctionArgument<'a, 'holder, 'py, IMPLEMENTS_FROMPYOBJECT>, + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `extract_argument` error[E0277]: `Box` cannot be used as a Python function argument - --> tests/ui/invalid_pyclass_args.rs:205:12 + --> tests/ui/invalid_pyclass_args.rs:248:12 | -205 | field: Box, +248 | field: Box, | ^^^ the trait `pyo3::impl_::pyclass::ExtractPyClassWithClone` is not implemented for `Box` | = note: implement `FromPyObject` to enable using `Box` as a function argument @@ -473,84 +473,89 @@ error[E0277]: `Box` cannot be used as a Pyt = note: required for `Box` to implement `pyo3::FromPyObject<'_, '_>` = note: required for `Box` to implement `pyo3::impl_::extract_argument::PyFunctionArgument<'_, '_, '_, true>` note: required by a bound in `pyo3::impl_::extract_argument::extract_argument` - --> src/impl_/extract_argument.rs - | - | pub fn extract_argument<'a, 'holder, 'py, T, const IMPLEMENTS_FROMPYOBJECT: bool>( - | ---------------- required by a bound in this function + --> src/impl_/extract_argument.rs + | + | pub fn extract_argument<'a, 'holder, 'py, T, const IMPLEMENTS_FROMPYOBJECT: bool>( + | ---------------- required by a bound in this function ... - | T: PyFunctionArgument<'a, 'holder, 'py, IMPLEMENTS_FROMPYOBJECT>, - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `extract_argument` + | T: PyFunctionArgument<'a, 'holder, 'py, IMPLEMENTS_FROMPYOBJECT>, + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `extract_argument` error[E0277]: the trait bound `dyn std::error::Error + Send + Sync: Clone` is not satisfied - --> tests/ui/invalid_pyclass_args.rs:205:12 + --> tests/ui/invalid_pyclass_args.rs:248:12 | -205 | field: Box, +248 | field: Box, | ^^^ the trait `Clone` is not implemented for `dyn std::error::Error + Send + Sync` | help: the following other types implement trait `pyo3::impl_::extract_argument::PyFunctionArgument<'a, 'holder, 'py, IMPLEMENTS_FROMPYOBJECT>` - --> src/impl_/extract_argument.rs - | - | / impl<'a, 'holder, 'py, T: 'a + 'py> PyFunctionArgument<'a, 'holder, 'py, false> - | | for &'holder Bound<'py, T> - | | where - | | T: PyTypeCheck, - | |___________________^ `&'holder pyo3::Bound<'py, T>` implements `pyo3::impl_::extract_argument::PyFunctionArgument<'a, 'holder, 'py, false>` + --> src/impl_/extract_argument.rs + | + | / impl<'a, 'holder, 'py, T: 'a + 'py> PyFunctionArgument<'a, 'holder, 'py, false> + | | for &'holder Bound<'py, T> + | | where + | | T: PyTypeCheck, + | |___________________^ `&'holder pyo3::Bound<'py, T>` implements `pyo3::impl_::extract_argument::PyFunctionArgument<'a, 'holder, 'py, false>` ... - | / impl<'a, 'holder, 'py, T> PyFunctionArgument<'a, 'holder, 'py, false> for Option - | | where - | | T: PyFunctionArgument<'a, 'holder, 'py, false>, - | |___________________________________________________^ `Option` implements `pyo3::impl_::extract_argument::PyFunctionArgument<'a, 'holder, 'py, false>` + | / impl<'a, 'holder, 'py, T> PyFunctionArgument<'a, 'holder, 'py, false> for Option + | | where + | | T: PyFunctionArgument<'a, 'holder, 'py, false>, + | |___________________________________________________^ `Option` implements `pyo3::impl_::extract_argument::PyFunctionArgument<'a, 'holder, 'py, false>` ... - | impl<'a, 'holder, T: PyClass> PyFunctionArgument<'a, 'holder, '_, false> for &'holder T { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `&'holder T` implements `pyo3::impl_::extract_argument::PyFunctionArgument<'a, 'holder, '_, false>` + | impl<'a, 'holder, T: PyClass> PyFunctionArgument<'a, 'holder, '_, false> for &'holder T { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `&'holder T` implements `pyo3::impl_::extract_argument::PyFunctionArgument<'a, 'holder, '_, false>` ... - | / impl<'a, 'holder, T: PyClass> PyFunctionArgument<'a, 'holder, '_, false> - | | for &'holder mut T - | |______________________^ `&'holder mut T` implements `pyo3::impl_::extract_argument::PyFunctionArgument<'a, 'holder, '_, false>` - = note: required for `Box` to implement `Clone` - = note: required for `Box` to implement `pyo3::FromPyObject<'_, '_>` - = note: required for `Box` to implement `pyo3::impl_::extract_argument::PyFunctionArgument<'_, '_, '_, true>` + | / impl<'a, 'holder, T: PyClass> PyFunctionArgument<'a, 'holder, '_, false> + | | for &'holder mut T + | |______________________^ `&'holder mut T` implements `pyo3::impl_::extract_argument::PyFunctionArgument<'a, 'holder, '_, false>` + = note: required for `Box` to implement `Clone` + = note: required for `Box` to implement `pyo3::FromPyObject<'_, '_>` + = note: required for `Box` to implement `pyo3::impl_::extract_argument::PyFunctionArgument<'_, '_, '_, true>` note: required by a bound in `pyo3::impl_::extract_argument::extract_argument` - --> src/impl_/extract_argument.rs - | - | pub fn extract_argument<'a, 'holder, 'py, T, const IMPLEMENTS_FROMPYOBJECT: bool>( - | ---------------- required by a bound in this function + --> src/impl_/extract_argument.rs + | + | pub fn extract_argument<'a, 'holder, 'py, T, const IMPLEMENTS_FROMPYOBJECT: bool>( + | ---------------- required by a bound in this function ... - | T: PyFunctionArgument<'a, 'holder, 'py, IMPLEMENTS_FROMPYOBJECT>, - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `extract_argument` + | T: PyFunctionArgument<'a, 'holder, 'py, IMPLEMENTS_FROMPYOBJECT>, + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `extract_argument` error[E0034]: multiple applicable items in scope - --> tests/ui/invalid_pyclass_args.rs:208:1 + --> tests/ui/invalid_pyclass_args.rs:254:1 | -208 | #[pyclass(new = "from_fields")] +254 | #[pyclass(new = "from_fields")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ multiple `__pymethod___new____` found | note: candidate #1 is defined in an impl for the type `NewFromFieldsWithManualNew` - --> tests/ui/invalid_pyclass_args.rs:208:1 + --> tests/ui/invalid_pyclass_args.rs:254:1 | -208 | #[pyclass(new = "from_fields")] +254 | #[pyclass(new = "from_fields")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ note: candidate #2 is defined in an impl for the type `NewFromFieldsWithManualNew` - --> tests/ui/invalid_pyclass_args.rs:213:1 + --> tests/ui/invalid_pyclass_args.rs:262:1 | -213 | #[pymethods] +262 | #[pymethods] | ^^^^^^^^^^^^ = note: this error originates in the attribute macro `pyclass` which comes from the expansion of the attribute macro `pymethods` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0034]: multiple applicable items in scope - --> tests/ui/invalid_pyclass_args.rs:213:1 + --> tests/ui/invalid_pyclass_args.rs:262:1 | -213 | #[pymethods] +262 | #[pymethods] | ^^^^^^^^^^^^ multiple `__pymethod___new____` found | note: candidate #1 is defined in an impl for the type `NewFromFieldsWithManualNew` - --> tests/ui/invalid_pyclass_args.rs:208:1 + --> tests/ui/invalid_pyclass_args.rs:254:1 | -208 | #[pyclass(new = "from_fields")] +254 | #[pyclass(new = "from_fields")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ note: candidate #2 is defined in an impl for the type `NewFromFieldsWithManualNew` - --> tests/ui/invalid_pyclass_args.rs:213:1 + --> tests/ui/invalid_pyclass_args.rs:262:1 | -213 | #[pymethods] +262 | #[pymethods] | ^^^^^^^^^^^^ = note: this error originates in the attribute macro `pymethods` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 50 previous errors; 1 warning emitted + +Some errors have detailed explanations: E0034, E0119, E0277, E0369, E0592, E0609. +For more information about an error, try `rustc --explain E0034`. diff --git a/tests/ui/invalid_pyclass_doc.rs b/tests/ui/invalid_pyclass_doc.rs index 55122aa29db..03bfebb883a 100644 --- a/tests/ui/invalid_pyclass_doc.rs +++ b/tests/ui/invalid_pyclass_doc.rs @@ -1,6 +1,7 @@ use pyo3::prelude::*; #[doc = "This \0 contains a nul byte!"] +//~^ ERROR: Python doc may not contain nul byte, found nul at position 5 #[pyclass] struct InvalidDocWithNulByte {} diff --git a/tests/ui/invalid_pyclass_doc.stderr b/tests/ui/invalid_pyclass_doc.stderr index 7341125f85b..aa9d62c27fa 100644 --- a/tests/ui/invalid_pyclass_doc.stderr +++ b/tests/ui/invalid_pyclass_doc.stderr @@ -3,3 +3,5 @@ error: Python doc may not contain nul byte, found nul at position 5 | 3 | #[doc = "This \0 contains a nul byte!"] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 1 previous error diff --git a/tests/ui/invalid_pyclass_enum.rs b/tests/ui/invalid_pyclass_enum.rs index 99ccb8d5fdd..9d1eb63da67 100644 --- a/tests/ui/invalid_pyclass_enum.rs +++ b/tests/ui/invalid_pyclass_enum.rs @@ -1,12 +1,14 @@ use pyo3::prelude::*; #[pyclass(subclass)] +//~^ ERROR: enums can't be inherited by other classes enum NotBaseClass { X, Y, } #[pyclass(extends = PyList)] +//~^ ERROR: enums can't extend from other classes enum NotDerivedClass { X, Y, @@ -14,45 +16,55 @@ enum NotDerivedClass { #[pyclass] enum NoEmptyEnum {} +//~^ ERROR: #[pyclass] can't be used on enums without any variants #[pyclass] enum NoUnitVariants { StructVariant { field: i32 }, UnitVariant, +//~^ ERROR: Unit variant `UnitVariant` is not yet supported in a complex enum } #[pyclass] enum SimpleNoSignature { #[pyo3(constructor = (a, b))] +//~^ ERROR: `constructor` can't be used on a simple enum variant A, B, } #[pyclass(eq, eq_int)] +//~^ ERROR: binary operation `==` cannot be applied to type `&SimpleEqOptRequiresPartialEq` +//~| ERROR: binary operation `!=` cannot be applied to type `&SimpleEqOptRequiresPartialEq` enum SimpleEqOptRequiresPartialEq { A, B, } #[pyclass(eq)] +//~^ ERROR: binary operation `==` cannot be applied to type `&ComplexEqOptRequiresPartialEq` +//~| ERROR: binary operation `!=` cannot be applied to type `&ComplexEqOptRequiresPartialEq` enum ComplexEqOptRequiresPartialEq { A(i32), B { msg: String }, } #[pyclass(eq_int)] +//~^ ERROR: The `eq_int` option requires the `eq` option. enum SimpleEqIntWithoutEq { A, B, } #[pyclass(eq_int)] +//~^ ERROR: `eq_int` can only be used on simple enums. enum NoEqInt { A(i32), B { msg: String }, } #[pyclass(frozen, eq, eq_int, hash)] +//~^ ERROR: the trait bound `SimpleHashOptRequiresHash: Hash` is not satisfied #[derive(PartialEq)] enum SimpleHashOptRequiresHash { A, @@ -60,6 +72,7 @@ enum SimpleHashOptRequiresHash { } #[pyclass(frozen, eq, hash)] +//~^ ERROR: the trait bound `ComplexHashOptRequiresHash: Hash` is not satisfied #[derive(PartialEq)] enum ComplexHashOptRequiresHash { A(i32), @@ -67,6 +80,8 @@ enum ComplexHashOptRequiresHash { } #[pyclass(hash)] +//~^ ERROR: The `hash` option requires the `frozen` option. +//~| ERROR: The `hash` option requires the `eq` option. #[derive(Hash)] enum SimpleHashOptRequiresFrozenAndEq { A, @@ -74,6 +89,7 @@ enum SimpleHashOptRequiresFrozenAndEq { } #[pyclass(hash)] +//~^ ERROR: The `hash` option requires the `eq` option. #[derive(Hash)] enum ComplexHashOptRequiresEq { A(i32), @@ -81,12 +97,17 @@ enum ComplexHashOptRequiresEq { } #[pyclass(ord)] +//~^ ERROR: The `ord` option requires the `eq` option. enum InvalidOrderedComplexEnum { VariantA (i32), VariantB { msg: String } } #[pyclass(eq,ord)] +//~^ ERROR: binary operation `>` cannot be applied to type `&InvalidOrderedComplexEnum2` +//~| ERROR: binary operation `<` cannot be applied to type `&InvalidOrderedComplexEnum2` +//~| ERROR: binary operation `<=` cannot be applied to type `&InvalidOrderedComplexEnum2` +//~| ERROR: binary operation `>=` cannot be applied to type `&InvalidOrderedComplexEnum2` #[derive(PartialEq)] enum InvalidOrderedComplexEnum2 { VariantA (i32), @@ -96,6 +117,7 @@ enum InvalidOrderedComplexEnum2 { #[pyclass(eq)] #[derive(PartialEq)] enum AllEnumVariantsDisabled { +//~^ ERROR: #[pyclass] can't be used on enums without any variants - all variants of enum `AllEnumVariantsDisabled` have been configured out by cfg attributes #[cfg(any())] DisabledA, #[cfg(not(all()))] diff --git a/tests/ui/invalid_pyclass_enum.stderr b/tests/ui/invalid_pyclass_enum.stderr index 80dc9539748..cc5faa53700 100644 --- a/tests/ui/invalid_pyclass_enum.stderr +++ b/tests/ui/invalid_pyclass_enum.stderr @@ -5,229 +5,234 @@ error: enums can't be inherited by other classes | ^^^^^^^^ error: enums can't extend from other classes - --> tests/ui/invalid_pyclass_enum.rs:9:11 - | -9 | #[pyclass(extends = PyList)] - | ^^^^^^^ + --> tests/ui/invalid_pyclass_enum.rs:10:11 + | +10 | #[pyclass(extends = PyList)] + | ^^^^^^^ error: #[pyclass] can't be used on enums without any variants - --> tests/ui/invalid_pyclass_enum.rs:16:18 + --> tests/ui/invalid_pyclass_enum.rs:18:18 | -16 | enum NoEmptyEnum {} +18 | enum NoEmptyEnum {} | ^^ error: Unit variant `UnitVariant` is not yet supported in a complex enum = help: change to an empty tuple variant instead: `UnitVariant()` = note: the enum is complex because of non-unit variant `StructVariant` - --> tests/ui/invalid_pyclass_enum.rs:21:5 + --> tests/ui/invalid_pyclass_enum.rs:24:5 | -21 | UnitVariant, +24 | UnitVariant, | ^^^^^^^^^^^ error: `constructor` can't be used on a simple enum variant - --> tests/ui/invalid_pyclass_enum.rs:26:12 + --> tests/ui/invalid_pyclass_enum.rs:30:12 | -26 | #[pyo3(constructor = (a, b))] +30 | #[pyo3(constructor = (a, b))] | ^^^^^^^^^^^ error: The `eq_int` option requires the `eq` option. - --> tests/ui/invalid_pyclass_enum.rs:43:11 + --> tests/ui/invalid_pyclass_enum.rs:52:11 | -43 | #[pyclass(eq_int)] +52 | #[pyclass(eq_int)] | ^^^^^^ error: `eq_int` can only be used on simple enums. - --> tests/ui/invalid_pyclass_enum.rs:49:11 + --> tests/ui/invalid_pyclass_enum.rs:59:11 | -49 | #[pyclass(eq_int)] +59 | #[pyclass(eq_int)] | ^^^^^^ error: The `hash` option requires the `frozen` option. - --> tests/ui/invalid_pyclass_enum.rs:69:11 + --> tests/ui/invalid_pyclass_enum.rs:82:11 | -69 | #[pyclass(hash)] +82 | #[pyclass(hash)] | ^^^^ error: The `hash` option requires the `eq` option. - --> tests/ui/invalid_pyclass_enum.rs:69:11 + --> tests/ui/invalid_pyclass_enum.rs:82:11 | -69 | #[pyclass(hash)] +82 | #[pyclass(hash)] | ^^^^ error: The `hash` option requires the `eq` option. - --> tests/ui/invalid_pyclass_enum.rs:76:11 + --> tests/ui/invalid_pyclass_enum.rs:91:11 | -76 | #[pyclass(hash)] +91 | #[pyclass(hash)] | ^^^^ error: The `ord` option requires the `eq` option. - --> tests/ui/invalid_pyclass_enum.rs:83:11 + --> tests/ui/invalid_pyclass_enum.rs:99:11 | -83 | #[pyclass(ord)] +99 | #[pyclass(ord)] | ^^^ error: #[pyclass] can't be used on enums without any variants - all variants of enum `AllEnumVariantsDisabled` have been configured out by cfg attributes - --> tests/ui/invalid_pyclass_enum.rs:98:6 - | -98 | enum AllEnumVariantsDisabled { - | ^^^^^^^^^^^^^^^^^^^^^^^ + --> tests/ui/invalid_pyclass_enum.rs:119:6 + | +119 | enum AllEnumVariantsDisabled { + | ^^^^^^^^^^^^^^^^^^^^^^^ error[E0369]: binary operation `==` cannot be applied to type `&SimpleEqOptRequiresPartialEq` - --> tests/ui/invalid_pyclass_enum.rs:31:11 + --> tests/ui/invalid_pyclass_enum.rs:36:11 | -31 | #[pyclass(eq, eq_int)] +36 | #[pyclass(eq, eq_int)] | ^^ | note: an implementation of `PartialEq` might be missing for `SimpleEqOptRequiresPartialEq` - --> tests/ui/invalid_pyclass_enum.rs:32:1 + --> tests/ui/invalid_pyclass_enum.rs:39:1 | -32 | enum SimpleEqOptRequiresPartialEq { +39 | enum SimpleEqOptRequiresPartialEq { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ must implement `PartialEq` help: consider annotating `SimpleEqOptRequiresPartialEq` with `#[derive(PartialEq)]` | -32 + #[derive(PartialEq)] -33 | enum SimpleEqOptRequiresPartialEq { +39 + #[derive(PartialEq)] +40 | enum SimpleEqOptRequiresPartialEq { | error[E0369]: binary operation `!=` cannot be applied to type `&SimpleEqOptRequiresPartialEq` - --> tests/ui/invalid_pyclass_enum.rs:31:11 + --> tests/ui/invalid_pyclass_enum.rs:36:11 | -31 | #[pyclass(eq, eq_int)] +36 | #[pyclass(eq, eq_int)] | ^^ | note: an implementation of `PartialEq` might be missing for `SimpleEqOptRequiresPartialEq` - --> tests/ui/invalid_pyclass_enum.rs:32:1 + --> tests/ui/invalid_pyclass_enum.rs:39:1 | -32 | enum SimpleEqOptRequiresPartialEq { +39 | enum SimpleEqOptRequiresPartialEq { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ must implement `PartialEq` help: consider annotating `SimpleEqOptRequiresPartialEq` with `#[derive(PartialEq)]` | -32 + #[derive(PartialEq)] -33 | enum SimpleEqOptRequiresPartialEq { +39 + #[derive(PartialEq)] +40 | enum SimpleEqOptRequiresPartialEq { | error[E0369]: binary operation `==` cannot be applied to type `&ComplexEqOptRequiresPartialEq` - --> tests/ui/invalid_pyclass_enum.rs:37:11 + --> tests/ui/invalid_pyclass_enum.rs:44:11 | -37 | #[pyclass(eq)] +44 | #[pyclass(eq)] | ^^ | note: an implementation of `PartialEq` might be missing for `ComplexEqOptRequiresPartialEq` - --> tests/ui/invalid_pyclass_enum.rs:38:1 + --> tests/ui/invalid_pyclass_enum.rs:47:1 | -38 | enum ComplexEqOptRequiresPartialEq { +47 | enum ComplexEqOptRequiresPartialEq { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ must implement `PartialEq` help: consider annotating `ComplexEqOptRequiresPartialEq` with `#[derive(PartialEq)]` | -38 + #[derive(PartialEq)] -39 | enum ComplexEqOptRequiresPartialEq { +47 + #[derive(PartialEq)] +48 | enum ComplexEqOptRequiresPartialEq { | error[E0369]: binary operation `!=` cannot be applied to type `&ComplexEqOptRequiresPartialEq` - --> tests/ui/invalid_pyclass_enum.rs:37:11 + --> tests/ui/invalid_pyclass_enum.rs:44:11 | -37 | #[pyclass(eq)] +44 | #[pyclass(eq)] | ^^ | note: an implementation of `PartialEq` might be missing for `ComplexEqOptRequiresPartialEq` - --> tests/ui/invalid_pyclass_enum.rs:38:1 + --> tests/ui/invalid_pyclass_enum.rs:47:1 | -38 | enum ComplexEqOptRequiresPartialEq { +47 | enum ComplexEqOptRequiresPartialEq { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ must implement `PartialEq` help: consider annotating `ComplexEqOptRequiresPartialEq` with `#[derive(PartialEq)]` | -38 + #[derive(PartialEq)] -39 | enum ComplexEqOptRequiresPartialEq { +47 + #[derive(PartialEq)] +48 | enum ComplexEqOptRequiresPartialEq { | error[E0277]: the trait bound `SimpleHashOptRequiresHash: Hash` is not satisfied - --> tests/ui/invalid_pyclass_enum.rs:55:31 + --> tests/ui/invalid_pyclass_enum.rs:66:31 | -55 | #[pyclass(frozen, eq, eq_int, hash)] +66 | #[pyclass(frozen, eq, eq_int, hash)] | ^^^^ the trait `Hash` is not implemented for `SimpleHashOptRequiresHash` | help: consider annotating `SimpleHashOptRequiresHash` with `#[derive(Hash)]` | -57 + #[derive(Hash)] -58 | enum SimpleHashOptRequiresHash { +69 + #[derive(Hash)] +70 | enum SimpleHashOptRequiresHash { | error[E0277]: the trait bound `ComplexHashOptRequiresHash: Hash` is not satisfied - --> tests/ui/invalid_pyclass_enum.rs:62:23 + --> tests/ui/invalid_pyclass_enum.rs:74:23 | -62 | #[pyclass(frozen, eq, hash)] +74 | #[pyclass(frozen, eq, hash)] | ^^^^ the trait `Hash` is not implemented for `ComplexHashOptRequiresHash` | help: consider annotating `ComplexHashOptRequiresHash` with `#[derive(Hash)]` | -64 + #[derive(Hash)] -65 | enum ComplexHashOptRequiresHash { +77 + #[derive(Hash)] +78 | enum ComplexHashOptRequiresHash { | error[E0369]: binary operation `>` cannot be applied to type `&InvalidOrderedComplexEnum2` - --> tests/ui/invalid_pyclass_enum.rs:89:14 - | -89 | #[pyclass(eq,ord)] - | ^^^ - | + --> tests/ui/invalid_pyclass_enum.rs:106:14 + | +106 | #[pyclass(eq,ord)] + | ^^^ + | note: an implementation of `PartialOrd` might be missing for `InvalidOrderedComplexEnum2` - --> tests/ui/invalid_pyclass_enum.rs:91:1 - | -91 | enum InvalidOrderedComplexEnum2 { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ must implement `PartialOrd` + --> tests/ui/invalid_pyclass_enum.rs:112:1 + | +112 | enum InvalidOrderedComplexEnum2 { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ must implement `PartialOrd` help: consider annotating `InvalidOrderedComplexEnum2` with `#[derive(PartialEq, PartialOrd)]` - | -91 + #[derive(PartialEq, PartialOrd)] -92 | enum InvalidOrderedComplexEnum2 { - | + | +112 + #[derive(PartialEq, PartialOrd)] +113 | enum InvalidOrderedComplexEnum2 { + | error[E0369]: binary operation `<` cannot be applied to type `&InvalidOrderedComplexEnum2` - --> tests/ui/invalid_pyclass_enum.rs:89:14 - | -89 | #[pyclass(eq,ord)] - | ^^^ - | + --> tests/ui/invalid_pyclass_enum.rs:106:14 + | +106 | #[pyclass(eq,ord)] + | ^^^ + | note: an implementation of `PartialOrd` might be missing for `InvalidOrderedComplexEnum2` - --> tests/ui/invalid_pyclass_enum.rs:91:1 - | -91 | enum InvalidOrderedComplexEnum2 { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ must implement `PartialOrd` + --> tests/ui/invalid_pyclass_enum.rs:112:1 + | +112 | enum InvalidOrderedComplexEnum2 { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ must implement `PartialOrd` help: consider annotating `InvalidOrderedComplexEnum2` with `#[derive(PartialEq, PartialOrd)]` - | -91 + #[derive(PartialEq, PartialOrd)] -92 | enum InvalidOrderedComplexEnum2 { - | + | +112 + #[derive(PartialEq, PartialOrd)] +113 | enum InvalidOrderedComplexEnum2 { + | error[E0369]: binary operation `<=` cannot be applied to type `&InvalidOrderedComplexEnum2` - --> tests/ui/invalid_pyclass_enum.rs:89:14 - | -89 | #[pyclass(eq,ord)] - | ^^^ - | + --> tests/ui/invalid_pyclass_enum.rs:106:14 + | +106 | #[pyclass(eq,ord)] + | ^^^ + | note: an implementation of `PartialOrd` might be missing for `InvalidOrderedComplexEnum2` - --> tests/ui/invalid_pyclass_enum.rs:91:1 - | -91 | enum InvalidOrderedComplexEnum2 { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ must implement `PartialOrd` + --> tests/ui/invalid_pyclass_enum.rs:112:1 + | +112 | enum InvalidOrderedComplexEnum2 { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ must implement `PartialOrd` help: consider annotating `InvalidOrderedComplexEnum2` with `#[derive(PartialEq, PartialOrd)]` - | -91 + #[derive(PartialEq, PartialOrd)] -92 | enum InvalidOrderedComplexEnum2 { - | + | +112 + #[derive(PartialEq, PartialOrd)] +113 | enum InvalidOrderedComplexEnum2 { + | error[E0369]: binary operation `>=` cannot be applied to type `&InvalidOrderedComplexEnum2` - --> tests/ui/invalid_pyclass_enum.rs:89:14 - | -89 | #[pyclass(eq,ord)] - | ^^^ - | + --> tests/ui/invalid_pyclass_enum.rs:106:14 + | +106 | #[pyclass(eq,ord)] + | ^^^ + | note: an implementation of `PartialOrd` might be missing for `InvalidOrderedComplexEnum2` - --> tests/ui/invalid_pyclass_enum.rs:91:1 - | -91 | enum InvalidOrderedComplexEnum2 { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ must implement `PartialOrd` + --> tests/ui/invalid_pyclass_enum.rs:112:1 + | +112 | enum InvalidOrderedComplexEnum2 { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ must implement `PartialOrd` help: consider annotating `InvalidOrderedComplexEnum2` with `#[derive(PartialEq, PartialOrd)]` - | -91 + #[derive(PartialEq, PartialOrd)] -92 | enum InvalidOrderedComplexEnum2 { - | + | +112 + #[derive(PartialEq, PartialOrd)] +113 | enum InvalidOrderedComplexEnum2 { + | + +error: aborting due to 22 previous errors + +Some errors have detailed explanations: E0277, E0369. +For more information about an error, try `rustc --explain E0277`. diff --git a/tests/ui/invalid_pyclass_generic.rs b/tests/ui/invalid_pyclass_generic.rs index dac8c057d81..23524bb1237 100644 --- a/tests/ui/invalid_pyclass_generic.rs +++ b/tests/ui/invalid_pyclass_generic.rs @@ -2,6 +2,11 @@ use pyo3::prelude::*; use pyo3::types::PyType; #[pyclass(generic)] +//~^ ERROR: duplicate definitions with name `__pymethod___class_getitem____` +//~| ERROR: duplicate definitions with name `__class_getitem__` +//~| ERROR: multiple applicable items in scope +//~| ERROR: multiple applicable items in scope +//~| ERROR: multiple applicable items in scope struct ClassRedefinesClassGetItem {} #[pymethods] @@ -13,10 +18,14 @@ impl ClassRedefinesClassGetItem { #[classmethod] pub fn __class_getitem__( + //~^ ERROR: multiple applicable items in scope + //~| ERROR: multiple applicable items in scope cls: &Bound<'_, PyType>, key: &Bound<'_, PyAny>, ) -> PyResult> { + //~^ ERROR: multiple applicable items in scope pyo3::types::PyGenericAlias::new(cls.py(), cls.as_any(), key) + //~^ ERROR: mismatched types } } diff --git a/tests/ui/invalid_pyclass_generic.stderr b/tests/ui/invalid_pyclass_generic.stderr index 179399d17c3..1a99c4444d4 100644 --- a/tests/ui/invalid_pyclass_generic.stderr +++ b/tests/ui/invalid_pyclass_generic.stderr @@ -1,13 +1,13 @@ error[E0592]: duplicate definitions with name `__pymethod___class_getitem____` - --> tests/ui/invalid_pyclass_generic.rs:4:1 - | -4 | #[pyclass(generic)] - | ^^^^^^^^^^^^^^^^^^^ duplicate definitions for `__pymethod___class_getitem____` + --> tests/ui/invalid_pyclass_generic.rs:4:1 + | + 4 | #[pyclass(generic)] + | ^^^^^^^^^^^^^^^^^^^ duplicate definitions for `__pymethod___class_getitem____` ... -7 | #[pymethods] - | ------------ other definition for `__pymethod___class_getitem____` - | - = note: this error originates in the macro `::pyo3::impl_::pymethods::maybe_define_fastcall_function_with_keywords` which comes from the expansion of the attribute macro `pyclass` (in Nightly builds, run with -Z macro-backtrace for more info) +12 | #[pymethods] + | ------------ other definition for `__pymethod___class_getitem____` + | + = note: this error originates in the macro `::pyo3::impl_::pymethods::maybe_define_fastcall_function_with_keywords` which comes from the expansion of the attribute macro `pyclass` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0592]: duplicate definitions with name `__class_getitem__` --> tests/ui/invalid_pyclass_generic.rs:4:1 @@ -15,31 +15,33 @@ error[E0592]: duplicate definitions with name `__class_getitem__` 4 | #[pyclass(generic)] | ^^^^^^^^^^^^^^^^^^^ duplicate definitions for `__class_getitem__` ... -15 | / pub fn __class_getitem__( -16 | | cls: &Bound<'_, PyType>, -17 | | key: &Bound<'_, PyAny>, -18 | | ) -> PyResult> { +20 | / pub fn __class_getitem__( +21 | | +22 | | +23 | | cls: &Bound<'_, PyType>, +24 | | key: &Bound<'_, PyAny>, +25 | | ) -> PyResult> { | |____________________________- other definition for `__class_getitem__` | = note: this error originates in the attribute macro `pyclass` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0034]: multiple applicable items in scope - --> tests/ui/invalid_pyclass_generic.rs:4:1 - | -4 | #[pyclass(generic)] - | ^^^^^^^^^^^^^^^^^^^ multiple `__pymethod___class_getitem____` found - | + --> tests/ui/invalid_pyclass_generic.rs:4:1 + | + 4 | #[pyclass(generic)] + | ^^^^^^^^^^^^^^^^^^^ multiple `__pymethod___class_getitem____` found + | note: candidate #1 is defined in an impl for the type `ClassRedefinesClassGetItem` - --> tests/ui/invalid_pyclass_generic.rs:4:1 - | -4 | #[pyclass(generic)] - | ^^^^^^^^^^^^^^^^^^^ + --> tests/ui/invalid_pyclass_generic.rs:4:1 + | + 4 | #[pyclass(generic)] + | ^^^^^^^^^^^^^^^^^^^ note: candidate #2 is defined in an impl for the type `ClassRedefinesClassGetItem` - --> tests/ui/invalid_pyclass_generic.rs:7:1 - | -7 | #[pymethods] - | ^^^^^^^^^^^^ - = note: this error originates in the attribute macro `pyclass` which comes from the expansion of the attribute macro `pymethods` (in Nightly builds, run with -Z macro-backtrace for more info) + --> tests/ui/invalid_pyclass_generic.rs:12:1 + | +12 | #[pymethods] + | ^^^^^^^^^^^^ + = note: this error originates in the attribute macro `pyclass` which comes from the expansion of the attribute macro `pymethods` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0034]: multiple applicable items in scope --> tests/ui/invalid_pyclass_generic.rs:4:1 @@ -53,12 +55,14 @@ note: candidate #1 is defined in an impl for the type `ClassRedefinesClassGetIte 4 | #[pyclass(generic)] | ^^^^^^^^^^^^^^^^^^^ note: candidate #2 is defined in an impl for the type `ClassRedefinesClassGetItem` - --> tests/ui/invalid_pyclass_generic.rs:15:5 - | -15 | / pub fn __class_getitem__( -16 | | cls: &Bound<'_, PyType>, -17 | | key: &Bound<'_, PyAny>, -18 | | ) -> PyResult> { + --> tests/ui/invalid_pyclass_generic.rs:20:5 + | +20 | / pub fn __class_getitem__( +21 | | +22 | | +23 | | cls: &Bound<'_, PyType>, +24 | | key: &Bound<'_, PyAny>, +25 | | ) -> PyResult> { | |____________________________^ = note: this error originates in the attribute macro `pyclass` (in Nightly builds, run with -Z macro-backtrace for more info) @@ -73,20 +77,21 @@ error[E0034]: multiple applicable items in scope = note: this error originates in the attribute macro `pyclass` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0308]: mismatched types - --> tests/ui/invalid_pyclass_generic.rs:19:9 + --> tests/ui/invalid_pyclass_generic.rs:27:9 | -18 | ) -> PyResult> { +25 | ) -> PyResult> { | ------------------- expected `Result, PyErr>` because of return type -19 | pyo3::types::PyGenericAlias::new(cls.py(), cls.as_any(), key) +26 | +27 | pyo3::types::PyGenericAlias::new(cls.py(), cls.as_any(), key) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `Result, PyErr>`, found `Result, PyErr>` | - = note: expected enum `Result, PyErr>` - found enum `Result, PyErr>` + = note: expected enum `Result, _>` + found enum `Result, _>` error[E0034]: multiple applicable items in scope - --> tests/ui/invalid_pyclass_generic.rs:15:12 + --> tests/ui/invalid_pyclass_generic.rs:20:12 | -15 | pub fn __class_getitem__( +20 | pub fn __class_getitem__( | ^^^^^^^^^^^^^^^^^ multiple `__pymethod___class_getitem____` found | note: candidate #1 is defined in an impl for the type `ClassRedefinesClassGetItem` @@ -95,16 +100,16 @@ note: candidate #1 is defined in an impl for the type `ClassRedefinesClassGetIte 4 | #[pyclass(generic)] | ^^^^^^^^^^^^^^^^^^^ note: candidate #2 is defined in an impl for the type `ClassRedefinesClassGetItem` - --> tests/ui/invalid_pyclass_generic.rs:7:1 + --> tests/ui/invalid_pyclass_generic.rs:12:1 | - 7 | #[pymethods] +12 | #[pymethods] | ^^^^^^^^^^^^ = note: this error originates in the macro `::pyo3::impl_::pymethods::maybe_define_fastcall_function_with_keywords` which comes from the expansion of the attribute macro `pymethods` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0034]: multiple applicable items in scope - --> tests/ui/invalid_pyclass_generic.rs:15:12 + --> tests/ui/invalid_pyclass_generic.rs:20:12 | -15 | pub fn __class_getitem__( +20 | pub fn __class_getitem__( | ^^^^^^^^^^^^^^^^^ multiple `__class_getitem__` found | note: candidate #1 is defined in an impl for the type `ClassRedefinesClassGetItem` @@ -113,20 +118,27 @@ note: candidate #1 is defined in an impl for the type `ClassRedefinesClassGetIte 4 | #[pyclass(generic)] | ^^^^^^^^^^^^^^^^^^^ note: candidate #2 is defined in an impl for the type `ClassRedefinesClassGetItem` - --> tests/ui/invalid_pyclass_generic.rs:15:5 - | -15 | / pub fn __class_getitem__( -16 | | cls: &Bound<'_, PyType>, -17 | | key: &Bound<'_, PyAny>, -18 | | ) -> PyResult> { + --> tests/ui/invalid_pyclass_generic.rs:20:5 + | +20 | / pub fn __class_getitem__( +21 | | +22 | | +23 | | cls: &Bound<'_, PyType>, +24 | | key: &Bound<'_, PyAny>, +25 | | ) -> PyResult> { | |____________________________^ = note: this error originates in the attribute macro `pyclass` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0034]: multiple applicable items in scope - --> tests/ui/invalid_pyclass_generic.rs:18:10 + --> tests/ui/invalid_pyclass_generic.rs:25:10 | -18 | ) -> PyResult> { +25 | ) -> PyResult> { | ^^^^^^^^ multiple `wrap` found | = note: candidate #1 is defined in an impl for the type `pyo3::impl_::wrap::IntoPyObjectConverter>` = note: candidate #2 is defined in an impl for the type `pyo3::impl_::wrap::IntoPyObjectConverter` + +error: aborting due to 9 previous errors + +Some errors have detailed explanations: E0034, E0308, E0592. +For more information about an error, try `rustc --explain E0034`. diff --git a/tests/ui/invalid_pyclass_init.rs b/tests/ui/invalid_pyclass_init.rs index 5fae78fbec3..faa66796c7c 100644 --- a/tests/ui/invalid_pyclass_init.rs +++ b/tests/ui/invalid_pyclass_init.rs @@ -1,13 +1,14 @@ -use pyo3::prelude::*; - -#[pyclass] -struct InvalidInitReturn; - -#[pymethods] -impl InvalidInitReturn { - fn __init__(&self) -> i32 { - 0 - } -} - -fn main() {} +use pyo3::prelude::*; + +#[pyclass] +struct InvalidInitReturn; + +#[pymethods] +impl InvalidInitReturn { + fn __init__(&self) -> i32 { + //~^ ERROR: the trait bound `i32: pyo3::impl_::callback::IntoPyCallbackOutput<'_, i32>` is not satisfied + 0 + } +} + +fn main() {} diff --git a/tests/ui/invalid_pyclass_init.stderr b/tests/ui/invalid_pyclass_init.stderr index 8380964a1be..0a4bafdb4bb 100644 --- a/tests/ui/invalid_pyclass_init.stderr +++ b/tests/ui/invalid_pyclass_init.stderr @@ -1,9 +1,9 @@ error[E0277]: the trait bound `i32: pyo3::impl_::callback::IntoPyCallbackOutput<'_, i32>` is not satisfied - --> tests/ui/invalid_pyclass_init.rs:8:27 - | -8 | fn __init__(&self) -> i32 { - | ^^^ the trait `pyo3::impl_::callback::IntoPyCallbackOutput<'_, i32>` is not implemented for `i32` - | + --> tests/ui/invalid_pyclass_init.rs:8:27 + | + 8 | fn __init__(&self) -> i32 { + | ^^^ the trait `pyo3::impl_::callback::IntoPyCallbackOutput<'_, i32>` is not implemented for `i32` + | help: the following other types implement trait `pyo3::impl_::callback::IntoPyCallbackOutput<'py, Target>` --> src/impl_/callback.rs | @@ -12,3 +12,7 @@ help: the following other types implement trait `pyo3::impl_::callback::IntoPyCa ... | impl IntoPyCallbackOutput<'_, usize> for usize { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `usize` implements `pyo3::impl_::callback::IntoPyCallbackOutput<'_, usize>` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/invalid_pyclass_item.rs b/tests/ui/invalid_pyclass_item.rs index 4b348540608..03c77ee4a09 100644 --- a/tests/ui/invalid_pyclass_item.rs +++ b/tests/ui/invalid_pyclass_item.rs @@ -2,5 +2,6 @@ use pyo3::prelude::*; #[pyclass] fn foo() {} +//~^ ERROR: #[pyclass] only supports structs and enums. fn main() {} diff --git a/tests/ui/invalid_pyclass_item.stderr b/tests/ui/invalid_pyclass_item.stderr index f29756dfaec..30d7fdec2c8 100644 --- a/tests/ui/invalid_pyclass_item.stderr +++ b/tests/ui/invalid_pyclass_item.stderr @@ -3,3 +3,5 @@ error: #[pyclass] only supports structs and enums. | 4 | fn foo() {} | ^^^^^^^^^^^ + +error: aborting due to 1 previous error diff --git a/tests/ui/invalid_pyfunction_argument.rs b/tests/ui/invalid_pyfunction_argument.rs index 0505c2f0ad0..5f4d61deeb8 100644 --- a/tests/ui/invalid_pyfunction_argument.rs +++ b/tests/ui/invalid_pyfunction_argument.rs @@ -3,6 +3,9 @@ use std::sync::atomic::AtomicPtr; #[pyfunction] fn invalid_pyfunction_argument(arg: AtomicPtr<()>) { + //~^ ERROR: `AtomicPtr<()>` cannot be used as a Python function argument + //~| ERROR: `AtomicPtr<()>` cannot be used as a Python function argument + //~| ERROR: `AtomicPtr<()>` cannot be used as a Python function argument let _ = arg; } @@ -12,6 +15,7 @@ struct Foo; #[pyfunction] fn skip_from_py_object_without_custom_from_py_object(arg: Foo) { + //~^ ERROR: `Foo` cannot be used as a Python function argument let _ = arg; } diff --git a/tests/ui/invalid_pyfunction_argument.stderr b/tests/ui/invalid_pyfunction_argument.stderr index f0f935dd878..20bcce943ec 100644 --- a/tests/ui/invalid_pyfunction_argument.stderr +++ b/tests/ui/invalid_pyfunction_argument.stderr @@ -1,18 +1,18 @@ error[E0277]: `AtomicPtr<()>` cannot be used as a Python function argument - --> tests/ui/invalid_pyfunction_argument.rs:5:37 - | -5 | fn invalid_pyfunction_argument(arg: AtomicPtr<()>) { - | ^^^^^^^^^ the trait `PyClass` is not implemented for `AtomicPtr<()>` - | - = note: implement `FromPyObject` to enable using `AtomicPtr<()>` as a function argument - = note: `Python<'py>` is also a valid argument type to pass the Python token into `#[pyfunction]`s and `#[pymethods]` + --> tests/ui/invalid_pyfunction_argument.rs:5:37 + | + 5 | fn invalid_pyfunction_argument(arg: AtomicPtr<()>) { + | ^^^^^^^^^ the trait `PyClass` is not implemented for `AtomicPtr<()>` + | + = note: implement `FromPyObject` to enable using `AtomicPtr<()>` as a function argument + = note: `Python<'py>` is also a valid argument type to pass the Python token into `#[pyfunction]`s and `#[pymethods]` help: the trait `PyClass` is implemented for `Foo` - --> tests/ui/invalid_pyfunction_argument.rs:9:1 - | -9 | #[pyclass(skip_from_py_object)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - = note: required for `AtomicPtr<()>` to implement `FromPyObject<'_, '_>` - = note: required for `AtomicPtr<()>` to implement `pyo3::impl_::extract_argument::PyFunctionArgument<'_, '_, '_, true>` + --> tests/ui/invalid_pyfunction_argument.rs:12:1 + | + 12 | #[pyclass(skip_from_py_object)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: required for `AtomicPtr<()>` to implement `FromPyObject<'_, '_>` + = note: required for `AtomicPtr<()>` to implement `pyo3::impl_::extract_argument::PyFunctionArgument<'_, '_, '_, true>` note: required by a bound in `pyo3::impl_::extract_argument::extract_argument` --> src/impl_/extract_argument.rs | @@ -24,13 +24,13 @@ note: required by a bound in `pyo3::impl_::extract_argument::extract_argument` = note: this error originates in the attribute macro `pyclass` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0277]: `AtomicPtr<()>` cannot be used as a Python function argument - --> tests/ui/invalid_pyfunction_argument.rs:5:37 - | -5 | fn invalid_pyfunction_argument(arg: AtomicPtr<()>) { - | ^^^^^^^^^ the trait `Clone` is not implemented for `AtomicPtr<()>` - | - = note: implement `FromPyObject` to enable using `AtomicPtr<()>` as a function argument - = note: `Python<'py>` is also a valid argument type to pass the Python token into `#[pyfunction]`s and `#[pymethods]` + --> tests/ui/invalid_pyfunction_argument.rs:5:37 + | + 5 | fn invalid_pyfunction_argument(arg: AtomicPtr<()>) { + | ^^^^^^^^^ the trait `Clone` is not implemented for `AtomicPtr<()>` + | + = note: implement `FromPyObject` to enable using `AtomicPtr<()>` as a function argument + = note: `Python<'py>` is also a valid argument type to pass the Python token into `#[pyfunction]`s and `#[pymethods]` help: the following other types implement trait `pyo3::impl_::extract_argument::PyFunctionArgument<'a, 'holder, 'py, IMPLEMENTS_FROMPYOBJECT>` --> src/impl_/extract_argument.rs | @@ -63,13 +63,13 @@ note: required by a bound in `pyo3::impl_::extract_argument::extract_argument` | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `extract_argument` error[E0277]: `AtomicPtr<()>` cannot be used as a Python function argument - --> tests/ui/invalid_pyfunction_argument.rs:5:37 - | -5 | fn invalid_pyfunction_argument(arg: AtomicPtr<()>) { - | ^^^^^^^^^ the trait `pyo3::impl_::pyclass::ExtractPyClassWithClone` is not implemented for `AtomicPtr<()>` - | - = note: implement `FromPyObject` to enable using `AtomicPtr<()>` as a function argument - = note: `Python<'py>` is also a valid argument type to pass the Python token into `#[pyfunction]`s and `#[pymethods]` + --> tests/ui/invalid_pyfunction_argument.rs:5:37 + | + 5 | fn invalid_pyfunction_argument(arg: AtomicPtr<()>) { + | ^^^^^^^^^ the trait `pyo3::impl_::pyclass::ExtractPyClassWithClone` is not implemented for `AtomicPtr<()>` + | + = note: implement `FromPyObject` to enable using `AtomicPtr<()>` as a function argument + = note: `Python<'py>` is also a valid argument type to pass the Python token into `#[pyfunction]`s and `#[pymethods]` help: the following other types implement trait `pyo3::impl_::extract_argument::PyFunctionArgument<'a, 'holder, 'py, IMPLEMENTS_FROMPYOBJECT>` --> src/impl_/extract_argument.rs | @@ -102,45 +102,49 @@ note: required by a bound in `pyo3::impl_::extract_argument::extract_argument` | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `extract_argument` error[E0277]: `Foo` cannot be used as a Python function argument - --> tests/ui/invalid_pyfunction_argument.rs:14:59 - | -14 | fn skip_from_py_object_without_custom_from_py_object(arg: Foo) { - | ^^^ unsatisfied trait bound - | + --> tests/ui/invalid_pyfunction_argument.rs:17:59 + | + 17 | fn skip_from_py_object_without_custom_from_py_object(arg: Foo) { + | ^^^ unsatisfied trait bound + | help: the trait `pyo3::impl_::pyclass::ExtractPyClassWithClone` is not implemented for `Foo` - --> tests/ui/invalid_pyfunction_argument.rs:11:1 - | -11 | struct Foo; - | ^^^^^^^^^^ - = note: implement `FromPyObject` to enable using `Foo` as a function argument - = note: `Python<'py>` is also a valid argument type to pass the Python token into `#[pyfunction]`s and `#[pymethods]` + --> tests/ui/invalid_pyfunction_argument.rs:14:1 + | + 14 | struct Foo; + | ^^^^^^^^^^ + = note: implement `FromPyObject` to enable using `Foo` as a function argument + = note: `Python<'py>` is also a valid argument type to pass the Python token into `#[pyfunction]`s and `#[pymethods]` help: the following other types implement trait `pyo3::impl_::extract_argument::PyFunctionArgument<'a, 'holder, 'py, IMPLEMENTS_FROMPYOBJECT>` - --> src/impl_/extract_argument.rs - | - | / impl<'a, 'holder, 'py, T: 'a + 'py> PyFunctionArgument<'a, 'holder, 'py, false> - | | for &'holder Bound<'py, T> - | | where - | | T: PyTypeCheck, - | |___________________^ `&'holder pyo3::Bound<'py, T>` implements `pyo3::impl_::extract_argument::PyFunctionArgument<'a, 'holder, 'py, false>` + --> src/impl_/extract_argument.rs + | + | / impl<'a, 'holder, 'py, T: 'a + 'py> PyFunctionArgument<'a, 'holder, 'py, false> + | | for &'holder Bound<'py, T> + | | where + | | T: PyTypeCheck, + | |___________________^ `&'holder pyo3::Bound<'py, T>` implements `pyo3::impl_::extract_argument::PyFunctionArgument<'a, 'holder, 'py, false>` ... - | / impl<'a, 'holder, 'py, T> PyFunctionArgument<'a, 'holder, 'py, false> for Option - | | where - | | T: PyFunctionArgument<'a, 'holder, 'py, false>, - | |___________________________________________________^ `Option` implements `pyo3::impl_::extract_argument::PyFunctionArgument<'a, 'holder, 'py, false>` + | / impl<'a, 'holder, 'py, T> PyFunctionArgument<'a, 'holder, 'py, false> for Option + | | where + | | T: PyFunctionArgument<'a, 'holder, 'py, false>, + | |___________________________________________________^ `Option` implements `pyo3::impl_::extract_argument::PyFunctionArgument<'a, 'holder, 'py, false>` ... - | impl<'a, 'holder, T: PyClass> PyFunctionArgument<'a, 'holder, '_, false> for &'holder T { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `&'holder T` implements `pyo3::impl_::extract_argument::PyFunctionArgument<'a, 'holder, '_, false>` + | impl<'a, 'holder, T: PyClass> PyFunctionArgument<'a, 'holder, '_, false> for &'holder T { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `&'holder T` implements `pyo3::impl_::extract_argument::PyFunctionArgument<'a, 'holder, '_, false>` ... - | / impl<'a, 'holder, T: PyClass> PyFunctionArgument<'a, 'holder, '_, false> - | | for &'holder mut T - | |______________________^ `&'holder mut T` implements `pyo3::impl_::extract_argument::PyFunctionArgument<'a, 'holder, '_, false>` - = note: required for `Foo` to implement `FromPyObject<'_, '_>` - = note: required for `Foo` to implement `pyo3::impl_::extract_argument::PyFunctionArgument<'_, '_, '_, true>` + | / impl<'a, 'holder, T: PyClass> PyFunctionArgument<'a, 'holder, '_, false> + | | for &'holder mut T + | |______________________^ `&'holder mut T` implements `pyo3::impl_::extract_argument::PyFunctionArgument<'a, 'holder, '_, false>` + = note: required for `Foo` to implement `FromPyObject<'_, '_>` + = note: required for `Foo` to implement `pyo3::impl_::extract_argument::PyFunctionArgument<'_, '_, '_, true>` note: required by a bound in `pyo3::impl_::extract_argument::extract_argument` - --> src/impl_/extract_argument.rs - | - | pub fn extract_argument<'a, 'holder, 'py, T, const IMPLEMENTS_FROMPYOBJECT: bool>( - | ---------------- required by a bound in this function + --> src/impl_/extract_argument.rs + | + | pub fn extract_argument<'a, 'holder, 'py, T, const IMPLEMENTS_FROMPYOBJECT: bool>( + | ---------------- required by a bound in this function ... - | T: PyFunctionArgument<'a, 'holder, 'py, IMPLEMENTS_FROMPYOBJECT>, - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `extract_argument` + | T: PyFunctionArgument<'a, 'holder, 'py, IMPLEMENTS_FROMPYOBJECT>, + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `extract_argument` + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/invalid_pyfunction_definition.rs b/tests/ui/invalid_pyfunction_definition.rs index 2f08ff421b9..7dfad1eb38c 100644 --- a/tests/ui/invalid_pyfunction_definition.rs +++ b/tests/ui/invalid_pyfunction_definition.rs @@ -9,6 +9,7 @@ mod pyo3_scratch { impl Foo { #[pyfunction] fn bug() {} +//~^ ERROR: functions inside #[pymethods] do not need to be annotated with #[pyfunction] } } diff --git a/tests/ui/invalid_pyfunction_definition.stderr b/tests/ui/invalid_pyfunction_definition.stderr index 9c7cac1f0f3..35a00fc7e14 100644 --- a/tests/ui/invalid_pyfunction_definition.stderr +++ b/tests/ui/invalid_pyfunction_definition.stderr @@ -3,3 +3,5 @@ error: functions inside #[pymethods] do not need to be annotated with #[pyfuncti | 11 | fn bug() {} | ^^ + +error: aborting due to 1 previous error diff --git a/tests/ui/invalid_pyfunction_signatures.rs b/tests/ui/invalid_pyfunction_signatures.rs index d6799885cbb..ab227e19da9 100644 --- a/tests/ui/invalid_pyfunction_signatures.rs +++ b/tests/ui/invalid_pyfunction_signatures.rs @@ -3,19 +3,23 @@ use pyo3::types::{PyDict, PyTuple}; #[pyfunction] #[pyo3(signature = ())] +//~^ ERROR: missing signature entry for argument `_x` fn function_with_one_argument_empty_signature(_x: i32) {} #[pyfunction] #[pyo3(signature = (x))] +//~^ ERROR: signature entry does not have a corresponding function argument fn function_with_one_entry_signature_no_args() {} #[pyfunction] #[pyo3(signature = (x))] +//~^ ERROR: expected argument from function definition `y` but got argument `x` fn function_with_incorrect_argument_names(y: i32) { let _ = y; } #[pyfunction(x)] +//~^ ERROR: expected one of: `name`, `pass_module`, `signature`, `text_signature`, `crate`, `warn` #[pyo3(signature = (x))] fn function_with_both_args_and_signature(x: i32) { let _ = x; @@ -23,16 +27,19 @@ fn function_with_both_args_and_signature(x: i32) { #[pyfunction] #[pyo3(signature = (*, *args))] +//~^ ERROR: `*args` not allowed after `*` fn function_with_args_after_args_sep(args: &PyTuple) { let _ = args; } #[pyfunction] #[pyo3(signature = (*, *))] +//~^ ERROR: `*` not allowed after `*` fn function_with_args_sep_after_args_sep() {} #[pyfunction] #[pyo3(signature = (**kwargs, *args))] +//~^ ERROR: `*args` not allowed after `**kwargs` fn function_with_args_after_kwargs(kwargs: Option<&PyDict>, args: &PyTuple) { let _ = args; let _ = kwargs; @@ -40,12 +47,14 @@ fn function_with_args_after_kwargs(kwargs: Option<&PyDict>, args: &PyTuple) { #[pyfunction] #[pyo3(signature = (**kwargs_a, **kwargs_b))] +//~^ ERROR: `**kwargs_b` not allowed after `**kwargs_a` fn function_with_kwargs_after_kwargs(kwargs_a: Option<&PyDict>, kwargs_b: Option<&PyDict>) { let _ = kwargs_a; let _ = kwargs_b; } #[pyfunction(signature = (py))] +//~^ ERROR: arguments of type `Python` must not be part of the signature fn signature_contains_py(py: Python<'_>) { let _ = py; } @@ -56,6 +65,7 @@ struct MyClass; #[pymethods] impl MyClass { #[pyo3(signature = (**kwargs, *, *args, x))] +//~^ ERROR: expected argument from function definition `args` but got argument `kwargs` fn multiple_errors_same_order(kwargs: Option<&PyDict>, args: &PyTuple, x: i32) { let _ = kwargs; let _ = args; @@ -63,6 +73,7 @@ impl MyClass { } #[pyo3(signature = (**kwargs, *, *args, x))] +//~^ ERROR: expected argument from function definition `x` but got argument `kwargs` fn multiple_errors_different_order(args: &PyTuple, x: i32, kwargs: Option<&PyDict>) { let _ = kwargs; let _ = args; diff --git a/tests/ui/invalid_pyfunction_signatures.stderr b/tests/ui/invalid_pyfunction_signatures.stderr index c7ddb11dd37..7ad4f52d495 100644 --- a/tests/ui/invalid_pyfunction_signatures.stderr +++ b/tests/ui/invalid_pyfunction_signatures.stderr @@ -5,61 +5,63 @@ error: missing signature entry for argument `_x` | ^^^^^^^^^ error: signature entry does not have a corresponding function argument - --> tests/ui/invalid_pyfunction_signatures.rs:9:21 - | -9 | #[pyo3(signature = (x))] - | ^ + --> tests/ui/invalid_pyfunction_signatures.rs:10:21 + | +10 | #[pyo3(signature = (x))] + | ^ error: expected argument from function definition `y` but got argument `x` - --> tests/ui/invalid_pyfunction_signatures.rs:13:21 + --> tests/ui/invalid_pyfunction_signatures.rs:15:21 | -13 | #[pyo3(signature = (x))] +15 | #[pyo3(signature = (x))] | ^ error: expected one of: `name`, `pass_module`, `signature`, `text_signature`, `crate`, `warn` - --> tests/ui/invalid_pyfunction_signatures.rs:18:14 + --> tests/ui/invalid_pyfunction_signatures.rs:21:14 | -18 | #[pyfunction(x)] +21 | #[pyfunction(x)] | ^ error: `*args` not allowed after `*` - --> tests/ui/invalid_pyfunction_signatures.rs:25:24 + --> tests/ui/invalid_pyfunction_signatures.rs:29:24 | -25 | #[pyo3(signature = (*, *args))] +29 | #[pyo3(signature = (*, *args))] | ^ error: `*` not allowed after `*` - --> tests/ui/invalid_pyfunction_signatures.rs:31:24 + --> tests/ui/invalid_pyfunction_signatures.rs:36:24 | -31 | #[pyo3(signature = (*, *))] +36 | #[pyo3(signature = (*, *))] | ^ error: `*args` not allowed after `**kwargs` - --> tests/ui/invalid_pyfunction_signatures.rs:35:31 + --> tests/ui/invalid_pyfunction_signatures.rs:41:31 | -35 | #[pyo3(signature = (**kwargs, *args))] +41 | #[pyo3(signature = (**kwargs, *args))] | ^ error: `**kwargs_b` not allowed after `**kwargs_a` - --> tests/ui/invalid_pyfunction_signatures.rs:42:33 + --> tests/ui/invalid_pyfunction_signatures.rs:49:33 | -42 | #[pyo3(signature = (**kwargs_a, **kwargs_b))] +49 | #[pyo3(signature = (**kwargs_a, **kwargs_b))] | ^ error: arguments of type `Python` must not be part of the signature - --> tests/ui/invalid_pyfunction_signatures.rs:48:27 + --> tests/ui/invalid_pyfunction_signatures.rs:56:27 | -48 | #[pyfunction(signature = (py))] +56 | #[pyfunction(signature = (py))] | ^^ error: expected argument from function definition `args` but got argument `kwargs` - --> tests/ui/invalid_pyfunction_signatures.rs:58:27 + --> tests/ui/invalid_pyfunction_signatures.rs:67:27 | -58 | #[pyo3(signature = (**kwargs, *, *args, x))] +67 | #[pyo3(signature = (**kwargs, *, *args, x))] | ^^^^^^ error: expected argument from function definition `x` but got argument `kwargs` - --> tests/ui/invalid_pyfunction_signatures.rs:65:27 + --> tests/ui/invalid_pyfunction_signatures.rs:75:27 | -65 | #[pyo3(signature = (**kwargs, *, *args, x))] +75 | #[pyo3(signature = (**kwargs, *, *args, x))] | ^^^^^^ + +error: aborting due to 11 previous errors diff --git a/tests/ui/invalid_pyfunction_warn.rs b/tests/ui/invalid_pyfunction_warn.rs index fe1b72dbc3f..974bc535201 100644 --- a/tests/ui/invalid_pyfunction_warn.rs +++ b/tests/ui/invalid_pyfunction_warn.rs @@ -2,26 +2,32 @@ use pyo3::prelude::*; #[pyfunction] #[pyo3(warn)] +//~^ ERROR: unexpected end of input, expected parentheses fn no_parenthesis_deprecated() {} #[pyfunction] #[pyo3(warn())] +//~^ ERROR: missing `message` in `warn` attribute fn no_message_deprecated() {} #[pyfunction] #[pyo3(warn(category = pyo3::exceptions::PyDeprecationWarning))] +//~^ ERROR: missing `message` in `warn` attribute fn no_message_deprecated_with_category() {} #[pyfunction] #[pyo3(warn(category = pyo3::exceptions::PyDeprecationWarning, message = ,))] +//~^ ERROR: expected string literal fn empty_message_deprecated_with_category() {} #[pyfunction] #[pyo3(warn(message = "deprecated function", category = ,))] +//~^ ERROR: expected identifier fn empty_category_deprecated_with_message() {} #[pyfunction] #[pyo3(warn(message = "deprecated function", random_key))] +//~^ ERROR: expected `message` or `category` fn random_key_deprecated() {} #[pyclass] @@ -31,6 +37,7 @@ struct DeprecatedMethodContainer {} impl DeprecatedMethodContainer { #[classattr] #[pyo3(warn(message = "deprecated class attr"))] +//~^ ERROR: #[classattr] cannot be used with #[pyo3(warn)] fn deprecated_class_attr() -> i32 { 5 } @@ -39,6 +46,7 @@ impl DeprecatedMethodContainer { #[pymethods] impl DeprecatedMethodContainer { #[pyo3(warn(message = "deprecated __traverse__"))] +//~^ ERROR: __traverse__ cannot be used with #[pyo3(warn)] fn __traverse__(&self, _visit: pyo3::gc::PyVisit<'_>) -> Result<(), pyo3::PyTraverseError> { Ok(()) } diff --git a/tests/ui/invalid_pyfunction_warn.stderr b/tests/ui/invalid_pyfunction_warn.stderr index 584abfcdeaf..40491543a9a 100644 --- a/tests/ui/invalid_pyfunction_warn.stderr +++ b/tests/ui/invalid_pyfunction_warn.stderr @@ -5,43 +5,45 @@ error: unexpected end of input, expected parentheses | ^ error: missing `message` in `warn` attribute - --> tests/ui/invalid_pyfunction_warn.rs:8:13 + --> tests/ui/invalid_pyfunction_warn.rs:9:13 | -8 | #[pyo3(warn())] +9 | #[pyo3(warn())] | ^ error: missing `message` in `warn` attribute - --> tests/ui/invalid_pyfunction_warn.rs:12:62 + --> tests/ui/invalid_pyfunction_warn.rs:14:62 | -12 | #[pyo3(warn(category = pyo3::exceptions::PyDeprecationWarning))] +14 | #[pyo3(warn(category = pyo3::exceptions::PyDeprecationWarning))] | ^ error: expected string literal - --> tests/ui/invalid_pyfunction_warn.rs:16:74 + --> tests/ui/invalid_pyfunction_warn.rs:19:74 | -16 | #[pyo3(warn(category = pyo3::exceptions::PyDeprecationWarning, message = ,))] +19 | #[pyo3(warn(category = pyo3::exceptions::PyDeprecationWarning, message = ,))] | ^ error: expected identifier - --> tests/ui/invalid_pyfunction_warn.rs:20:57 + --> tests/ui/invalid_pyfunction_warn.rs:24:57 | -20 | #[pyo3(warn(message = "deprecated function", category = ,))] +24 | #[pyo3(warn(message = "deprecated function", category = ,))] | ^ error: expected `message` or `category` - --> tests/ui/invalid_pyfunction_warn.rs:24:46 + --> tests/ui/invalid_pyfunction_warn.rs:29:46 | -24 | #[pyo3(warn(message = "deprecated function", random_key))] +29 | #[pyo3(warn(message = "deprecated function", random_key))] | ^^^^^^^^^^ error: #[classattr] cannot be used with #[pyo3(warn)] - --> tests/ui/invalid_pyfunction_warn.rs:33:12 + --> tests/ui/invalid_pyfunction_warn.rs:39:12 | -33 | #[pyo3(warn(message = "deprecated class attr"))] +39 | #[pyo3(warn(message = "deprecated class attr"))] | ^^^^ error: __traverse__ cannot be used with #[pyo3(warn)] - --> tests/ui/invalid_pyfunction_warn.rs:41:12 + --> tests/ui/invalid_pyfunction_warn.rs:48:12 | -41 | #[pyo3(warn(message = "deprecated __traverse__"))] +48 | #[pyo3(warn(message = "deprecated __traverse__"))] | ^^^^ + +error: aborting due to 8 previous errors diff --git a/tests/ui/invalid_pyfunctions.rs b/tests/ui/invalid_pyfunctions.rs index cb59808ecc7..a37dd145418 100644 --- a/tests/ui/invalid_pyfunctions.rs +++ b/tests/ui/invalid_pyfunctions.rs @@ -3,34 +3,42 @@ use pyo3::types::{PyDict, PyString, PyTuple}; #[pyfunction] fn generic_function(_value: T) {} +//~^ ERROR: Python functions cannot have generic type parameters #[pyfunction] fn impl_trait_function(_impl_trait: impl AsRef) {} +//~^ ERROR: Python functions cannot have `impl Trait` arguments #[pyfunction] fn wildcard_argument(_: i32) {} +//~^ ERROR: wildcard argument names are not supported #[pyfunction] fn destructured_argument((_a, _b): (i32, i32)) {} +//~^ ERROR: destructuring in arguments is not supported #[pyfunction] #[pyo3(signature=(*args))] fn function_with_optional_args(args: Option>) { + //~^ ERROR: args cannot be optional let _ = args; } #[pyfunction] #[pyo3(signature=(**kwargs))] fn function_with_required_kwargs(kwargs: Bound<'_, PyDict>) { + //~^ ERROR: kwargs must be Option<_> let _ = kwargs; } #[pyfunction(pass_module)] fn pass_module_but_no_arguments<'py>() {} +//~^ ERROR: expected `&PyModule` or `Py` as first argument with `pass_module` #[pyfunction(pass_module)] fn first_argument_not_module<'a, 'py>( _string: &str, + //~^ ERROR: the trait bound `&str: From<&pyo3::Bound<'_, pyo3::types::PyModule>>` is not satisfied module: &'a Bound<'py, PyModule>, ) -> PyResult> { module.name() diff --git a/tests/ui/invalid_pyfunctions.stderr b/tests/ui/invalid_pyfunctions.stderr index 4b55c41c2d4..e383591de60 100644 --- a/tests/ui/invalid_pyfunctions.stderr +++ b/tests/ui/invalid_pyfunctions.stderr @@ -5,45 +5,45 @@ error: Python functions cannot have generic type parameters | ^ error: Python functions cannot have `impl Trait` arguments - --> tests/ui/invalid_pyfunctions.rs:8:37 + --> tests/ui/invalid_pyfunctions.rs:9:37 | -8 | fn impl_trait_function(_impl_trait: impl AsRef) {} +9 | fn impl_trait_function(_impl_trait: impl AsRef) {} | ^^^^ error: wildcard argument names are not supported - --> tests/ui/invalid_pyfunctions.rs:11:22 + --> tests/ui/invalid_pyfunctions.rs:13:22 | -11 | fn wildcard_argument(_: i32) {} +13 | fn wildcard_argument(_: i32) {} | ^ error: destructuring in arguments is not supported - --> tests/ui/invalid_pyfunctions.rs:14:26 + --> tests/ui/invalid_pyfunctions.rs:17:26 | -14 | fn destructured_argument((_a, _b): (i32, i32)) {} +17 | fn destructured_argument((_a, _b): (i32, i32)) {} | ^^^^^^^^ error: args cannot be optional - --> tests/ui/invalid_pyfunctions.rs:18:32 + --> tests/ui/invalid_pyfunctions.rs:22:32 | -18 | fn function_with_optional_args(args: Option>) { +22 | fn function_with_optional_args(args: Option>) { | ^^^^ error: kwargs must be Option<_> - --> tests/ui/invalid_pyfunctions.rs:24:34 + --> tests/ui/invalid_pyfunctions.rs:29:34 | -24 | fn function_with_required_kwargs(kwargs: Bound<'_, PyDict>) { +29 | fn function_with_required_kwargs(kwargs: Bound<'_, PyDict>) { | ^^^^^^ error: expected `&PyModule` or `Py` as first argument with `pass_module` - --> tests/ui/invalid_pyfunctions.rs:29:37 + --> tests/ui/invalid_pyfunctions.rs:35:37 | -29 | fn pass_module_but_no_arguments<'py>() {} +35 | fn pass_module_but_no_arguments<'py>() {} | ^^ error[E0277]: the trait bound `&str: From<&pyo3::Bound<'_, pyo3::types::PyModule>>` is not satisfied - --> tests/ui/invalid_pyfunctions.rs:33:14 + --> tests/ui/invalid_pyfunctions.rs:40:14 | -33 | _string: &str, +40 | _string: &str, | ^ the trait `From<&pyo3::Bound<'_, pyo3::types::PyModule>>` is not implemented for `&str` | = help: the following other types implement trait `From`: @@ -54,3 +54,7 @@ error[E0277]: the trait bound `&str: From<&pyo3::Bound<'_, pyo3::types::PyModule `String` implements `From>` `String` implements `From` = note: required for `&pyo3::Bound<'_, pyo3::types::PyModule>` to implement `Into<&str>` + +error: aborting due to 8 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/invalid_pymethod_enum.rs b/tests/ui/invalid_pymethod_enum.rs index 5c41d19d4e7..062f8b00cc2 100644 --- a/tests/ui/invalid_pymethod_enum.rs +++ b/tests/ui/invalid_pymethod_enum.rs @@ -7,8 +7,10 @@ enum ComplexEnum { } #[pymethods] +//~^ ERROR: type mismatch resolving `::Frozen == False` impl ComplexEnum { fn mutate_in_place(&mut self) { +//~^ ERROR: type mismatch resolving `::Frozen == False` *self = match self { ComplexEnum::Int { int } => ComplexEnum::Str { string: int.to_string() }, ComplexEnum::Str { string } => ComplexEnum::Int { int: string.len() as i32 }, @@ -23,8 +25,10 @@ enum TupleEnum { } #[pymethods] +//~^ ERROR: type mismatch resolving `::Frozen == False` impl TupleEnum { fn mutate_in_place(&mut self) { +//~^ ERROR: type mismatch resolving `::Frozen == False` *self = match self { TupleEnum::Int(int) => TupleEnum::Str(int.to_string()), TupleEnum::Str(string) => TupleEnum::Int(string.len() as i32), diff --git a/tests/ui/invalid_pymethod_enum.stderr b/tests/ui/invalid_pymethod_enum.stderr index 896a637460a..aeaaa240f9d 100644 --- a/tests/ui/invalid_pymethod_enum.stderr +++ b/tests/ui/invalid_pymethod_enum.stderr @@ -1,32 +1,32 @@ error[E0271]: type mismatch resolving `::Frozen == False` - --> tests/ui/invalid_pymethod_enum.rs:11:24 - | -11 | fn mutate_in_place(&mut self) { - | ^ type mismatch resolving `::Frozen == False` - | + --> tests/ui/invalid_pymethod_enum.rs:12:24 + | + 12 | fn mutate_in_place(&mut self) { + | ^ type mismatch resolving `::Frozen == False` + | note: expected this to be `pyo3::pyclass::boolean_struct::False` - --> tests/ui/invalid_pymethod_enum.rs:3:1 - | - 3 | #[pyclass] - | ^^^^^^^^^^ + --> tests/ui/invalid_pymethod_enum.rs:3:1 + | + 3 | #[pyclass] + | ^^^^^^^^^^ note: required by a bound in `pyo3::impl_::extract_argument::extract_pyclass_ref_mut` - --> src/impl_/extract_argument.rs - | - | pub fn extract_pyclass_ref_mut<'a, 'holder, T: PyClass>( - | ^^^^^^^^^^^^^^ required by this bound in `extract_pyclass_ref_mut` - = note: this error originates in the attribute macro `pyclass` (in Nightly builds, run with -Z macro-backtrace for more info) + --> src/impl_/extract_argument.rs + | + | pub fn extract_pyclass_ref_mut<'a, 'holder, T: PyClass>( + | ^^^^^^^^^^^^^^ required by this bound in `extract_pyclass_ref_mut` + = note: this error originates in the attribute macro `pyclass` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0271]: type mismatch resolving `::Frozen == False` - --> tests/ui/invalid_pymethod_enum.rs:9:1 - | -9 | #[pymethods] - | ^^^^^^^^^^^^ type mismatch resolving `::Frozen == False` - | + --> tests/ui/invalid_pymethod_enum.rs:9:1 + | + 9 | #[pymethods] + | ^^^^^^^^^^^^ type mismatch resolving `::Frozen == False` + | note: expected this to be `pyo3::pyclass::boolean_struct::False` - --> tests/ui/invalid_pymethod_enum.rs:3:1 - | -3 | #[pyclass] - | ^^^^^^^^^^ + --> tests/ui/invalid_pymethod_enum.rs:3:1 + | + 3 | #[pyclass] + | ^^^^^^^^^^ note: required by a bound in `PyClassGuardMut` --> src/pyclass/guard.rs | @@ -35,37 +35,41 @@ note: required by a bound in `PyClassGuardMut` = note: this error originates in the attribute macro `pymethods` which comes from the expansion of the attribute macro `pyclass` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0271]: type mismatch resolving `::Frozen == False` - --> tests/ui/invalid_pymethod_enum.rs:27:24 - | -27 | fn mutate_in_place(&mut self) { - | ^ type mismatch resolving `::Frozen == False` - | + --> tests/ui/invalid_pymethod_enum.rs:30:24 + | + 30 | fn mutate_in_place(&mut self) { + | ^ type mismatch resolving `::Frozen == False` + | note: expected this to be `pyo3::pyclass::boolean_struct::False` - --> tests/ui/invalid_pymethod_enum.rs:19:1 - | -19 | #[pyclass] - | ^^^^^^^^^^ + --> tests/ui/invalid_pymethod_enum.rs:21:1 + | + 21 | #[pyclass] + | ^^^^^^^^^^ note: required by a bound in `pyo3::impl_::extract_argument::extract_pyclass_ref_mut` - --> src/impl_/extract_argument.rs - | - | pub fn extract_pyclass_ref_mut<'a, 'holder, T: PyClass>( - | ^^^^^^^^^^^^^^ required by this bound in `extract_pyclass_ref_mut` - = note: this error originates in the attribute macro `pyclass` (in Nightly builds, run with -Z macro-backtrace for more info) + --> src/impl_/extract_argument.rs + | + | pub fn extract_pyclass_ref_mut<'a, 'holder, T: PyClass>( + | ^^^^^^^^^^^^^^ required by this bound in `extract_pyclass_ref_mut` + = note: this error originates in the attribute macro `pyclass` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0271]: type mismatch resolving `::Frozen == False` - --> tests/ui/invalid_pymethod_enum.rs:25:1 - | -25 | #[pymethods] - | ^^^^^^^^^^^^ type mismatch resolving `::Frozen == False` - | + --> tests/ui/invalid_pymethod_enum.rs:27:1 + | + 27 | #[pymethods] + | ^^^^^^^^^^^^ type mismatch resolving `::Frozen == False` + | note: expected this to be `pyo3::pyclass::boolean_struct::False` - --> tests/ui/invalid_pymethod_enum.rs:19:1 - | -19 | #[pyclass] - | ^^^^^^^^^^ + --> tests/ui/invalid_pymethod_enum.rs:21:1 + | + 21 | #[pyclass] + | ^^^^^^^^^^ note: required by a bound in `PyClassGuardMut` - --> src/pyclass/guard.rs - | - | pub struct PyClassGuardMut<'a, T: PyClass> { - | ^^^^^^^^^^^^^^ required by this bound in `PyClassGuardMut` - = note: this error originates in the attribute macro `pymethods` which comes from the expansion of the attribute macro `pyclass` (in Nightly builds, run with -Z macro-backtrace for more info) + --> src/pyclass/guard.rs + | + | pub struct PyClassGuardMut<'a, T: PyClass> { + | ^^^^^^^^^^^^^^ required by this bound in `PyClassGuardMut` + = note: this error originates in the attribute macro `pymethods` which comes from the expansion of the attribute macro `pyclass` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0271`. diff --git a/tests/ui/invalid_pymethod_names.rs b/tests/ui/invalid_pymethod_names.rs index 1334bcabde4..6d910fc8f8a 100644 --- a/tests/ui/invalid_pymethod_names.rs +++ b/tests/ui/invalid_pymethod_names.rs @@ -9,6 +9,7 @@ struct TestClass { impl TestClass { #[pyo3(name = "num")] #[getter(number)] +//~^ ERROR: `name` may only be specified once fn get_num(&self) -> u32 { self.num } } @@ -16,12 +17,14 @@ impl TestClass { impl TestClass { #[pyo3(name = "foo")] #[pyo3(name = "bar")] +//~^ ERROR: `name` may only be specified once fn qux(&self) -> u32 { self.num } } #[pymethods] impl TestClass { #[pyo3(name = "makenew")] +//~^ ERROR: `name` not allowed with `#[new]` #[new] fn new(&self) -> Self { Self { num: 0 } } } @@ -29,12 +32,14 @@ impl TestClass { #[pymethods] impl TestClass { #[getter(1)] +//~^ ERROR: expected ident or string literal for property name fn get_one(&self) -> Self { Self { num: 0 } } } #[pymethods] impl TestClass { #[getter = 1] +//~^ ERROR: expected `#[getter(name)]` to set the name fn get_two(&self) -> Self { Self { num: 0 } } } diff --git a/tests/ui/invalid_pymethod_names.stderr b/tests/ui/invalid_pymethod_names.stderr index 1e7a6f44065..09a031f19c4 100644 --- a/tests/ui/invalid_pymethod_names.stderr +++ b/tests/ui/invalid_pymethod_names.stderr @@ -5,25 +5,27 @@ error: `name` may only be specified once | ^^^^^^ error: `name` may only be specified once - --> tests/ui/invalid_pymethod_names.rs:18:12 + --> tests/ui/invalid_pymethod_names.rs:19:12 | -18 | #[pyo3(name = "bar")] +19 | #[pyo3(name = "bar")] | ^^^^ error: `name` not allowed with `#[new]` - --> tests/ui/invalid_pymethod_names.rs:24:19 + --> tests/ui/invalid_pymethod_names.rs:26:19 | -24 | #[pyo3(name = "makenew")] +26 | #[pyo3(name = "makenew")] | ^^^^^^^^^ error: expected ident or string literal for property name - --> tests/ui/invalid_pymethod_names.rs:31:14 + --> tests/ui/invalid_pymethod_names.rs:34:14 | -31 | #[getter(1)] +34 | #[getter(1)] | ^ error: expected `#[getter(name)]` to set the name - --> tests/ui/invalid_pymethod_names.rs:37:14 + --> tests/ui/invalid_pymethod_names.rs:41:14 | -37 | #[getter = 1] +41 | #[getter = 1] | ^ + +error: aborting due to 5 previous errors diff --git a/tests/ui/invalid_pymethod_receiver.rs b/tests/ui/invalid_pymethod_receiver.rs index 4949ff96022..d0836616f54 100644 --- a/tests/ui/invalid_pymethod_receiver.rs +++ b/tests/ui/invalid_pymethod_receiver.rs @@ -6,6 +6,7 @@ struct MyClass {} #[pymethods] impl MyClass { fn method_with_invalid_self_type(_slf: i32, _py: Python<'_>, _index: u32) {} + //~^ ERROR: the trait bound `i32: TryFrom<&pyo3::Bound<'_, MyClass>>` is not satisfied } fn main() {} diff --git a/tests/ui/invalid_pymethod_receiver.stderr b/tests/ui/invalid_pymethod_receiver.stderr index d40c0be1c32..00e32d60da5 100644 --- a/tests/ui/invalid_pymethod_receiver.stderr +++ b/tests/ui/invalid_pymethod_receiver.stderr @@ -12,3 +12,7 @@ error[E0277]: the trait bound `i32: TryFrom<&pyo3::Bound<'_, MyClass>>` is not s `i32` implements `From` = note: required for `&pyo3::Bound<'_, MyClass>` to implement `Into` = note: required for `i32` to implement `TryFrom<&pyo3::Bound<'_, MyClass>>` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/invalid_pymethods.rs b/tests/ui/invalid_pymethods.rs index 372490ca580..254c74992d0 100644 --- a/tests/ui/invalid_pymethods.rs +++ b/tests/ui/invalid_pymethods.rs @@ -7,20 +7,26 @@ struct MyClass {} impl MyClass { #[classattr] fn class_attr_with_args(_foo: i32) {} + //~^ ERROR: #[classattr] can only have one argument (of type pyo3::Python) #[classattr(foobar)] + //~^ ERROR: `#[classattr]` does not take any arguments const CLASS_ATTR_WITH_ATTRIBUTE_ARG: i32 = 3; fn staticmethod_without_attribute() {} + //~^ ERROR: static method needs #[staticmethod] attribute #[staticmethod] fn staticmethod_with_receiver(&self) {} + //~^ ERROR: unexpected receiver #[classmethod] fn classmethod_with_receiver(&self) {} + //~^ ERROR: Expected `&Bound` or `Py` as the first argument to `#[classmethod]` #[classmethod] fn classmethod_missing_argument() -> Self { + //~^ ERROR: Expected `&Bound` or `Py` as the first argument to `#[classmethod]` Self {} } } @@ -31,6 +37,7 @@ struct NotATypeObject; impl MyClass { #[classmethod] fn classmethod_wrong_first_argument(_t: NotATypeObject) -> Self { + //~^ ERROR: the trait bound `NotATypeObject: From<&pyo3::Bound<'_, PyType>>` is not satisfied Self {} } } @@ -39,36 +46,44 @@ impl MyClass { impl MyClass { #[getter(x)] fn getter_without_receiver() {} + //~^ ERROR: expected receiver for `#[getter]` } #[pymethods] impl MyClass { #[setter(x)] fn setter_without_receiver() {} + //~^ ERROR: expected receiver for `#[setter]` } #[pymethods] impl MyClass { #[pyo3(name = "__call__", text_signature = "()")] fn text_signature_on_call() {} + //~^ ERROR: static method needs #[staticmethod] attribute #[getter(x)] #[pyo3(text_signature = "()")] + //~^ ERROR: `text_signature` not allowed with `getter` fn text_signature_on_getter(&self) {} #[setter(x)] #[pyo3(text_signature = "()")] + //~^ ERROR: `text_signature` not allowed with `setter` fn text_signature_on_setter(&self) {} #[classattr] #[pyo3(text_signature = "()")] + //~^ ERROR: `text_signature` not allowed with `classattr` fn text_signature_on_classattr() {} #[pyo3(text_signature = 1)] + //~^ ERROR: expected a string literal or `None` fn invalid_text_signature() {} #[pyo3(text_signature = "()")] #[pyo3(text_signature = None)] + //~^ ERROR: `text_signature` may only be specified once fn duplicate_text_signature() {} } @@ -76,20 +91,24 @@ impl MyClass { impl MyClass { #[getter(x)] #[pyo3(signature = ())] + //~^ ERROR: `signature` not allowed with `getter` fn signature_on_getter(&self) {} #[setter(x)] #[pyo3(signature = ())] + //~^ ERROR: `signature` not allowed with `setter` fn signature_on_setter(&self) {} #[classattr] #[pyo3(signature = ())] + //~^ ERROR: `signature` not allowed with `classattr` fn signature_on_classattr() {} } #[pymethods] impl MyClass { #[new] + //~^ ERROR: `#[new]` may not be combined with `#[classmethod]` `#[staticmethod]`, `#[classattr]`, `#[getter]`, and `#[setter]` #[classmethod] #[staticmethod] #[classattr] @@ -101,54 +120,64 @@ impl MyClass { #[pymethods] impl MyClass { #[new(signature = ())] + //~^ ERROR: `#[new]` does not take any arguments fn new_takes_no_arguments(&self) {} } #[pymethods] impl MyClass { #[new = ()] // in this form there's no suggestion to move arguments to `#[pyo3()]` attribute + //~^ ERROR: `#[new]` does not take any arguments fn new_takes_no_arguments_nv(&self) {} } #[pymethods] impl MyClass { #[classmethod(signature = ())] + //~^ ERROR: `#[classmethod]` does not take any arguments fn classmethod_takes_no_arguments(&self) {} } #[pymethods] impl MyClass { #[staticmethod(signature = ())] + //~^ ERROR: `#[staticmethod]` does not take any arguments fn staticmethod_takes_no_arguments(&self) {} } #[pymethods] impl MyClass { #[classattr(signature = ())] + //~^ ERROR: `#[classattr]` does not take any arguments fn classattr_takes_no_arguments(&self) {} } #[pymethods] impl MyClass { fn generic_method(_value: T) {} + //~^ ERROR: Python functions cannot have generic type parameters } #[pymethods] impl MyClass { fn impl_trait_method_first_arg(_impl_trait: impl AsRef) {} + //~^ ERROR: Python functions cannot have `impl Trait` arguments fn impl_trait_method_second_arg(&self, _impl_trait: impl AsRef) {} + //~^ ERROR: Python functions cannot have `impl Trait` arguments } #[pymethods] impl MyClass { #[pyo3(pass_module)] + //~^ ERROR: `pass_module` cannot be used on Python methods fn method_cannot_pass_module(&self, _m: &PyModule) {} } #[pymethods] impl MyClass { fn method_self_by_value(self) {} + //~^ ERROR: Python objects are shared, so 'self' cannot be moved out of the Python interpreter. } macro_rules! macro_invocation { @@ -158,19 +187,23 @@ macro_rules! macro_invocation { #[pymethods] impl MyClass { macro_invocation!(); + //~^ ERROR: macros cannot be used as items in `#[pymethods]` impl blocks } #[pymethods] impl MyClass { #[staticmethod] + //~^ ERROR: `#[staticmethod]` may not be combined with `#[classmethod]` #[classmethod] fn multiple_errors_static_and_class_method() {} #[staticmethod] fn multiple_errors_staticmethod_with_receiver(&self) {} + //~^ ERROR: unexpected receiver #[classmethod] fn multiple_errors_classmethod_with_receiver(&self) {} + //~^ ERROR: Expected `&Bound` or `Py` as the first argument to `#[classmethod]` } fn main() {} diff --git a/tests/ui/invalid_pymethods.stderr b/tests/ui/invalid_pymethods.stderr index 9690c0a07e8..2e849e797ef 100644 --- a/tests/ui/invalid_pymethods.stderr +++ b/tests/ui/invalid_pymethods.stderr @@ -5,207 +5,211 @@ error: #[classattr] can only have one argument (of type pyo3::Python) | ^^^ error: `#[classattr]` does not take any arguments - --> tests/ui/invalid_pymethods.rs:11:5 + --> tests/ui/invalid_pymethods.rs:12:5 | -11 | #[classattr(foobar)] +12 | #[classattr(foobar)] | ^ error: static method needs #[staticmethod] attribute - --> tests/ui/invalid_pymethods.rs:14:5 + --> tests/ui/invalid_pymethods.rs:16:5 | -14 | fn staticmethod_without_attribute() {} +16 | fn staticmethod_without_attribute() {} | ^^ error: unexpected receiver - --> tests/ui/invalid_pymethods.rs:17:35 + --> tests/ui/invalid_pymethods.rs:20:35 | -17 | fn staticmethod_with_receiver(&self) {} +20 | fn staticmethod_with_receiver(&self) {} | ^ error: Expected `&Bound` or `Py` as the first argument to `#[classmethod]` - --> tests/ui/invalid_pymethods.rs:20:33 + --> tests/ui/invalid_pymethods.rs:24:33 | -20 | fn classmethod_with_receiver(&self) {} +24 | fn classmethod_with_receiver(&self) {} | ^^^^^^^ error: Expected `&Bound` or `Py` as the first argument to `#[classmethod]` - --> tests/ui/invalid_pymethods.rs:23:36 + --> tests/ui/invalid_pymethods.rs:28:36 | -23 | fn classmethod_missing_argument() -> Self { +28 | fn classmethod_missing_argument() -> Self { | ^^ error: expected receiver for `#[getter]` - --> tests/ui/invalid_pymethods.rs:41:5 + --> tests/ui/invalid_pymethods.rs:48:5 | -41 | fn getter_without_receiver() {} +48 | fn getter_without_receiver() {} | ^^ error: expected receiver for `#[setter]` - --> tests/ui/invalid_pymethods.rs:47:5 + --> tests/ui/invalid_pymethods.rs:55:5 | -47 | fn setter_without_receiver() {} +55 | fn setter_without_receiver() {} | ^^ error: static method needs #[staticmethod] attribute - --> tests/ui/invalid_pymethods.rs:53:5 + --> tests/ui/invalid_pymethods.rs:62:5 | -53 | fn text_signature_on_call() {} +62 | fn text_signature_on_call() {} | ^^ error: `text_signature` not allowed with `getter` - --> tests/ui/invalid_pymethods.rs:56:12 + --> tests/ui/invalid_pymethods.rs:66:12 | -56 | #[pyo3(text_signature = "()")] +66 | #[pyo3(text_signature = "()")] | ^^^^^^^^^^^^^^ error: `text_signature` not allowed with `setter` - --> tests/ui/invalid_pymethods.rs:60:12 + --> tests/ui/invalid_pymethods.rs:71:12 | -60 | #[pyo3(text_signature = "()")] +71 | #[pyo3(text_signature = "()")] | ^^^^^^^^^^^^^^ error: `text_signature` not allowed with `classattr` - --> tests/ui/invalid_pymethods.rs:64:12 + --> tests/ui/invalid_pymethods.rs:76:12 | -64 | #[pyo3(text_signature = "()")] +76 | #[pyo3(text_signature = "()")] | ^^^^^^^^^^^^^^ error: expected a string literal or `None` - --> tests/ui/invalid_pymethods.rs:67:30 + --> tests/ui/invalid_pymethods.rs:80:30 | -67 | #[pyo3(text_signature = 1)] +80 | #[pyo3(text_signature = 1)] | ^ error: `text_signature` may only be specified once - --> tests/ui/invalid_pymethods.rs:71:12 + --> tests/ui/invalid_pymethods.rs:85:12 | -71 | #[pyo3(text_signature = None)] +85 | #[pyo3(text_signature = None)] | ^^^^^^^^^^^^^^ error: `signature` not allowed with `getter` - --> tests/ui/invalid_pymethods.rs:78:12 + --> tests/ui/invalid_pymethods.rs:93:12 | -78 | #[pyo3(signature = ())] +93 | #[pyo3(signature = ())] | ^^^^^^^^^ error: `signature` not allowed with `setter` - --> tests/ui/invalid_pymethods.rs:82:12 + --> tests/ui/invalid_pymethods.rs:98:12 | -82 | #[pyo3(signature = ())] +98 | #[pyo3(signature = ())] | ^^^^^^^^^ error: `signature` not allowed with `classattr` - --> tests/ui/invalid_pymethods.rs:86:12 - | -86 | #[pyo3(signature = ())] - | ^^^^^^^^^ + --> tests/ui/invalid_pymethods.rs:103:12 + | +103 | #[pyo3(signature = ())] + | ^^^^^^^^^ error: `#[new]` may not be combined with `#[classmethod]` `#[staticmethod]`, `#[classattr]`, `#[getter]`, and `#[setter]` - --> tests/ui/invalid_pymethods.rs:92:7 - | -92 | #[new] - | ^^^ + --> tests/ui/invalid_pymethods.rs:110:7 + | +110 | #[new] + | ^^^ error: `#[new]` does not take any arguments = help: did you mean `#[new] #[pyo3(signature = ())]`? - --> tests/ui/invalid_pymethods.rs:103:7 + --> tests/ui/invalid_pymethods.rs:122:7 | -103 | #[new(signature = ())] +122 | #[new(signature = ())] | ^^^ error: `#[new]` does not take any arguments = note: this was previously accepted and ignored - --> tests/ui/invalid_pymethods.rs:109:11 + --> tests/ui/invalid_pymethods.rs:129:11 | -109 | #[new = ()] // in this form there's no suggestion to move arguments to `#[pyo3()]` attribute +129 | #[new = ()] // in this form there's no suggestion to move arguments to `#[pyo3()]` attribute | ^ error: `#[classmethod]` does not take any arguments = help: did you mean `#[classmethod] #[pyo3(signature = ())]`? - --> tests/ui/invalid_pymethods.rs:115:7 + --> tests/ui/invalid_pymethods.rs:136:7 | -115 | #[classmethod(signature = ())] +136 | #[classmethod(signature = ())] | ^^^^^^^^^^^ error: `#[staticmethod]` does not take any arguments = help: did you mean `#[staticmethod] #[pyo3(signature = ())]`? - --> tests/ui/invalid_pymethods.rs:121:7 + --> tests/ui/invalid_pymethods.rs:143:7 | -121 | #[staticmethod(signature = ())] +143 | #[staticmethod(signature = ())] | ^^^^^^^^^^^^ error: `#[classattr]` does not take any arguments = help: did you mean `#[classattr] #[pyo3(signature = ())]`? - --> tests/ui/invalid_pymethods.rs:127:7 + --> tests/ui/invalid_pymethods.rs:150:7 | -127 | #[classattr(signature = ())] +150 | #[classattr(signature = ())] | ^^^^^^^^^ error: Python functions cannot have generic type parameters - --> tests/ui/invalid_pymethods.rs:133:23 + --> tests/ui/invalid_pymethods.rs:157:23 | -133 | fn generic_method(_value: T) {} +157 | fn generic_method(_value: T) {} | ^ error: Python functions cannot have `impl Trait` arguments - --> tests/ui/invalid_pymethods.rs:138:49 + --> tests/ui/invalid_pymethods.rs:163:49 | -138 | fn impl_trait_method_first_arg(_impl_trait: impl AsRef) {} +163 | fn impl_trait_method_first_arg(_impl_trait: impl AsRef) {} | ^^^^ error: Python functions cannot have `impl Trait` arguments - --> tests/ui/invalid_pymethods.rs:140:57 + --> tests/ui/invalid_pymethods.rs:166:57 | -140 | fn impl_trait_method_second_arg(&self, _impl_trait: impl AsRef) {} +166 | fn impl_trait_method_second_arg(&self, _impl_trait: impl AsRef) {} | ^^^^ error: `pass_module` cannot be used on Python methods - --> tests/ui/invalid_pymethods.rs:145:12 + --> tests/ui/invalid_pymethods.rs:172:12 | -145 | #[pyo3(pass_module)] +172 | #[pyo3(pass_module)] | ^^^^^^^^^^^ error: Python objects are shared, so 'self' cannot be moved out of the Python interpreter. Try `&self`, `&mut self, `slf: PyClassGuard<'_, Self>` or `slf: PyClassGuardMut<'_, Self>`. - --> tests/ui/invalid_pymethods.rs:151:29 + --> tests/ui/invalid_pymethods.rs:179:29 | -151 | fn method_self_by_value(self) {} +179 | fn method_self_by_value(self) {} | ^^^^ error: macros cannot be used as items in `#[pymethods]` impl blocks = note: this was previously accepted and ignored - --> tests/ui/invalid_pymethods.rs:160:5 + --> tests/ui/invalid_pymethods.rs:189:5 | -160 | macro_invocation!(); +189 | macro_invocation!(); | ^^^^^^^^^^^^^^^^ error: `#[staticmethod]` may not be combined with `#[classmethod]` - --> tests/ui/invalid_pymethods.rs:165:7 + --> tests/ui/invalid_pymethods.rs:195:7 | -165 | #[staticmethod] +195 | #[staticmethod] | ^^^^^^^^^^^^ error: unexpected receiver - --> tests/ui/invalid_pymethods.rs:170:51 + --> tests/ui/invalid_pymethods.rs:201:51 | -170 | fn multiple_errors_staticmethod_with_receiver(&self) {} +201 | fn multiple_errors_staticmethod_with_receiver(&self) {} | ^ error: Expected `&Bound` or `Py` as the first argument to `#[classmethod]` - --> tests/ui/invalid_pymethods.rs:173:49 + --> tests/ui/invalid_pymethods.rs:205:49 | -173 | fn multiple_errors_classmethod_with_receiver(&self) {} +205 | fn multiple_errors_classmethod_with_receiver(&self) {} | ^^^^^^^ error[E0277]: the trait bound `NotATypeObject: From<&pyo3::Bound<'_, PyType>>` is not satisfied - --> tests/ui/invalid_pymethods.rs:33:45 + --> tests/ui/invalid_pymethods.rs:39:45 | -33 | fn classmethod_wrong_first_argument(_t: NotATypeObject) -> Self { +39 | fn classmethod_wrong_first_argument(_t: NotATypeObject) -> Self { | ^^^^^^^^^^^^^^ unsatisfied trait bound | help: the trait `From<&pyo3::Bound<'_, PyType>>` is not implemented for `NotATypeObject` - --> tests/ui/invalid_pymethods.rs:28:1 + --> tests/ui/invalid_pymethods.rs:34:1 | -28 | struct NotATypeObject; +34 | struct NotATypeObject; | ^^^^^^^^^^^^^^^^^^^^^ = note: required for `&pyo3::Bound<'_, PyType>` to implement `Into` + +error: aborting due to 33 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/invalid_pymethods_buffer.rs b/tests/ui/invalid_pymethods_buffer.rs index d16eddee37a..f518bdd4774 100644 --- a/tests/ui/invalid_pymethods_buffer.rs +++ b/tests/ui/invalid_pymethods_buffer.rs @@ -7,12 +7,14 @@ struct MyClass {} impl MyClass { #[pyo3(name = "__getbuffer__")] fn getbuffer_must_be_unsafe(&self, _view: *mut pyo3::ffi::Py_buffer, _flags: std::ffi::c_int) {} +//~^ ERROR: `__getbuffer__` must be `unsafe fn` } #[pymethods] impl MyClass { #[pyo3(name = "__releasebuffer__")] fn releasebuffer_must_be_unsafe(&self, _view: *mut pyo3::ffi::Py_buffer) {} +//~^ ERROR: `__releasebuffer__` must be `unsafe fn` } fn main() {} diff --git a/tests/ui/invalid_pymethods_buffer.stderr b/tests/ui/invalid_pymethods_buffer.stderr index 899d4a569f4..4ecaaca3a58 100644 --- a/tests/ui/invalid_pymethods_buffer.stderr +++ b/tests/ui/invalid_pymethods_buffer.stderr @@ -5,7 +5,9 @@ error: `__getbuffer__` must be `unsafe fn` | ^^^^^^^^^^^^^^^^^^^^^^^^ error: `__releasebuffer__` must be `unsafe fn` - --> tests/ui/invalid_pymethods_buffer.rs:15:8 + --> tests/ui/invalid_pymethods_buffer.rs:16:8 | -15 | fn releasebuffer_must_be_unsafe(&self, _view: *mut pyo3::ffi::Py_buffer) {} +16 | fn releasebuffer_must_be_unsafe(&self, _view: *mut pyo3::ffi::Py_buffer) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors diff --git a/tests/ui/invalid_pymethods_duplicates.rs b/tests/ui/invalid_pymethods_duplicates.rs index 04435dcb64a..018e2b80c12 100644 --- a/tests/ui/invalid_pymethods_duplicates.rs +++ b/tests/ui/invalid_pymethods_duplicates.rs @@ -7,6 +7,8 @@ use pyo3::prelude::*; struct TwoNew {} #[pymethods] +//~^ ERROR: conflicting implementations of trait `pyo3::impl_::pyclass::doc::PyClassNewTextSignature` for type `TwoNew` +//~| ERROR: duplicate definitions with name `__pymethod___new____` impl TwoNew { #[new] fn new_1() -> Self { @@ -23,6 +25,7 @@ impl TwoNew { struct DuplicateMethod {} #[pymethods] +//~^ ERROR: duplicate definitions with name `__pymethod_func__` impl DuplicateMethod { #[pyo3(name = "func")] fn func_a(&self) {} diff --git a/tests/ui/invalid_pymethods_duplicates.stderr b/tests/ui/invalid_pymethods_duplicates.stderr index fdc6f780d91..6856ee97863 100644 --- a/tests/ui/invalid_pymethods_duplicates.stderr +++ b/tests/ui/invalid_pymethods_duplicates.stderr @@ -21,12 +21,17 @@ error[E0592]: duplicate definitions with name `__pymethod___new____` = note: this error originates in the attribute macro `pymethods` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0592]: duplicate definitions with name `__pymethod_func__` - --> tests/ui/invalid_pymethods_duplicates.rs:25:1 + --> tests/ui/invalid_pymethods_duplicates.rs:27:1 | -25 | #[pymethods] +27 | #[pymethods] | ^^^^^^^^^^^^ | | | duplicate definitions for `__pymethod_func__` | other definition for `__pymethod_func__` | = note: this error originates in the attribute macro `pymethods` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0119, E0592. +For more information about an error, try `rustc --explain E0119`. diff --git a/tests/ui/invalid_pymethods_warn.rs b/tests/ui/invalid_pymethods_warn.rs index 6c6f39f5dc0..0a17a6e9a92 100644 --- a/tests/ui/invalid_pymethods_warn.rs +++ b/tests/ui/invalid_pymethods_warn.rs @@ -6,6 +6,7 @@ struct WarningMethodContainer {} #[pymethods] impl WarningMethodContainer { #[pyo3(warn(message = "warn on __traverse__"))] +//~^ ERROR: __traverse__ cannot be used with #[pyo3(warn)] fn __traverse__(&self) {} } @@ -13,6 +14,7 @@ impl WarningMethodContainer { impl WarningMethodContainer { #[classattr] #[pyo3(warn(message = "warn for class attr"))] +//~^ ERROR: #[classattr] cannot be used with #[pyo3(warn)] fn a_class_attr(_py: pyo3::Python<'_>) -> i64 { 5 } diff --git a/tests/ui/invalid_pymethods_warn.stderr b/tests/ui/invalid_pymethods_warn.stderr index 9e0c8f1d7e9..76cca26f9d7 100644 --- a/tests/ui/invalid_pymethods_warn.stderr +++ b/tests/ui/invalid_pymethods_warn.stderr @@ -5,7 +5,9 @@ error: __traverse__ cannot be used with #[pyo3(warn)] | ^^^^ error: #[classattr] cannot be used with #[pyo3(warn)] - --> tests/ui/invalid_pymethods_warn.rs:15:12 + --> tests/ui/invalid_pymethods_warn.rs:16:12 | -15 | #[pyo3(warn(message = "warn for class attr"))] +16 | #[pyo3(warn(message = "warn for class attr"))] | ^^^^ + +error: aborting due to 2 previous errors diff --git a/tests/ui/invalid_pymodule_args.rs b/tests/ui/invalid_pymodule_args.rs index 4a6e65de150..e7eda436a42 100644 --- a/tests/ui/invalid_pymodule_args.rs +++ b/tests/ui/invalid_pymodule_args.rs @@ -1,16 +1,21 @@ use pyo3::prelude::*; #[pymodule(some_arg)] +//~^ ERROR: expected one of: `name`, `crate`, `module`, `submodule`, `gil_used` fn module(m: &Bound<'_, PyModule>) -> PyResult<()> { Ok(()) } #[pyo3::pymodule(gil_used = false, gil_used = true, name = "foo", name = "bar")] +//~^ ERROR: `name` may only be specified once +//~| ERROR: `gil_used` may only be specified once fn module_fn_multiple_errors(m: &Bound<'_, PyModule>) -> PyResult<()> { Ok(()) } #[pyo3::pymodule(gil_used = false, gil_used = true, name = "foo", name = "bar")] +//~^ ERROR: `name` may only be specified once +//~| ERROR: `gil_used` may only be specified once mod pyo3_module_multiple_errors {} fn main() {} diff --git a/tests/ui/invalid_pymodule_args.stderr b/tests/ui/invalid_pymodule_args.stderr index f741d83a82d..88e0eafbb9e 100644 --- a/tests/ui/invalid_pymodule_args.stderr +++ b/tests/ui/invalid_pymodule_args.stderr @@ -5,25 +5,27 @@ error: expected one of: `name`, `crate`, `module`, `submodule`, `gil_used` | ^^^^^^^^ error: `gil_used` may only be specified once - --> tests/ui/invalid_pymodule_args.rs:8:36 + --> tests/ui/invalid_pymodule_args.rs:9:36 | -8 | #[pyo3::pymodule(gil_used = false, gil_used = true, name = "foo", name = "bar")] +9 | #[pyo3::pymodule(gil_used = false, gil_used = true, name = "foo", name = "bar")] | ^^^^^^^^ error: `name` may only be specified once - --> tests/ui/invalid_pymodule_args.rs:8:67 + --> tests/ui/invalid_pymodule_args.rs:9:67 | -8 | #[pyo3::pymodule(gil_used = false, gil_used = true, name = "foo", name = "bar")] +9 | #[pyo3::pymodule(gil_used = false, gil_used = true, name = "foo", name = "bar")] | ^^^^ error: `gil_used` may only be specified once - --> tests/ui/invalid_pymodule_args.rs:13:36 + --> tests/ui/invalid_pymodule_args.rs:16:36 | -13 | #[pyo3::pymodule(gil_used = false, gil_used = true, name = "foo", name = "bar")] +16 | #[pyo3::pymodule(gil_used = false, gil_used = true, name = "foo", name = "bar")] | ^^^^^^^^ error: `name` may only be specified once - --> tests/ui/invalid_pymodule_args.rs:13:67 + --> tests/ui/invalid_pymodule_args.rs:16:67 | -13 | #[pyo3::pymodule(gil_used = false, gil_used = true, name = "foo", name = "bar")] +16 | #[pyo3::pymodule(gil_used = false, gil_used = true, name = "foo", name = "bar")] | ^^^^ + +error: aborting due to 5 previous errors diff --git a/tests/ui/invalid_pymodule_glob.rs b/tests/ui/invalid_pymodule_glob.rs index 853493b535e..14ebc866ea2 100644 --- a/tests/ui/invalid_pymodule_glob.rs +++ b/tests/ui/invalid_pymodule_glob.rs @@ -11,6 +11,7 @@ fn foo() -> usize { mod module { #[pymodule_export] use super::*; +//~^ ERROR: #[pymodule] cannot import glob statements } fn main() {} diff --git a/tests/ui/invalid_pymodule_glob.stderr b/tests/ui/invalid_pymodule_glob.stderr index 1c033083e0c..7a1db45a211 100644 --- a/tests/ui/invalid_pymodule_glob.stderr +++ b/tests/ui/invalid_pymodule_glob.stderr @@ -3,3 +3,5 @@ error: #[pymodule] cannot import glob statements | 13 | use super::*; | ^ + +error: aborting due to 1 previous error diff --git a/tests/ui/invalid_pymodule_in_root.rs b/tests/ui/invalid_pymodule_in_root.rs index 76ced6c3fb6..046759f98db 100644 --- a/tests/ui/invalid_pymodule_in_root.rs +++ b/tests/ui/invalid_pymodule_in_root.rs @@ -3,5 +3,7 @@ use pyo3::prelude::*; #[pymodule] #[path = "empty.rs"] // to silence error related to missing file mod invalid_pymodule_in_root_module; +//~^ ERROR: file modules in proc macro input are unstable +//~| ERROR: `#[pymodule]` can only be used on inline modules fn main() {} diff --git a/tests/ui/invalid_pymodule_in_root.stderr b/tests/ui/invalid_pymodule_in_root.stderr index 1e763279d81..ae89fda1e5c 100644 --- a/tests/ui/invalid_pymodule_in_root.stderr +++ b/tests/ui/invalid_pymodule_in_root.stderr @@ -11,3 +11,7 @@ error: `#[pymodule]` can only be used on inline modules | 5 | mod invalid_pymodule_in_root_module; | ^^^ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/invalid_pymodule_trait.rs b/tests/ui/invalid_pymodule_trait.rs index 6649a3547a0..c320f919b8f 100644 --- a/tests/ui/invalid_pymodule_trait.rs +++ b/tests/ui/invalid_pymodule_trait.rs @@ -3,6 +3,8 @@ use pyo3::prelude::*; #[pymodule] mod module { #[pymodule_export] +//~^ ERROR: cannot find attribute `pymodule_export` in this scope +//~| ERROR: `#[pymodule_export]` may only be used on `use` or `const` statements trait Foo {} } diff --git a/tests/ui/invalid_pymodule_trait.stderr b/tests/ui/invalid_pymodule_trait.stderr index f8cfc1b1bdf..f1204f18d1b 100644 --- a/tests/ui/invalid_pymodule_trait.stderr +++ b/tests/ui/invalid_pymodule_trait.stderr @@ -9,3 +9,5 @@ error: cannot find attribute `pymodule_export` in this scope | 5 | #[pymodule_export] | ^^^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors diff --git a/tests/ui/invalid_pymodule_two_pymodule_init.rs b/tests/ui/invalid_pymodule_two_pymodule_init.rs index ed72cbb7237..e0df90373d1 100644 --- a/tests/ui/invalid_pymodule_two_pymodule_init.rs +++ b/tests/ui/invalid_pymodule_two_pymodule_init.rs @@ -11,6 +11,7 @@ mod module { #[pymodule_init] fn init2(_m: &Bound<'_, PyModule>) -> PyResult<()> { +//~^ ERROR: only one `#[pymodule_init]` may be specified Ok(()) } } diff --git a/tests/ui/invalid_pymodule_two_pymodule_init.stderr b/tests/ui/invalid_pymodule_two_pymodule_init.stderr index 8fbd12f2e45..8de162f8a06 100644 --- a/tests/ui/invalid_pymodule_two_pymodule_init.stderr +++ b/tests/ui/invalid_pymodule_two_pymodule_init.stderr @@ -3,3 +3,5 @@ error: only one `#[pymodule_init]` may be specified | 13 | fn init2(_m: &Bound<'_, PyModule>) -> PyResult<()> { | ^^ + +error: aborting due to 1 previous error diff --git a/tests/ui/invalid_result_conversion.rs b/tests/ui/invalid_result_conversion.rs index 692ce71f6dd..0b5f931f753 100644 --- a/tests/ui/invalid_result_conversion.rs +++ b/tests/ui/invalid_result_conversion.rs @@ -20,6 +20,7 @@ impl fmt::Display for MyError { #[pyfunction] fn should_not_work() -> Result<(), MyError> { +//~^ ERROR: the trait bound `PyErr: From` is not satisfied Err(MyError { descr: "something went wrong", }) diff --git a/tests/ui/invalid_result_conversion.stderr b/tests/ui/invalid_result_conversion.stderr index 4adc47dee38..3cb6322b53e 100644 --- a/tests/ui/invalid_result_conversion.stderr +++ b/tests/ui/invalid_result_conversion.stderr @@ -8,10 +8,14 @@ error[E0277]: the trait bound `PyErr: From` is not satisfied `PyErr` implements `From` `PyErr` implements `From>` `PyErr` implements `From>` + `PyErr` implements `From` `PyErr` implements `From>` `PyErr` implements `From>` `PyErr` implements `From` `PyErr` implements `From` - `PyErr` implements `From>` and $N others = note: required for `MyError` to implement `Into` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/missing_intopy.rs b/tests/ui/missing_intopy.rs index 36de7bdee78..0c1a0b58448 100644 --- a/tests/ui/missing_intopy.rs +++ b/tests/ui/missing_intopy.rs @@ -2,6 +2,8 @@ struct Blah; #[pyo3::pyfunction] fn blah() -> Blah { +//~^ ERROR: `Blah` cannot be converted to a Python object +//~| ERROR: no method named `map_err` found for struct `Blah` in the current scope Blah } diff --git a/tests/ui/missing_intopy.stderr b/tests/ui/missing_intopy.stderr index 327c8bdf6f7..b765e4df04e 100644 --- a/tests/ui/missing_intopy.stderr +++ b/tests/ui/missing_intopy.stderr @@ -1,27 +1,27 @@ error[E0277]: `Blah` cannot be converted to a Python object - --> tests/ui/missing_intopy.rs:4:14 - | -4 | fn blah() -> Blah { - | ^^^^ unsatisfied trait bound - | + --> tests/ui/missing_intopy.rs:4:14 + | + 4 | fn blah() -> Blah { + | ^^^^ unsatisfied trait bound + | help: the trait `IntoPyObject<'_>` is not implemented for `Blah` - --> tests/ui/missing_intopy.rs:1:1 - | -1 | struct Blah; - | ^^^^^^^^^^^ - = note: `IntoPyObject` is automatically implemented by the `#[pyclass]` macro - = note: if you do not wish to have a corresponding Python type, implement it manually - = note: if you do not own `Blah` you can perform a manual conversion to one of the types in `pyo3::types::*` - = help: the following other types implement trait `IntoPyObject<'py>`: - &&'a T - &&OsStr - &&Path - &&str - &'a (T0, T1) - &'a (T0, T1, T2) - &'a (T0, T1, T2, T3) - &'a (T0, T1, T2, T3, T4) - and $N others + --> tests/ui/missing_intopy.rs:1:1 + | + 1 | struct Blah; + | ^^^^^^^^^^^ + = note: `IntoPyObject` is automatically implemented by the `#[pyclass]` macro + = note: if you do not wish to have a corresponding Python type, implement it manually + = note: if you do not own `Blah` you can perform a manual conversion to one of the types in `pyo3::types::*` + = help: the following other types implement trait `IntoPyObject<'py>`: + &&'a T + &&OsStr + &&Path + &&str + &'a (T0, T1) + &'a (T0, T1, T2) + &'a (T0, T1, T2, T3) + &'a (T0, T1, T2, T3, T4) + and $N others note: required by a bound in `pyo3::impl_::wrap::UnknownReturnType::::wrap` --> src/impl_/wrap.rs | @@ -39,3 +39,8 @@ error[E0599]: no method named `map_err` found for struct `Blah` in the current s ... 4 | fn blah() -> Blah { | ^^^^ method not found in `Blah` + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0277, E0599. +For more information about an error, try `rustc --explain E0277`. diff --git a/tests/ui/not_send.rs b/tests/ui/not_send.rs index 926343538aa..6ff785d4635 100644 --- a/tests/ui/not_send.rs +++ b/tests/ui/not_send.rs @@ -1,7 +1,9 @@ +//@normalize-stderr-test: ".*/src/rust/(.*)" -> "../src/$1" use pyo3::prelude::*; fn test_not_send_detach(py: Python<'_>) { - py.detach(|| { drop(py); }); + py.detach(|| drop(py)); + //~^ ERROR: `*mut pyo3::Python<'static>` cannot be shared between threads safely } fn main() { diff --git a/tests/ui/not_send.stderr b/tests/ui/not_send.stderr index 0cb4039b186..d43252da722 100644 --- a/tests/ui/not_send.stderr +++ b/tests/ui/not_send.stderr @@ -1,27 +1,27 @@ error[E0277]: `*mut pyo3::Python<'static>` cannot be shared between threads safely - --> tests/ui/not_send.rs:4:15 - | -4 | py.detach(|| { drop(py); }); - | ------ ^^^^^^^^^^^^^^^^ `*mut pyo3::Python<'static>` cannot be shared between threads safely - | | - | required by a bound introduced by this call - | - = help: within `pyo3::Python<'_>`, the trait `Sync` is not implemented for `*mut pyo3::Python<'static>` + --> tests/ui/not_send.rs:5:15 + | + 5 | py.detach(|| drop(py)); + | ------ ^^^^^^^^^^^ `*mut pyo3::Python<'static>` cannot be shared between threads safely + | | + | required by a bound introduced by this call + | + = help: within `pyo3::Python<'_>`, the trait `Sync` is not implemented for `*mut pyo3::Python<'static>` note: required because it appears within the type `PhantomData<*mut pyo3::Python<'static>>` - --> $RUST/core/src/marker.rs - | - | pub struct PhantomData; - | ^^^^^^^^^^^ +../src/library/core/src/marker.rs:814:12 + | +814 | pub struct PhantomData; + | ^^^^^^^^^^^ note: required because it appears within the type `pyo3::marker::NotSend` --> src/marker.rs | | struct NotSend(PhantomData<*mut Python<'static>>); | ^^^^^^^ note: required because it appears within the type `PhantomData` - --> $RUST/core/src/marker.rs - | - | pub struct PhantomData; - | ^^^^^^^^^^^ +../src/library/core/src/marker.rs:814:12 + | +814 | pub struct PhantomData; + | ^^^^^^^^^^^ note: required because it appears within the type `pyo3::Python<'_>` --> src/marker.rs | @@ -29,11 +29,11 @@ note: required because it appears within the type `pyo3::Python<'_>` | ^^^^^^ = note: required for `&pyo3::Python<'_>` to implement `Send` note: required because it's used within this closure - --> tests/ui/not_send.rs:4:15 - | -4 | py.detach(|| { drop(py); }); - | ^^ - = note: required for `{closure@$DIR/tests/ui/not_send.rs:4:15: 4:17}` to implement `Ungil` + --> tests/ui/not_send.rs:5:15 + | + 5 | py.detach(|| drop(py)); + | ^^ + = note: required for `{closure@tests/ui/not_send.rs:5:15: 5:17}` to implement `Ungil` note: required by a bound in `pyo3::Python::<'py>::detach` --> src/marker.rs | @@ -42,3 +42,7 @@ note: required by a bound in `pyo3::Python::<'py>::detach` | where | F: Ungil + FnOnce() -> T, | ^^^^^ required by this bound in `Python::<'py>::detach` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/not_send2.rs b/tests/ui/not_send2.rs index 78c73d5e9c8..58382a7c207 100644 --- a/tests/ui/not_send2.rs +++ b/tests/ui/not_send2.rs @@ -1,3 +1,4 @@ +//@normalize-stderr-test: ".*/src/rust/(.*)" -> "../src/$1" use pyo3::prelude::*; use pyo3::types::PyString; @@ -6,6 +7,7 @@ fn main() { let string = PyString::new(py, "foo"); py.detach(|| { + //~^ ERROR: `*mut pyo3::Python<'static>` cannot be shared between threads safely println!("{:?}", string); }); }); diff --git a/tests/ui/not_send2.stderr b/tests/ui/not_send2.stderr index 3d76b5ebc11..7124e0c4852 100644 --- a/tests/ui/not_send2.stderr +++ b/tests/ui/not_send2.stderr @@ -1,52 +1,57 @@ error[E0277]: `*mut pyo3::Python<'static>` cannot be shared between threads safely - --> tests/ui/not_send2.rs:8:19 - | - 8 | py.detach(|| { - | ____________------_^ - | | | - | | required by a bound introduced by this call - 9 | | println!("{:?}", string); -10 | | }); - | |_________^ `*mut pyo3::Python<'static>` cannot be shared between threads safely - | - = help: within `pyo3::Bound<'_, PyString>`, the trait `Sync` is not implemented for `*mut pyo3::Python<'static>` + --> tests/ui/not_send2.rs:9:19 + | + 9 | py.detach(|| { + | ____________------_^ + | | | + | | required by a bound introduced by this call + 10 | | + 11 | | println!("{:?}", string); + 12 | | }); + | |_________^ `*mut pyo3::Python<'static>` cannot be shared between threads safely + | + = help: within `pyo3::Bound<'_, PyString>`, the trait `Sync` is not implemented for `*mut pyo3::Python<'static>` note: required because it appears within the type `PhantomData<*mut pyo3::Python<'static>>` - --> $RUST/core/src/marker.rs - | - | pub struct PhantomData; - | ^^^^^^^^^^^ +../src/library/core/src/marker.rs:814:12 + | +814 | pub struct PhantomData; + | ^^^^^^^^^^^ note: required because it appears within the type `pyo3::marker::NotSend` - --> src/marker.rs - | - | struct NotSend(PhantomData<*mut Python<'static>>); - | ^^^^^^^ + --> src/marker.rs + | + | struct NotSend(PhantomData<*mut Python<'static>>); + | ^^^^^^^ note: required because it appears within the type `PhantomData` - --> $RUST/core/src/marker.rs - | - | pub struct PhantomData; - | ^^^^^^^^^^^ +../src/library/core/src/marker.rs:814:12 + | +814 | pub struct PhantomData; + | ^^^^^^^^^^^ note: required because it appears within the type `pyo3::Python<'_>` - --> src/marker.rs - | - | pub struct Python<'py>(PhantomData<&'py AttachGuard>, PhantomData); - | ^^^^^^ + --> src/marker.rs + | + | pub struct Python<'py>(PhantomData<&'py AttachGuard>, PhantomData); + | ^^^^^^ note: required because it appears within the type `pyo3::Bound<'_, PyString>` - --> src/instance.rs - | - | pub struct Bound<'py, T>(Python<'py>, ManuallyDrop>); - | ^^^^^ - = note: required for `&pyo3::Bound<'_, PyString>` to implement `Send` + --> src/instance.rs + | + | pub struct Bound<'py, T>(Python<'py>, ManuallyDrop>); + | ^^^^^ + = note: required for `&pyo3::Bound<'_, PyString>` to implement `Send` note: required because it's used within this closure - --> tests/ui/not_send2.rs:8:19 - | - 8 | py.detach(|| { - | ^^ - = note: required for `{closure@$DIR/tests/ui/not_send2.rs:8:19: 8:21}` to implement `Ungil` + --> tests/ui/not_send2.rs:9:19 + | + 9 | py.detach(|| { + | ^^ + = note: required for `{closure@tests/ui/not_send2.rs:9:19: 9:21}` to implement `Ungil` note: required by a bound in `pyo3::Python::<'py>::detach` - --> src/marker.rs - | - | pub fn detach(self, f: F) -> T - | ------ required by a bound in this associated function - | where - | F: Ungil + FnOnce() -> T, - | ^^^^^ required by this bound in `Python::<'py>::detach` + --> src/marker.rs + | + | pub fn detach(self, f: F) -> T + | ------ required by a bound in this associated function + | where + | F: Ungil + FnOnce() -> T, + | ^^^^^ required by this bound in `Python::<'py>::detach` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/pyclass_generic_enum.rs b/tests/ui/pyclass_generic_enum.rs index 94fd779b2d4..110c9a0e37b 100644 --- a/tests/ui/pyclass_generic_enum.rs +++ b/tests/ui/pyclass_generic_enum.rs @@ -1,12 +1,14 @@ use pyo3::prelude::*; #[pyclass(generic)] +//~^ ERROR: enums do not support #[pyclass(generic)] enum NotGenericForEnum { A, B, } #[pyclass(generic)] +//~^ ERROR: enums do not support #[pyclass(generic)] enum NoGenericForComplexEnum { A { x: f64 }, B { y: f64, z: f64 }, diff --git a/tests/ui/pyclass_generic_enum.stderr b/tests/ui/pyclass_generic_enum.stderr index cfc1e178af3..9ae4d0ad285 100644 --- a/tests/ui/pyclass_generic_enum.stderr +++ b/tests/ui/pyclass_generic_enum.stderr @@ -5,7 +5,9 @@ error: enums do not support #[pyclass(generic)] | ^^^^^^^ error: enums do not support #[pyclass(generic)] - --> tests/ui/pyclass_generic_enum.rs:9:11 - | -9 | #[pyclass(generic)] - | ^^^^^^^ + --> tests/ui/pyclass_generic_enum.rs:10:11 + | +10 | #[pyclass(generic)] + | ^^^^^^^ + +error: aborting due to 2 previous errors diff --git a/tests/ui/pyclass_probe.rs b/tests/ui/pyclass_probe.rs index 7a18ddc1aef..7919cb82de9 100644 --- a/tests/ui/pyclass_probe.rs +++ b/tests/ui/pyclass_probe.rs @@ -1,52 +1,53 @@ -#![deny(unused_imports)] -use pyo3::prelude::*; - -#[pymodule] -mod probe_no_fields { - use pyo3::prelude::*; - #[pyclass] - pub struct Probe {} - - #[pymethods] - impl Probe { - #[new] - fn new() -> Self { - Self {} - } - } -} - -#[pymodule] -mod probe_with_fields { - use pyo3::prelude::*; - #[pyclass(get_all)] - pub struct Probe { - field: u8, - } - - #[pymethods] - impl Probe { - #[new] - fn new() -> Self { - Self { field: 0 } - } - } -} - -#[pyclass] -struct Check5029(); - -macro_rules! impl_methods { - ($name:ident) => { - #[pymethods] - impl Check5029 { - fn $name(&self, _value: Option<&str>) -> PyResult<()> { - Ok(()) - } - } - }; -} - -impl_methods!(some_method); - -fn main() {} +//@check-pass +#![deny(unused_imports)] +use pyo3::prelude::*; + +#[pymodule] +mod probe_no_fields { + use pyo3::prelude::*; + #[pyclass] + pub struct Probe {} + + #[pymethods] + impl Probe { + #[new] + fn new() -> Self { + Self {} + } + } +} + +#[pymodule] +mod probe_with_fields { + use pyo3::prelude::*; + #[pyclass(get_all)] + pub struct Probe { + field: u8, + } + + #[pymethods] + impl Probe { + #[new] + fn new() -> Self { + Self { field: 0 } + } + } +} + +#[pyclass] +struct Check5029(); + +macro_rules! impl_methods { + ($name:ident) => { + #[pymethods] + impl Check5029 { + fn $name(&self, _value: Option<&str>) -> PyResult<()> { + Ok(()) + } + } + }; +} + +impl_methods!(some_method); + +fn main() {} diff --git a/tests/ui/pyclass_send.rs b/tests/ui/pyclass_send.rs index 1a764f621f0..93d39343fa8 100644 --- a/tests/ui/pyclass_send.rs +++ b/tests/ui/pyclass_send.rs @@ -3,13 +3,17 @@ use std::ffi::c_void; #[pyclass] struct NotSyncNotSend(*mut c_void); +//~^ ERROR: `*mut c_void` cannot be sent between threads safely +//~| ERROR: `*mut c_void` cannot be shared between threads safely #[pyclass] struct SendNotSync(*mut c_void); +//~^ ERROR: `*mut c_void` cannot be shared between threads safely unsafe impl Send for SendNotSync {} #[pyclass] struct SyncNotSend(*mut c_void); +//~^ ERROR: `*mut c_void` cannot be sent between threads safely unsafe impl Sync for SyncNotSend {} // None of the `unsendable` forms below should fail to compile diff --git a/tests/ui/pyclass_send.stderr b/tests/ui/pyclass_send.stderr index ff482f8e402..351552f0c99 100644 --- a/tests/ui/pyclass_send.stderr +++ b/tests/ui/pyclass_send.stderr @@ -41,17 +41,17 @@ note: required by a bound in `pyo3::impl_::pyclass::assertions::assert_pyclass_s | ^^^^ required by this bound in `assert_pyclass_send_sync` error[E0277]: `*mut c_void` cannot be shared between threads safely - --> tests/ui/pyclass_send.rs:8:8 - | -8 | struct SendNotSync(*mut c_void); - | ^^^^^^^^^^^ `*mut c_void` cannot be shared between threads safely - | - = help: within `SendNotSync`, the trait `Sync` is not implemented for `*mut c_void` + --> tests/ui/pyclass_send.rs:10:8 + | +10 | struct SendNotSync(*mut c_void); + | ^^^^^^^^^^^ `*mut c_void` cannot be shared between threads safely + | + = help: within `SendNotSync`, the trait `Sync` is not implemented for `*mut c_void` note: required because it appears within the type `SendNotSync` - --> tests/ui/pyclass_send.rs:8:8 - | -8 | struct SendNotSync(*mut c_void); - | ^^^^^^^^^^^ + --> tests/ui/pyclass_send.rs:10:8 + | +10 | struct SendNotSync(*mut c_void); + | ^^^^^^^^^^^ note: required by a bound in `pyo3::impl_::pyclass::assertions::assert_pyclass_send_sync` --> src/impl_/pyclass/assertions.rs | @@ -62,22 +62,26 @@ note: required by a bound in `pyo3::impl_::pyclass::assertions::assert_pyclass_s | ^^^^ required by this bound in `assert_pyclass_send_sync` error[E0277]: `*mut c_void` cannot be sent between threads safely - --> tests/ui/pyclass_send.rs:12:8 + --> tests/ui/pyclass_send.rs:15:8 | -12 | struct SyncNotSend(*mut c_void); +15 | struct SyncNotSend(*mut c_void); | ^^^^^^^^^^^ `*mut c_void` cannot be sent between threads safely | = help: within `SyncNotSend`, the trait `Send` is not implemented for `*mut c_void` note: required because it appears within the type `SyncNotSend` - --> tests/ui/pyclass_send.rs:12:8 + --> tests/ui/pyclass_send.rs:15:8 | -12 | struct SyncNotSend(*mut c_void); +15 | struct SyncNotSend(*mut c_void); | ^^^^^^^^^^^ note: required by a bound in `pyo3::impl_::pyclass::assertions::assert_pyclass_send_sync` - --> src/impl_/pyclass/assertions.rs - | - | pub const fn assert_pyclass_send_sync() - | ------------------------ required by a bound in this function - | where - | T: Send + Sync, - | ^^^^ required by this bound in `assert_pyclass_send_sync` + --> src/impl_/pyclass/assertions.rs + | + | pub const fn assert_pyclass_send_sync() + | ------------------------ required by a bound in this function + | where + | T: Send + Sync, + | ^^^^ required by this bound in `assert_pyclass_send_sync` + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/pymodule_missing_docs.rs b/tests/ui/pymodule_missing_docs.rs index d8bf2eb4d2f..ee2a58314fc 100644 --- a/tests/ui/pymodule_missing_docs.rs +++ b/tests/ui/pymodule_missing_docs.rs @@ -1,3 +1,4 @@ +//@check-pass #![deny(missing_docs)] //! Some crate docs diff --git a/tests/ui/reject_generics.rs b/tests/ui/reject_generics.rs index 55142ee0e37..7c9aa5de925 100644 --- a/tests/ui/reject_generics.rs +++ b/tests/ui/reject_generics.rs @@ -2,11 +2,13 @@ use pyo3::prelude::*; #[pyclass] struct ClassWithGenerics { + //~^ ERROR: #[pyclass] cannot have generic parameters. For an explanation, see a: A, } #[pyclass] struct ClassWithLifetimes<'a> { + //~^ ERROR: #[pyclass] cannot have lifetime parameters. For an explanation, see a: &'a str, } diff --git a/tests/ui/reject_generics.stderr b/tests/ui/reject_generics.stderr index 8a50eab2a04..cfa93521d4a 100644 --- a/tests/ui/reject_generics.stderr +++ b/tests/ui/reject_generics.stderr @@ -5,7 +5,9 @@ error: #[pyclass] cannot have generic parameters. For an explanation, see https: | ^ error: #[pyclass] cannot have lifetime parameters. For an explanation, see https://pyo3.rs/v0.28.3/class.html#no-lifetime-parameters - --> tests/ui/reject_generics.rs:9:27 - | -9 | struct ClassWithLifetimes<'a> { - | ^^ + --> tests/ui/reject_generics.rs:10:27 + | +10 | struct ClassWithLifetimes<'a> { + | ^^ + +error: aborting due to 2 previous errors diff --git a/tests/ui/static_ref.rs b/tests/ui/static_ref.rs index e8015db2f64..6465848a589 100644 --- a/tests/ui/static_ref.rs +++ b/tests/ui/static_ref.rs @@ -2,11 +2,14 @@ use pyo3::prelude::*; use pyo3::types::PyList; #[pyfunction] +//~^ ERROR: borrowed data escapes outside of function +//~| ERROR: temporary value dropped while borrowed fn static_ref(list: &'static Bound<'_, PyList>) -> usize { list.len() } #[pyfunction] +//~^ ERROR: borrowed data escapes outside of function fn static_py(list: &Bound<'static, PyList>) -> usize { list.len() } diff --git a/tests/ui/static_ref.stderr b/tests/ui/static_ref.stderr index d32b7508c4b..3886b89c690 100644 --- a/tests/ui/static_ref.stderr +++ b/tests/ui/static_ref.stderr @@ -24,14 +24,19 @@ error[E0716]: temporary value dropped while borrowed = note: this error originates in the attribute macro `pyfunction` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0521]: borrowed data escapes outside of function - --> tests/ui/static_ref.rs:9:1 - | -9 | #[pyfunction] - | ^^^^^^^^^^^^^ - | | - | `py` is a reference that is only valid in the function body - | `py` escapes the function body here - | lifetime `'py` defined here - | argument requires that `'py` must outlive `'static` - | - = note: this error originates in the attribute macro `pyfunction` (in Nightly builds, run with -Z macro-backtrace for more info) + --> tests/ui/static_ref.rs:11:1 + | +11 | #[pyfunction] + | ^^^^^^^^^^^^^ + | | + | `py` is a reference that is only valid in the function body + | `py` escapes the function body here + | lifetime `'py` defined here + | argument requires that `'py` must outlive `'static` + | + = note: this error originates in the attribute macro `pyfunction` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0521, E0716. +For more information about an error, try `rustc --explain E0521`. diff --git a/tests/ui/traverse.rs b/tests/ui/traverse.rs index faa7b5c041d..d65d46e3e71 100644 --- a/tests/ui/traverse.rs +++ b/tests/ui/traverse.rs @@ -8,6 +8,7 @@ struct TraverseTriesToTakePyRef {} #[pymethods] impl TraverseTriesToTakePyRef { fn __traverse__(_slf: PyRef, _visit: PyVisit) -> Result<(), PyTraverseError> { +//~^ ERROR: __traverse__ may not take a receiver other than `&self`. Usually, an implementation of `__traverse__(&self, visit: PyVisit<'_>) -> Result<(), PyTraverseError>` should do nothing but calls to `visit.call`. Most importantly, safe access to the Python interpreter is prohibited inside implementations of `__traverse__`, i.e. `Python::attach` will panic. Ok(()) } } @@ -18,6 +19,7 @@ struct TraverseTriesToTakePyRefMut {} #[pymethods] impl TraverseTriesToTakePyRefMut { fn __traverse__(_slf: PyRefMut, _visit: PyVisit) -> Result<(), PyTraverseError> { +//~^ ERROR: __traverse__ may not take a receiver other than `&self`. Usually, an implementation of `__traverse__(&self, visit: PyVisit<'_>) -> Result<(), PyTraverseError>` should do nothing but calls to `visit.call`. Most importantly, safe access to the Python interpreter is prohibited inside implementations of `__traverse__`, i.e. `Python::attach` will panic. Ok(()) } } @@ -28,6 +30,7 @@ struct TraverseTriesToTakeBound {} #[pymethods] impl TraverseTriesToTakeBound { fn __traverse__(_slf: Bound<'_, Self>, _visit: PyVisit) -> Result<(), PyTraverseError> { +//~^ ERROR: __traverse__ may not take a receiver other than `&self`. Usually, an implementation of `__traverse__(&self, visit: PyVisit<'_>) -> Result<(), PyTraverseError>` should do nothing but calls to `visit.call`. Most importantly, safe access to the Python interpreter is prohibited inside implementations of `__traverse__`, i.e. `Python::attach` will panic. Ok(()) } } @@ -38,6 +41,7 @@ struct TraverseTriesToTakeMutSelf {} #[pymethods] impl TraverseTriesToTakeMutSelf { fn __traverse__(&mut self, _visit: PyVisit) -> Result<(), PyTraverseError> { +//~^ ERROR: __traverse__ may not take a receiver other than `&self`. Usually, an implementation of `__traverse__(&self, visit: PyVisit<'_>) -> Result<(), PyTraverseError>` should do nothing but calls to `visit.call`. Most importantly, safe access to the Python interpreter is prohibited inside implementations of `__traverse__`, i.e. `Python::attach` will panic. Ok(()) } } @@ -58,6 +62,7 @@ struct Class; #[pymethods] impl Class { fn __traverse__(&self, _py: Python<'_>, _visit: PyVisit<'_>) -> Result<(), PyTraverseError> { +//~^ ERROR: __traverse__ may not take `Python`. Usually, an implementation of `__traverse__(&self, visit: PyVisit<'_>) -> Result<(), PyTraverseError>` should do nothing but calls to `visit.call`. Most importantly, safe access to the Python interpreter is prohibited inside implementations of `__traverse__`, i.e. `Python::attach` will panic. Ok(()) } diff --git a/tests/ui/traverse.stderr b/tests/ui/traverse.stderr index 343a67f5641..701ce4bccb4 100644 --- a/tests/ui/traverse.stderr +++ b/tests/ui/traverse.stderr @@ -5,25 +5,27 @@ error: __traverse__ may not take a receiver other than `&self`. Usually, an impl | ^^^^^ error: __traverse__ may not take a receiver other than `&self`. Usually, an implementation of `__traverse__(&self, visit: PyVisit<'_>) -> Result<(), PyTraverseError>` should do nothing but calls to `visit.call`. Most importantly, safe access to the Python interpreter is prohibited inside implementations of `__traverse__`, i.e. `Python::attach` will panic. - --> tests/ui/traverse.rs:20:27 + --> tests/ui/traverse.rs:21:27 | -20 | fn __traverse__(_slf: PyRefMut, _visit: PyVisit) -> Result<(), PyTraverseError> { +21 | fn __traverse__(_slf: PyRefMut, _visit: PyVisit) -> Result<(), PyTraverseError> { | ^^^^^^^^ error: __traverse__ may not take a receiver other than `&self`. Usually, an implementation of `__traverse__(&self, visit: PyVisit<'_>) -> Result<(), PyTraverseError>` should do nothing but calls to `visit.call`. Most importantly, safe access to the Python interpreter is prohibited inside implementations of `__traverse__`, i.e. `Python::attach` will panic. - --> tests/ui/traverse.rs:30:27 + --> tests/ui/traverse.rs:32:27 | -30 | fn __traverse__(_slf: Bound<'_, Self>, _visit: PyVisit) -> Result<(), PyTraverseError> { +32 | fn __traverse__(_slf: Bound<'_, Self>, _visit: PyVisit) -> Result<(), PyTraverseError> { | ^^^^^ error: __traverse__ may not take a receiver other than `&self`. Usually, an implementation of `__traverse__(&self, visit: PyVisit<'_>) -> Result<(), PyTraverseError>` should do nothing but calls to `visit.call`. Most importantly, safe access to the Python interpreter is prohibited inside implementations of `__traverse__`, i.e. `Python::attach` will panic. - --> tests/ui/traverse.rs:40:21 + --> tests/ui/traverse.rs:43:21 | -40 | fn __traverse__(&mut self, _visit: PyVisit) -> Result<(), PyTraverseError> { +43 | fn __traverse__(&mut self, _visit: PyVisit) -> Result<(), PyTraverseError> { | ^ error: __traverse__ may not take `Python`. Usually, an implementation of `__traverse__(&self, visit: PyVisit<'_>) -> Result<(), PyTraverseError>` should do nothing but calls to `visit.call`. Most importantly, safe access to the Python interpreter is prohibited inside implementations of `__traverse__`, i.e. `Python::attach` will panic. - --> tests/ui/traverse.rs:60:33 + --> tests/ui/traverse.rs:64:33 | -60 | fn __traverse__(&self, _py: Python<'_>, _visit: PyVisit<'_>) -> Result<(), PyTraverseError> { +64 | fn __traverse__(&self, _py: Python<'_>, _visit: PyVisit<'_>) -> Result<(), PyTraverseError> { | ^^^^^^^^^^ + +error: aborting due to 5 previous errors diff --git a/tests/ui/wrong_aspyref_lifetimes.rs b/tests/ui/wrong_aspyref_lifetimes.rs index b5f050ebcf9..6438ae4636a 100644 --- a/tests/ui/wrong_aspyref_lifetimes.rs +++ b/tests/ui/wrong_aspyref_lifetimes.rs @@ -5,6 +5,7 @@ fn main() { // Should not be able to get access to Py contents outside of `attach`. let dict: &Bound<'_, PyDict> = Python::attach(|py| dict.bind(py)); +//~^ ERROR: lifetime may not live long enough let _py: Python = dict.py(); // Obtain a Python<'p> without GIL. } diff --git a/tests/ui/wrong_aspyref_lifetimes.stderr b/tests/ui/wrong_aspyref_lifetimes.stderr index 8a9cc553349..1a681292c7c 100644 --- a/tests/ui/wrong_aspyref_lifetimes.stderr +++ b/tests/ui/wrong_aspyref_lifetimes.stderr @@ -6,3 +6,5 @@ error: lifetime may not live long enough | | | | | return type of closure is &'2 pyo3::Bound<'_, PyDict> | has type `Python<'1>` + +error: aborting due to 1 previous error