From dd3b313b56f34e21cd79d610cdf4e501a4bb8c4e Mon Sep 17 00:00:00 2001 From: Jieyou Xu Date: Thu, 5 Dec 2024 07:32:05 +0000 Subject: Adjust `alias-uninit-value.rs` - Document and tidy up `alias-uninit-value.rs` - Move `alias-uninit-value.rs` to `tests/ui/codegen/` --- tests/ui/alias-uninit-value.rs | 19 ------------------- tests/ui/codegen/alias-uninit-value.rs | 26 ++++++++++++++++++++++++++ 2 files changed, 26 insertions(+), 19 deletions(-) delete mode 100644 tests/ui/alias-uninit-value.rs create mode 100644 tests/ui/codegen/alias-uninit-value.rs (limited to 'tests') diff --git a/tests/ui/alias-uninit-value.rs b/tests/ui/alias-uninit-value.rs deleted file mode 100644 index 0084a98e627..00000000000 --- a/tests/ui/alias-uninit-value.rs +++ /dev/null @@ -1,19 +0,0 @@ -//@ run-pass - -#![allow(non_camel_case_types)] -#![allow(dead_code)] - - - -// Regression test for issue #374 - - -enum sty { ty_nil, } - -struct RawT {struct_: sty, cname: Option, hash: usize} - -fn mk_raw_ty(st: sty, cname: Option) -> RawT { - return RawT {struct_: st, cname: cname, hash: 0}; -} - -pub fn main() { mk_raw_ty(sty::ty_nil, None::); } diff --git a/tests/ui/codegen/alias-uninit-value.rs b/tests/ui/codegen/alias-uninit-value.rs new file mode 100644 index 00000000000..a8aa94caaf2 --- /dev/null +++ b/tests/ui/codegen/alias-uninit-value.rs @@ -0,0 +1,26 @@ +//! Regression test for issue #374, where previously rustc performed conditional jumps or moves that +//! incorrectly depended on uninitialized values. +//! +//! Issue: . + +//@ run-pass + +#![allow(dead_code)] + +enum TyS { + Nil, +} + +struct RawT { + struct_: TyS, + cname: Option, + hash: usize, +} + +fn mk_raw_ty(st: TyS, cname: Option) -> RawT { + return RawT { struct_: st, cname: cname, hash: 0 }; +} + +pub fn main() { + mk_raw_ty(TyS::Nil, None::); +} -- cgit 1.4.1-3-g733a5 From b5c7a552502e6d27f96a1b7edf1b86d703dbad8a Mon Sep 17 00:00:00 2001 From: Jieyou Xu Date: Thu, 5 Dec 2024 08:09:02 +0000 Subject: Adjust `allow-non-lint-warnings.rs` - Document `allow-non-lint-warnings.rs` - Move `allow-non-lint-warnings.rs` under `tests/ui/diagnostic-flags/` - Improve the test to use two *differential* revisions: 1. One revision checks that without `-A warnings` the code sample actually emits a warning. 2. The other revision checks that `-A warnings` suppresses the warning. This makes sure that if the code sample no longer warns, the test doesn't silently pass but fail to check its intended purpose. --- tests/ui/allow-non-lint-warnings.rs | 8 ------- .../ui/diagnostic-flags/allow-non-lint-warnings.rs | 27 ++++++++++++++++++++++ .../allow-non-lint-warnings.without_flag.stderr | 8 +++++++ 3 files changed, 35 insertions(+), 8 deletions(-) delete mode 100644 tests/ui/allow-non-lint-warnings.rs create mode 100644 tests/ui/diagnostic-flags/allow-non-lint-warnings.rs create mode 100644 tests/ui/diagnostic-flags/allow-non-lint-warnings.without_flag.stderr (limited to 'tests') diff --git a/tests/ui/allow-non-lint-warnings.rs b/tests/ui/allow-non-lint-warnings.rs deleted file mode 100644 index f8f5a78ebff..00000000000 --- a/tests/ui/allow-non-lint-warnings.rs +++ /dev/null @@ -1,8 +0,0 @@ -//@ compile-flags: -Awarnings -//@ check-pass - -#[derive()] -#[derive(Copy, Clone)] -pub struct Foo; - -pub fn main() {} diff --git a/tests/ui/diagnostic-flags/allow-non-lint-warnings.rs b/tests/ui/diagnostic-flags/allow-non-lint-warnings.rs new file mode 100644 index 00000000000..40b9e6536f5 --- /dev/null +++ b/tests/ui/diagnostic-flags/allow-non-lint-warnings.rs @@ -0,0 +1,27 @@ +// ignore-tidy-linelength +//! Check that `-A warnings` cli flag applies to non-lint warnings as well. +//! +//! This test tries to exercise that by checking that the "relaxing a default bound only does +//! something for `?Sized`; all other traits are not bound by default" non-lint warning (normally +//! warn-by-default) is suppressed if the `-A warnings` cli flag is passed. +//! +//! Take special note that `warnings` is a special pseudo lint group in relationship to non-lint +//! warnings, which is somewhat special. This test does not exercise other `-A ` +//! that check that they are working in the same way, only `warnings` specifically. +//! +//! # Relevant context +//! +//! - Original impl PR: . +//! - RFC 507 "Release channels": +//! . +#![crate_type = "lib"] + +//@ revisions: without_flag with_flag + +//@[with_flag] compile-flags: -Awarnings + +//@ check-pass + +pub trait Trait {} +pub fn f() {} +//[without_flag]~^ WARN relaxing a default bound only does something for `?Sized`; all other traits are not bound by default diff --git a/tests/ui/diagnostic-flags/allow-non-lint-warnings.without_flag.stderr b/tests/ui/diagnostic-flags/allow-non-lint-warnings.without_flag.stderr new file mode 100644 index 00000000000..b037847c70f --- /dev/null +++ b/tests/ui/diagnostic-flags/allow-non-lint-warnings.without_flag.stderr @@ -0,0 +1,8 @@ +warning: relaxing a default bound only does something for `?Sized`; all other traits are not bound by default + --> $DIR/allow-non-lint-warnings.rs:26:13 + | +LL | pub fn f() {} + | ^^^^^^ + +warning: 1 warning emitted + -- cgit 1.4.1-3-g733a5 From d734d22bd8bd7bae6b0e8e3df93c53a9e97dd926 Mon Sep 17 00:00:00 2001 From: Jieyou Xu Date: Thu, 5 Dec 2024 08:21:41 +0000 Subject: Adjust `anonymous-higher-ranked-lifetime.rs` - Document `anonymous-higher-ranked-lifetime.rs` - Move `anonymous-higher-ranked-lifetime.rs` to `tests/ui/higher-ranked` --- tests/ui/anonymous-higher-ranked-lifetime.rs | 30 --- tests/ui/anonymous-higher-ranked-lifetime.stderr | 234 --------------------- .../anonymous-higher-ranked-lifetime.rs | 36 ++++ .../anonymous-higher-ranked-lifetime.stderr | 234 +++++++++++++++++++++ 4 files changed, 270 insertions(+), 264 deletions(-) delete mode 100644 tests/ui/anonymous-higher-ranked-lifetime.rs delete mode 100644 tests/ui/anonymous-higher-ranked-lifetime.stderr create mode 100644 tests/ui/higher-ranked/anonymous-higher-ranked-lifetime.rs create mode 100644 tests/ui/higher-ranked/anonymous-higher-ranked-lifetime.stderr (limited to 'tests') diff --git a/tests/ui/anonymous-higher-ranked-lifetime.rs b/tests/ui/anonymous-higher-ranked-lifetime.rs deleted file mode 100644 index 898fe22fa23..00000000000 --- a/tests/ui/anonymous-higher-ranked-lifetime.rs +++ /dev/null @@ -1,30 +0,0 @@ -fn main() { - f1(|_: (), _: ()| {}); //~ ERROR type mismatch - f2(|_: (), _: ()| {}); //~ ERROR type mismatch - f3(|_: (), _: ()| {}); //~ ERROR type mismatch - f4(|_: (), _: ()| {}); //~ ERROR type mismatch - f5(|_: (), _: ()| {}); //~ ERROR type mismatch - g1(|_: (), _: ()| {}); //~ ERROR type mismatch - g2(|_: (), _: ()| {}); //~ ERROR type mismatch - g3(|_: (), _: ()| {}); //~ ERROR type mismatch - g4(|_: (), _: ()| {}); //~ ERROR type mismatch - h1(|_: (), _: (), _: (), _: ()| {}); //~ ERROR type mismatch - h2(|_: (), _: (), _: (), _: ()| {}); //~ ERROR type mismatch -} - -// Basic -fn f1(_: F) where F: Fn(&(), &()) {} -fn f2(_: F) where F: for<'a> Fn(&'a (), &()) {} -fn f3<'a, F>(_: F) where F: Fn(&'a (), &()) {} -fn f4(_: F) where F: for<'r> Fn(&(), &'r ()) {} -fn f5(_: F) where F: for<'r> Fn(&'r (), &'r ()) {} - -// Nested -fn g1(_: F) where F: Fn(&(), Box) {} -fn g2(_: F) where F: Fn(&(), fn(&())) {} -fn g3(_: F) where F: for<'s> Fn(&'s (), Box) {} -fn g4(_: F) where F: Fn(&(), for<'r> fn(&'r ())) {} - -// Mixed -fn h1(_: F) where F: Fn(&(), Box, &(), fn(&(), &())) {} -fn h2(_: F) where F: for<'t0> Fn(&(), Box, &'t0 (), fn(&(), &())) {} diff --git a/tests/ui/anonymous-higher-ranked-lifetime.stderr b/tests/ui/anonymous-higher-ranked-lifetime.stderr deleted file mode 100644 index c28d856ad55..00000000000 --- a/tests/ui/anonymous-higher-ranked-lifetime.stderr +++ /dev/null @@ -1,234 +0,0 @@ -error[E0631]: type mismatch in closure arguments - --> $DIR/anonymous-higher-ranked-lifetime.rs:2:5 - | -LL | f1(|_: (), _: ()| {}); - | ^^^--------------^^^^ - | | | - | | found signature defined here - | expected due to this - | - = note: expected closure signature `for<'a, 'b> fn(&'a (), &'b ()) -> _` - found closure signature `fn((), ()) -> _` -note: required by a bound in `f1` - --> $DIR/anonymous-higher-ranked-lifetime.rs:16:25 - | -LL | fn f1(_: F) where F: Fn(&(), &()) {} - | ^^^^^^^^^^^^ required by this bound in `f1` -help: consider adjusting the signature so it borrows its arguments - | -LL | f1(|_: &(), _: &()| {}); - | + + - -error[E0631]: type mismatch in closure arguments - --> $DIR/anonymous-higher-ranked-lifetime.rs:3:5 - | -LL | f2(|_: (), _: ()| {}); - | ^^^--------------^^^^ - | | | - | | found signature defined here - | expected due to this - | - = note: expected closure signature `for<'a, 'b> fn(&'a (), &'b ()) -> _` - found closure signature `fn((), ()) -> _` -note: required by a bound in `f2` - --> $DIR/anonymous-higher-ranked-lifetime.rs:17:25 - | -LL | fn f2(_: F) where F: for<'a> Fn(&'a (), &()) {} - | ^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `f2` -help: consider adjusting the signature so it borrows its arguments - | -LL | f2(|_: &(), _: &()| {}); - | + + - -error[E0631]: type mismatch in closure arguments - --> $DIR/anonymous-higher-ranked-lifetime.rs:4:5 - | -LL | f3(|_: (), _: ()| {}); - | ^^^--------------^^^^ - | | | - | | found signature defined here - | expected due to this - | - = note: expected closure signature `for<'a> fn(&(), &'a ()) -> _` - found closure signature `fn((), ()) -> _` -note: required by a bound in `f3` - --> $DIR/anonymous-higher-ranked-lifetime.rs:18:29 - | -LL | fn f3<'a, F>(_: F) where F: Fn(&'a (), &()) {} - | ^^^^^^^^^^^^^^^ required by this bound in `f3` -help: consider adjusting the signature so it borrows its arguments - | -LL | f3(|_: &(), _: &()| {}); - | + + - -error[E0631]: type mismatch in closure arguments - --> $DIR/anonymous-higher-ranked-lifetime.rs:5:5 - | -LL | f4(|_: (), _: ()| {}); - | ^^^--------------^^^^ - | | | - | | found signature defined here - | expected due to this - | - = note: expected closure signature `for<'a, 'r> fn(&'a (), &'r ()) -> _` - found closure signature `fn((), ()) -> _` -note: required by a bound in `f4` - --> $DIR/anonymous-higher-ranked-lifetime.rs:19:25 - | -LL | fn f4(_: F) where F: for<'r> Fn(&(), &'r ()) {} - | ^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `f4` -help: consider adjusting the signature so it borrows its arguments - | -LL | f4(|_: &(), _: &()| {}); - | + + - -error[E0631]: type mismatch in closure arguments - --> $DIR/anonymous-higher-ranked-lifetime.rs:6:5 - | -LL | f5(|_: (), _: ()| {}); - | ^^^--------------^^^^ - | | | - | | found signature defined here - | expected due to this - | - = note: expected closure signature `for<'r> fn(&'r (), &'r ()) -> _` - found closure signature `fn((), ()) -> _` -note: required by a bound in `f5` - --> $DIR/anonymous-higher-ranked-lifetime.rs:20:25 - | -LL | fn f5(_: F) where F: for<'r> Fn(&'r (), &'r ()) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `f5` -help: consider adjusting the signature so it borrows its arguments - | -LL | f5(|_: &(), _: &()| {}); - | + + - -error[E0631]: type mismatch in closure arguments - --> $DIR/anonymous-higher-ranked-lifetime.rs:7:5 - | -LL | g1(|_: (), _: ()| {}); - | ^^^--------------^^^^ - | | | - | | found signature defined here - | expected due to this - | - = note: expected closure signature `for<'a> fn(&'a (), Box<(dyn for<'a> Fn(&'a ()) + 'static)>) -> _` - found closure signature `fn((), ()) -> _` -note: required by a bound in `g1` - --> $DIR/anonymous-higher-ranked-lifetime.rs:23:25 - | -LL | fn g1(_: F) where F: Fn(&(), Box) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `g1` -help: consider adjusting the signature so it borrows its argument - | -LL | g1(|_: &(), _: ()| {}); - | + - -error[E0631]: type mismatch in closure arguments - --> $DIR/anonymous-higher-ranked-lifetime.rs:8:5 - | -LL | g2(|_: (), _: ()| {}); - | ^^^--------------^^^^ - | | | - | | found signature defined here - | expected due to this - | - = note: expected closure signature `for<'a> fn(&'a (), for<'a> fn(&'a ())) -> _` - found closure signature `fn((), ()) -> _` -note: required by a bound in `g2` - --> $DIR/anonymous-higher-ranked-lifetime.rs:24:25 - | -LL | fn g2(_: F) where F: Fn(&(), fn(&())) {} - | ^^^^^^^^^^^^^^^^ required by this bound in `g2` -help: consider adjusting the signature so it borrows its argument - | -LL | g2(|_: &(), _: ()| {}); - | + - -error[E0631]: type mismatch in closure arguments - --> $DIR/anonymous-higher-ranked-lifetime.rs:9:5 - | -LL | g3(|_: (), _: ()| {}); - | ^^^--------------^^^^ - | | | - | | found signature defined here - | expected due to this - | - = note: expected closure signature `for<'s> fn(&'s (), Box<(dyn for<'a> Fn(&'a ()) + 'static)>) -> _` - found closure signature `fn((), ()) -> _` -note: required by a bound in `g3` - --> $DIR/anonymous-higher-ranked-lifetime.rs:25:25 - | -LL | fn g3(_: F) where F: for<'s> Fn(&'s (), Box) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `g3` -help: consider adjusting the signature so it borrows its argument - | -LL | g3(|_: &(), _: ()| {}); - | + - -error[E0631]: type mismatch in closure arguments - --> $DIR/anonymous-higher-ranked-lifetime.rs:10:5 - | -LL | g4(|_: (), _: ()| {}); - | ^^^--------------^^^^ - | | | - | | found signature defined here - | expected due to this - | - = note: expected closure signature `for<'a> fn(&'a (), for<'r> fn(&'r ())) -> _` - found closure signature `fn((), ()) -> _` -note: required by a bound in `g4` - --> $DIR/anonymous-higher-ranked-lifetime.rs:26:25 - | -LL | fn g4(_: F) where F: Fn(&(), for<'r> fn(&'r ())) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `g4` -help: consider adjusting the signature so it borrows its argument - | -LL | g4(|_: &(), _: ()| {}); - | + - -error[E0631]: type mismatch in closure arguments - --> $DIR/anonymous-higher-ranked-lifetime.rs:11:5 - | -LL | h1(|_: (), _: (), _: (), _: ()| {}); - | ^^^----------------------------^^^^ - | | | - | | found signature defined here - | expected due to this - | - = note: expected closure signature `for<'a, 'b> fn(&'a (), Box<(dyn for<'a> Fn(&'a ()) + 'static)>, &'b (), for<'a, 'b> fn(&'a (), &'b ())) -> _` - found closure signature `fn((), (), (), ()) -> _` -note: required by a bound in `h1` - --> $DIR/anonymous-higher-ranked-lifetime.rs:29:25 - | -LL | fn h1(_: F) where F: Fn(&(), Box, &(), fn(&(), &())) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `h1` -help: consider adjusting the signature so it borrows its arguments - | -LL | h1(|_: &(), _: (), _: &(), _: ()| {}); - | + + - -error[E0631]: type mismatch in closure arguments - --> $DIR/anonymous-higher-ranked-lifetime.rs:12:5 - | -LL | h2(|_: (), _: (), _: (), _: ()| {}); - | ^^^----------------------------^^^^ - | | | - | | found signature defined here - | expected due to this - | - = note: expected closure signature `for<'a, 't0> fn(&'a (), Box<(dyn for<'a> Fn(&'a ()) + 'static)>, &'t0 (), for<'a, 'b> fn(&'a (), &'b ())) -> _` - found closure signature `fn((), (), (), ()) -> _` -note: required by a bound in `h2` - --> $DIR/anonymous-higher-ranked-lifetime.rs:30:25 - | -LL | fn h2(_: F) where F: for<'t0> Fn(&(), Box, &'t0 (), fn(&(), &())) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `h2` -help: consider adjusting the signature so it borrows its arguments - | -LL | h2(|_: &(), _: (), _: &(), _: ()| {}); - | + + - -error: aborting due to 11 previous errors - -For more information about this error, try `rustc --explain E0631`. diff --git a/tests/ui/higher-ranked/anonymous-higher-ranked-lifetime.rs b/tests/ui/higher-ranked/anonymous-higher-ranked-lifetime.rs new file mode 100644 index 00000000000..8d8d0e71067 --- /dev/null +++ b/tests/ui/higher-ranked/anonymous-higher-ranked-lifetime.rs @@ -0,0 +1,36 @@ +//! Diagnostics test to check that higher-ranked lifetimes are properly named when being pretty +//! printed in diagnostics. +//! +//! Issue: +//! PR: + +fn main() { + f1(|_: (), _: ()| {}); //~ ERROR type mismatch + f2(|_: (), _: ()| {}); //~ ERROR type mismatch + f3(|_: (), _: ()| {}); //~ ERROR type mismatch + f4(|_: (), _: ()| {}); //~ ERROR type mismatch + f5(|_: (), _: ()| {}); //~ ERROR type mismatch + g1(|_: (), _: ()| {}); //~ ERROR type mismatch + g2(|_: (), _: ()| {}); //~ ERROR type mismatch + g3(|_: (), _: ()| {}); //~ ERROR type mismatch + g4(|_: (), _: ()| {}); //~ ERROR type mismatch + h1(|_: (), _: (), _: (), _: ()| {}); //~ ERROR type mismatch + h2(|_: (), _: (), _: (), _: ()| {}); //~ ERROR type mismatch +} + +// Basic +fn f1(_: F) where F: Fn(&(), &()) {} +fn f2(_: F) where F: for<'a> Fn(&'a (), &()) {} +fn f3<'a, F>(_: F) where F: Fn(&'a (), &()) {} +fn f4(_: F) where F: for<'r> Fn(&(), &'r ()) {} +fn f5(_: F) where F: for<'r> Fn(&'r (), &'r ()) {} + +// Nested +fn g1(_: F) where F: Fn(&(), Box) {} +fn g2(_: F) where F: Fn(&(), fn(&())) {} +fn g3(_: F) where F: for<'s> Fn(&'s (), Box) {} +fn g4(_: F) where F: Fn(&(), for<'r> fn(&'r ())) {} + +// Mixed +fn h1(_: F) where F: Fn(&(), Box, &(), fn(&(), &())) {} +fn h2(_: F) where F: for<'t0> Fn(&(), Box, &'t0 (), fn(&(), &())) {} diff --git a/tests/ui/higher-ranked/anonymous-higher-ranked-lifetime.stderr b/tests/ui/higher-ranked/anonymous-higher-ranked-lifetime.stderr new file mode 100644 index 00000000000..7e0cdba6ff2 --- /dev/null +++ b/tests/ui/higher-ranked/anonymous-higher-ranked-lifetime.stderr @@ -0,0 +1,234 @@ +error[E0631]: type mismatch in closure arguments + --> $DIR/anonymous-higher-ranked-lifetime.rs:8:5 + | +LL | f1(|_: (), _: ()| {}); + | ^^^--------------^^^^ + | | | + | | found signature defined here + | expected due to this + | + = note: expected closure signature `for<'a, 'b> fn(&'a (), &'b ()) -> _` + found closure signature `fn((), ()) -> _` +note: required by a bound in `f1` + --> $DIR/anonymous-higher-ranked-lifetime.rs:22:25 + | +LL | fn f1(_: F) where F: Fn(&(), &()) {} + | ^^^^^^^^^^^^ required by this bound in `f1` +help: consider adjusting the signature so it borrows its arguments + | +LL | f1(|_: &(), _: &()| {}); + | + + + +error[E0631]: type mismatch in closure arguments + --> $DIR/anonymous-higher-ranked-lifetime.rs:9:5 + | +LL | f2(|_: (), _: ()| {}); + | ^^^--------------^^^^ + | | | + | | found signature defined here + | expected due to this + | + = note: expected closure signature `for<'a, 'b> fn(&'a (), &'b ()) -> _` + found closure signature `fn((), ()) -> _` +note: required by a bound in `f2` + --> $DIR/anonymous-higher-ranked-lifetime.rs:23:25 + | +LL | fn f2(_: F) where F: for<'a> Fn(&'a (), &()) {} + | ^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `f2` +help: consider adjusting the signature so it borrows its arguments + | +LL | f2(|_: &(), _: &()| {}); + | + + + +error[E0631]: type mismatch in closure arguments + --> $DIR/anonymous-higher-ranked-lifetime.rs:10:5 + | +LL | f3(|_: (), _: ()| {}); + | ^^^--------------^^^^ + | | | + | | found signature defined here + | expected due to this + | + = note: expected closure signature `for<'a> fn(&(), &'a ()) -> _` + found closure signature `fn((), ()) -> _` +note: required by a bound in `f3` + --> $DIR/anonymous-higher-ranked-lifetime.rs:24:29 + | +LL | fn f3<'a, F>(_: F) where F: Fn(&'a (), &()) {} + | ^^^^^^^^^^^^^^^ required by this bound in `f3` +help: consider adjusting the signature so it borrows its arguments + | +LL | f3(|_: &(), _: &()| {}); + | + + + +error[E0631]: type mismatch in closure arguments + --> $DIR/anonymous-higher-ranked-lifetime.rs:11:5 + | +LL | f4(|_: (), _: ()| {}); + | ^^^--------------^^^^ + | | | + | | found signature defined here + | expected due to this + | + = note: expected closure signature `for<'a, 'r> fn(&'a (), &'r ()) -> _` + found closure signature `fn((), ()) -> _` +note: required by a bound in `f4` + --> $DIR/anonymous-higher-ranked-lifetime.rs:25:25 + | +LL | fn f4(_: F) where F: for<'r> Fn(&(), &'r ()) {} + | ^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `f4` +help: consider adjusting the signature so it borrows its arguments + | +LL | f4(|_: &(), _: &()| {}); + | + + + +error[E0631]: type mismatch in closure arguments + --> $DIR/anonymous-higher-ranked-lifetime.rs:12:5 + | +LL | f5(|_: (), _: ()| {}); + | ^^^--------------^^^^ + | | | + | | found signature defined here + | expected due to this + | + = note: expected closure signature `for<'r> fn(&'r (), &'r ()) -> _` + found closure signature `fn((), ()) -> _` +note: required by a bound in `f5` + --> $DIR/anonymous-higher-ranked-lifetime.rs:26:25 + | +LL | fn f5(_: F) where F: for<'r> Fn(&'r (), &'r ()) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `f5` +help: consider adjusting the signature so it borrows its arguments + | +LL | f5(|_: &(), _: &()| {}); + | + + + +error[E0631]: type mismatch in closure arguments + --> $DIR/anonymous-higher-ranked-lifetime.rs:13:5 + | +LL | g1(|_: (), _: ()| {}); + | ^^^--------------^^^^ + | | | + | | found signature defined here + | expected due to this + | + = note: expected closure signature `for<'a> fn(&'a (), Box<(dyn for<'a> Fn(&'a ()) + 'static)>) -> _` + found closure signature `fn((), ()) -> _` +note: required by a bound in `g1` + --> $DIR/anonymous-higher-ranked-lifetime.rs:29:25 + | +LL | fn g1(_: F) where F: Fn(&(), Box) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `g1` +help: consider adjusting the signature so it borrows its argument + | +LL | g1(|_: &(), _: ()| {}); + | + + +error[E0631]: type mismatch in closure arguments + --> $DIR/anonymous-higher-ranked-lifetime.rs:14:5 + | +LL | g2(|_: (), _: ()| {}); + | ^^^--------------^^^^ + | | | + | | found signature defined here + | expected due to this + | + = note: expected closure signature `for<'a> fn(&'a (), for<'a> fn(&'a ())) -> _` + found closure signature `fn((), ()) -> _` +note: required by a bound in `g2` + --> $DIR/anonymous-higher-ranked-lifetime.rs:30:25 + | +LL | fn g2(_: F) where F: Fn(&(), fn(&())) {} + | ^^^^^^^^^^^^^^^^ required by this bound in `g2` +help: consider adjusting the signature so it borrows its argument + | +LL | g2(|_: &(), _: ()| {}); + | + + +error[E0631]: type mismatch in closure arguments + --> $DIR/anonymous-higher-ranked-lifetime.rs:15:5 + | +LL | g3(|_: (), _: ()| {}); + | ^^^--------------^^^^ + | | | + | | found signature defined here + | expected due to this + | + = note: expected closure signature `for<'s> fn(&'s (), Box<(dyn for<'a> Fn(&'a ()) + 'static)>) -> _` + found closure signature `fn((), ()) -> _` +note: required by a bound in `g3` + --> $DIR/anonymous-higher-ranked-lifetime.rs:31:25 + | +LL | fn g3(_: F) where F: for<'s> Fn(&'s (), Box) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `g3` +help: consider adjusting the signature so it borrows its argument + | +LL | g3(|_: &(), _: ()| {}); + | + + +error[E0631]: type mismatch in closure arguments + --> $DIR/anonymous-higher-ranked-lifetime.rs:16:5 + | +LL | g4(|_: (), _: ()| {}); + | ^^^--------------^^^^ + | | | + | | found signature defined here + | expected due to this + | + = note: expected closure signature `for<'a> fn(&'a (), for<'r> fn(&'r ())) -> _` + found closure signature `fn((), ()) -> _` +note: required by a bound in `g4` + --> $DIR/anonymous-higher-ranked-lifetime.rs:32:25 + | +LL | fn g4(_: F) where F: Fn(&(), for<'r> fn(&'r ())) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `g4` +help: consider adjusting the signature so it borrows its argument + | +LL | g4(|_: &(), _: ()| {}); + | + + +error[E0631]: type mismatch in closure arguments + --> $DIR/anonymous-higher-ranked-lifetime.rs:17:5 + | +LL | h1(|_: (), _: (), _: (), _: ()| {}); + | ^^^----------------------------^^^^ + | | | + | | found signature defined here + | expected due to this + | + = note: expected closure signature `for<'a, 'b> fn(&'a (), Box<(dyn for<'a> Fn(&'a ()) + 'static)>, &'b (), for<'a, 'b> fn(&'a (), &'b ())) -> _` + found closure signature `fn((), (), (), ()) -> _` +note: required by a bound in `h1` + --> $DIR/anonymous-higher-ranked-lifetime.rs:35:25 + | +LL | fn h1(_: F) where F: Fn(&(), Box, &(), fn(&(), &())) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `h1` +help: consider adjusting the signature so it borrows its arguments + | +LL | h1(|_: &(), _: (), _: &(), _: ()| {}); + | + + + +error[E0631]: type mismatch in closure arguments + --> $DIR/anonymous-higher-ranked-lifetime.rs:18:5 + | +LL | h2(|_: (), _: (), _: (), _: ()| {}); + | ^^^----------------------------^^^^ + | | | + | | found signature defined here + | expected due to this + | + = note: expected closure signature `for<'a, 't0> fn(&'a (), Box<(dyn for<'a> Fn(&'a ()) + 'static)>, &'t0 (), for<'a, 'b> fn(&'a (), &'b ())) -> _` + found closure signature `fn((), (), (), ()) -> _` +note: required by a bound in `h2` + --> $DIR/anonymous-higher-ranked-lifetime.rs:36:25 + | +LL | fn h2(_: F) where F: for<'t0> Fn(&(), Box, &'t0 (), fn(&(), &())) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `h2` +help: consider adjusting the signature so it borrows its arguments + | +LL | h2(|_: &(), _: (), _: &(), _: ()| {}); + | + + + +error: aborting due to 11 previous errors + +For more information about this error, try `rustc --explain E0631`. -- cgit 1.4.1-3-g733a5 From 4652b14f9bce16e5d1a5fe4babd0d356e895905f Mon Sep 17 00:00:00 2001 From: Jieyou Xu Date: Thu, 5 Dec 2024 08:42:20 +0000 Subject: Adjust `artificial-block.rs` - Document `artificial-block.rs` - Move `artificial-block.rs` under `tests/ui/reachable` --- tests/ui/artificial-block.rs | 5 ----- tests/ui/reachable/artificial-block.rs | 30 ++++++++++++++++++++++++++++++ 2 files changed, 30 insertions(+), 5 deletions(-) delete mode 100644 tests/ui/artificial-block.rs create mode 100644 tests/ui/reachable/artificial-block.rs (limited to 'tests') diff --git a/tests/ui/artificial-block.rs b/tests/ui/artificial-block.rs deleted file mode 100644 index 037163b4174..00000000000 --- a/tests/ui/artificial-block.rs +++ /dev/null @@ -1,5 +0,0 @@ -//@ run-pass - -fn f() -> isize { { return 3; } } - -pub fn main() { assert_eq!(f(), 3); } diff --git a/tests/ui/reachable/artificial-block.rs b/tests/ui/reachable/artificial-block.rs new file mode 100644 index 00000000000..6d73ba1a972 --- /dev/null +++ b/tests/ui/reachable/artificial-block.rs @@ -0,0 +1,30 @@ +//! Check that we don't get compile errors on unreachable code after the `{ return 3; }` artificial +//! block below. This test is run-pass to also exercise the codegen, but it might be possible to +//! reduce to build-pass or even check-pass. +//! +//! This test was introduced as part of commit `a833f152baa17460e8414355e832d30d5161f8e8` which +//! removes an "artificial block". See also commit `3d738e9e0634a4cd6239d1317bd7dad53be68dc8` for +//! more elaboration, reproduced below (this is outdated for *today*'s rustc as of 2024-12-10, but +//! is helpful to understand the original intention): +//! +//! > Return a fresh, unreachable context after ret, break, and cont +//! > +//! > This ensures we don't get compile errors on unreachable code (see +//! > test/run-pass/artificial-block.rs for an example of sane code that wasn't compiling). In the +//! > future, we might want to warn about non-trivial code appearing in an unreachable context, +//! > and/or avoid generating unreachable code altogether (though I'm sure LLVM will weed it out as +//! > well). +//! +//! Since then, `ret` became `return`, `int` became `isize` and `assert` became a macro. + +//@ run-pass + +fn f() -> isize { + { + return 3; + } +} + +fn main() { + assert_eq!(f(), 3); +} -- cgit 1.4.1-3-g733a5 From 56efa0a7bf55aa4d1413008df672b95f09a4d8e9 Mon Sep 17 00:00:00 2001 From: "许杰友 Jieyou Xu (Joe)" <39484203+jieyouxu@users.noreply.github.com> Date: Sun, 8 Dec 2024 22:13:07 +0800 Subject: Adjust `as-precedence.rs` - Document `as-precedence.rs` - Move `as-precedence.rs` under `tests/ui/parser/` --- tests/ui/as-precedence.rs | 10 ---------- tests/ui/parser/as-precedence.rs | 18 ++++++++++++++++++ 2 files changed, 18 insertions(+), 10 deletions(-) delete mode 100644 tests/ui/as-precedence.rs create mode 100644 tests/ui/parser/as-precedence.rs (limited to 'tests') diff --git a/tests/ui/as-precedence.rs b/tests/ui/as-precedence.rs deleted file mode 100644 index 5021a3b677f..00000000000 --- a/tests/ui/as-precedence.rs +++ /dev/null @@ -1,10 +0,0 @@ -//@ run-pass - -#[allow(unused_parens)] -fn main() { - assert_eq!(3 as usize * 3, 9); - assert_eq!(3 as (usize) * 3, 9); - assert_eq!(3 as (usize) / 3, 1); - assert_eq!(3 as usize + 3, 6); - assert_eq!(3 as (usize) + 3, 6); -} diff --git a/tests/ui/parser/as-precedence.rs b/tests/ui/parser/as-precedence.rs new file mode 100644 index 00000000000..ca8328adb0e --- /dev/null +++ b/tests/ui/parser/as-precedence.rs @@ -0,0 +1,18 @@ +//! Parser precedence test to help with [RFC 87 "Trait Bounds with Plus"][rfc-87], to check the +//! precedence of the `as` operator in relation to some arithmetic bin-ops and parentheses. +//! +//! Editor's note: this test seems quite incomplete compared to what's possible nowadays. Maybe +//! there's another set of tests whose coverage overshadows this test? +//! +//! [rfc-87]: https://rust-lang.github.io/rfcs/0087-trait-bounds-with-plus.html + +//@ run-pass + +#[allow(unused_parens)] +fn main() { + assert_eq!(3 as usize * 3, 9); + assert_eq!(3 as (usize) * 3, 9); + assert_eq!(3 as (usize) / 3, 1); + assert_eq!(3 as usize + 3, 6); + assert_eq!(3 as (usize) + 3, 6); +} -- cgit 1.4.1-3-g733a5 From 3f52583c6a85f243e8444145e533fa799a40f777 Mon Sep 17 00:00:00 2001 From: Esteban Küber Date: Thu, 5 Dec 2024 21:02:00 +0000 Subject: Add test for resolve errors caused by mod with parse errors --- tests/ui/resolve/parse-error-resolve.rs | 7 ++++++ tests/ui/resolve/parse-error-resolve.stderr | 35 +++++++++++++++++++++++++++++ tests/ui/resolve/parse_error.rs | 5 +++++ tests/ui/resolve/parse_error.stderr | 13 +++++++++++ 4 files changed, 60 insertions(+) create mode 100644 tests/ui/resolve/parse-error-resolve.rs create mode 100644 tests/ui/resolve/parse-error-resolve.stderr create mode 100644 tests/ui/resolve/parse_error.rs create mode 100644 tests/ui/resolve/parse_error.stderr (limited to 'tests') diff --git a/tests/ui/resolve/parse-error-resolve.rs b/tests/ui/resolve/parse-error-resolve.rs new file mode 100644 index 00000000000..b5b6637bcfa --- /dev/null +++ b/tests/ui/resolve/parse-error-resolve.rs @@ -0,0 +1,7 @@ +mod parse_error; +use parse_error::Canonical; //~ ERROR E0432 + +fn main() { + let _ = "" + 1; //~ ERROR E0369 + parse_error::Canonical.foo(); //~ ERROR E0425 +} diff --git a/tests/ui/resolve/parse-error-resolve.stderr b/tests/ui/resolve/parse-error-resolve.stderr new file mode 100644 index 00000000000..72456b797d1 --- /dev/null +++ b/tests/ui/resolve/parse-error-resolve.stderr @@ -0,0 +1,35 @@ +error: expected one of `+`, `,`, `::`, `=`, or `>`, found `From` + --> $DIR/parse_error.rs:2:46 + | +LL | impl> From for Canonical { + | ^^^^ expected one of `+`, `,`, `::`, `=`, or `>` + | +help: you might have meant to end the type parameters here + | +LL | impl>> From for Canonical { + | + + +error[E0432]: unresolved import `parse_error::Canonical` + --> $DIR/parse-error-resolve.rs:2:5 + | +LL | use parse_error::Canonical; + | ^^^^^^^^^^^^^^^^^^^^^^ no `Canonical` in `parse_error` + +error[E0425]: cannot find value `Canonical` in module `parse_error` + --> $DIR/parse-error-resolve.rs:6:18 + | +LL | parse_error::Canonical.foo(); + | ^^^^^^^^^ not found in `parse_error` + +error[E0369]: cannot add `{integer}` to `&str` + --> $DIR/parse-error-resolve.rs:5:16 + | +LL | let _ = "" + 1; + | -- ^ - {integer} + | | + | &str + +error: aborting due to 4 previous errors + +Some errors have detailed explanations: E0369, E0425, E0432. +For more information about an error, try `rustc --explain E0369`. diff --git a/tests/ui/resolve/parse_error.rs b/tests/ui/resolve/parse_error.rs new file mode 100644 index 00000000000..4cd025e1edf --- /dev/null +++ b/tests/ui/resolve/parse_error.rs @@ -0,0 +1,5 @@ +struct Canonical; +impl> From for Canonical { //~ ERROR expected + fn foo() {} +} +fn bar() {} diff --git a/tests/ui/resolve/parse_error.stderr b/tests/ui/resolve/parse_error.stderr new file mode 100644 index 00000000000..f764f08875f --- /dev/null +++ b/tests/ui/resolve/parse_error.stderr @@ -0,0 +1,13 @@ +error: expected one of `+`, `,`, `::`, `=`, or `>`, found `From` + --> $DIR/parse_error.rs:2:46 + | +LL | impl> From for Canonical { + | ^^^^ expected one of `+`, `,`, `::`, `=`, or `>` + | +help: you might have meant to end the type parameters here + | +LL | impl>> From for Canonical { + | + + +error: aborting due to 1 previous error + -- cgit 1.4.1-3-g733a5 From 69fb612608f6b3d7f21a4efae869e69ca949955f Mon Sep 17 00:00:00 2001 From: Esteban Küber Date: Thu, 5 Dec 2024 21:19:08 +0000 Subject: Keep track of parse errors in `mod`s and don't emit resolve errors for paths involving them When we expand a `mod foo;` and parse `foo.rs`, we now track whether that file had an unrecovered parse error that reached the end of the file. If so, we keep that information around. When resolving a path like `foo::bar`, we do not emit any errors for "`bar` not found in `foo`", as we know that the parse error might have caused `bar` to not be parsed and accounted for. When this happens in an existing project, every path referencing `foo` would be an irrelevant compile error. Instead, we now skip emitting anything until `foo.rs` is fixed. Tellingly enough, we didn't have any test for errors caused by `mod` expansion. Fix #97734. --- compiler/rustc_ast/src/ast.rs | 2 +- compiler/rustc_ast/src/mut_visit.rs | 7 +- compiler/rustc_ast/src/visit.rs | 2 +- compiler/rustc_ast_lowering/src/item.rs | 2 +- compiler/rustc_ast_passes/src/ast_validation.rs | 2 +- compiler/rustc_builtin_macros/src/test_harness.rs | 6 +- compiler/rustc_expand/src/expand.rs | 32 +++++---- compiler/rustc_expand/src/module.rs | 10 ++- compiler/rustc_lint/src/builtin.rs | 2 +- compiler/rustc_parse/src/parser/item.rs | 2 +- compiler/rustc_resolve/src/build_reduced_graph.rs | 6 +- compiler/rustc_resolve/src/diagnostics.rs | 2 +- compiler/rustc_resolve/src/ident.rs | 82 ++++++++++++++-------- compiler/rustc_resolve/src/imports.rs | 1 + compiler/rustc_resolve/src/late.rs | 7 ++ compiler/rustc_resolve/src/lib.rs | 6 ++ compiler/rustc_resolve/src/macros.rs | 2 +- src/tools/clippy/clippy_lints/src/duplicate_mod.rs | 2 +- .../clippy/clippy_lints/src/excessive_nesting.rs | 2 +- src/tools/clippy/clippy_utils/src/ast_utils.rs | 2 +- src/tools/rustfmt/src/items.rs | 2 +- src/tools/rustfmt/src/modules.rs | 7 +- src/tools/rustfmt/src/visitor.rs | 2 +- tests/ui/parser/circular_modules_main.stderr | 19 +---- tests/ui/resolve/parse-error-resolve.rs | 2 +- tests/ui/resolve/parse-error-resolve.stderr | 10 +-- 26 files changed, 128 insertions(+), 93 deletions(-) (limited to 'tests') diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index 650525a2f52..a219f1dc032 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -2877,7 +2877,7 @@ pub enum ModKind { /// or with definition outlined to a separate file `mod foo;` and already loaded from it. /// The inner span is from the first token past `{` to the last token until `}`, /// or from the first to the last token in the loaded file. - Loaded(ThinVec>, Inline, ModSpans), + Loaded(ThinVec>, Inline, ModSpans, Result<(), ErrorGuaranteed>), /// Module with definition outlined to a separate file `mod foo;` but not yet loaded from it. Unloaded, } diff --git a/compiler/rustc_ast/src/mut_visit.rs b/compiler/rustc_ast/src/mut_visit.rs index 2c09059fe19..0e299c60479 100644 --- a/compiler/rustc_ast/src/mut_visit.rs +++ b/compiler/rustc_ast/src/mut_visit.rs @@ -1212,7 +1212,12 @@ impl WalkItemKind for ItemKind { ItemKind::Mod(safety, mod_kind) => { visit_safety(vis, safety); match mod_kind { - ModKind::Loaded(items, _inline, ModSpans { inner_span, inject_use_span }) => { + ModKind::Loaded( + items, + _inline, + ModSpans { inner_span, inject_use_span }, + _, + ) => { items.flat_map_in_place(|item| vis.flat_map_item(item)); vis.visit_span(inner_span); vis.visit_span(inject_use_span); diff --git a/compiler/rustc_ast/src/visit.rs b/compiler/rustc_ast/src/visit.rs index a7f7c37693a..a6232b6dfaf 100644 --- a/compiler/rustc_ast/src/visit.rs +++ b/compiler/rustc_ast/src/visit.rs @@ -380,7 +380,7 @@ impl WalkItemKind for ItemKind { try_visit!(visitor.visit_fn(kind, span, id)); } ItemKind::Mod(_unsafety, mod_kind) => match mod_kind { - ModKind::Loaded(items, _inline, _inner_span) => { + ModKind::Loaded(items, _inline, _inner_span, _) => { walk_list!(visitor, visit_item, items); } ModKind::Unloaded => {} diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index 7d6c41992eb..d63131eacb5 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -238,7 +238,7 @@ impl<'hir> LoweringContext<'_, 'hir> { }) } ItemKind::Mod(_, mod_kind) => match mod_kind { - ModKind::Loaded(items, _, spans) => { + ModKind::Loaded(items, _, spans, _) => { hir::ItemKind::Mod(self.lower_mod(items, spans)) } ModKind::Unloaded => panic!("`mod` items should have been loaded by now"), diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs index 64e91c91e2c..290c2e52970 100644 --- a/compiler/rustc_ast_passes/src/ast_validation.rs +++ b/compiler/rustc_ast_passes/src/ast_validation.rs @@ -1029,7 +1029,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> { self.dcx().emit_err(errors::UnsafeItem { span, kind: "module" }); } // Ensure that `path` attributes on modules are recorded as used (cf. issue #35584). - if !matches!(mod_kind, ModKind::Loaded(_, Inline::Yes, _)) + if !matches!(mod_kind, ModKind::Loaded(_, Inline::Yes, _, _)) && !attr::contains_name(&item.attrs, sym::path) { self.check_mod_file_item_asciionly(item.ident); diff --git a/compiler/rustc_builtin_macros/src/test_harness.rs b/compiler/rustc_builtin_macros/src/test_harness.rs index b2048c534a4..e7ff65e08f9 100644 --- a/compiler/rustc_builtin_macros/src/test_harness.rs +++ b/compiler/rustc_builtin_macros/src/test_harness.rs @@ -141,8 +141,10 @@ impl<'a> MutVisitor for TestHarnessGenerator<'a> { // We don't want to recurse into anything other than mods, since // mods or tests inside of functions will break things - if let ast::ItemKind::Mod(_, ModKind::Loaded(.., ast::ModSpans { inner_span: span, .. })) = - item.kind + if let ast::ItemKind::Mod( + _, + ModKind::Loaded(.., ast::ModSpans { inner_span: span, .. }, _), + ) = item.kind { let prev_tests = mem::take(&mut self.tests); walk_item_kind( diff --git a/compiler/rustc_expand/src/expand.rs b/compiler/rustc_expand/src/expand.rs index 6a6496f9827..690e080fbfc 100644 --- a/compiler/rustc_expand/src/expand.rs +++ b/compiler/rustc_expand/src/expand.rs @@ -723,7 +723,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> { item_inner.kind, ItemKind::Mod( _, - ModKind::Unloaded | ModKind::Loaded(_, Inline::No, _), + ModKind::Unloaded | ModKind::Loaded(_, Inline::No, _, _), ) ) => { @@ -889,7 +889,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> { fn visit_item(&mut self, item: &'ast ast::Item) { match &item.kind { ItemKind::Mod(_, mod_kind) - if !matches!(mod_kind, ModKind::Loaded(_, Inline::Yes, _)) => + if !matches!(mod_kind, ModKind::Loaded(_, Inline::Yes, _, _)) => { feature_err( self.sess, @@ -1195,7 +1195,7 @@ impl InvocationCollectorNode for P { let ecx = &mut collector.cx; let (file_path, dir_path, dir_ownership) = match mod_kind { - ModKind::Loaded(_, inline, _) => { + ModKind::Loaded(_, inline, _, _) => { // Inline `mod foo { ... }`, but we still need to push directories. let (dir_path, dir_ownership) = mod_dir_path( ecx.sess, @@ -1217,15 +1217,21 @@ impl InvocationCollectorNode for P { ModKind::Unloaded => { // We have an outline `mod foo;` so we need to parse the file. let old_attrs_len = attrs.len(); - let ParsedExternalMod { items, spans, file_path, dir_path, dir_ownership } = - parse_external_mod( - ecx.sess, - ident, - span, - &ecx.current_expansion.module, - ecx.current_expansion.dir_ownership, - &mut attrs, - ); + let ParsedExternalMod { + items, + spans, + file_path, + dir_path, + dir_ownership, + had_parse_error, + } = parse_external_mod( + ecx.sess, + ident, + span, + &ecx.current_expansion.module, + ecx.current_expansion.dir_ownership, + &mut attrs, + ); if let Some(lint_store) = ecx.lint_store { lint_store.pre_expansion_lint( @@ -1239,7 +1245,7 @@ impl InvocationCollectorNode for P { ); } - *mod_kind = ModKind::Loaded(items, Inline::No, spans); + *mod_kind = ModKind::Loaded(items, Inline::No, spans, had_parse_error); node.attrs = attrs; if node.attrs.len() > old_attrs_len { // If we loaded an out-of-line module and added some inner attributes, diff --git a/compiler/rustc_expand/src/module.rs b/compiler/rustc_expand/src/module.rs index 614f52bbd28..85ea42e78ad 100644 --- a/compiler/rustc_expand/src/module.rs +++ b/compiler/rustc_expand/src/module.rs @@ -37,6 +37,7 @@ pub(crate) struct ParsedExternalMod { pub file_path: PathBuf, pub dir_path: PathBuf, pub dir_ownership: DirOwnership, + pub had_parse_error: Result<(), ErrorGuaranteed>, } pub enum ModError<'a> { @@ -74,14 +75,17 @@ pub(crate) fn parse_external_mod( attrs.extend(inner_attrs); (items, inner_span, mp.file_path) }; + // (1) ...instead, we return a dummy module. - let (items, spans, file_path) = - result.map_err(|err| err.report(sess, span)).unwrap_or_default(); + let ((items, spans, file_path), had_parse_error) = match result { + Err(err) => (Default::default(), Err(err.report(sess, span))), + Ok(result) => (result, Ok(())), + }; // Extract the directory path for submodules of the module. let dir_path = file_path.parent().unwrap_or(&file_path).to_owned(); - ParsedExternalMod { items, spans, file_path, dir_path, dir_ownership } + ParsedExternalMod { items, spans, file_path, dir_path, dir_ownership, had_parse_error } } pub(crate) fn mod_dir_path( diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs index 093cc16fb4c..3543784bc72 100644 --- a/compiler/rustc_lint/src/builtin.rs +++ b/compiler/rustc_lint/src/builtin.rs @@ -3038,7 +3038,7 @@ impl EarlyLintPass for SpecialModuleName { for item in &krate.items { if let ast::ItemKind::Mod( _, - ast::ModKind::Unloaded | ast::ModKind::Loaded(_, ast::Inline::No, _), + ast::ModKind::Unloaded | ast::ModKind::Loaded(_, ast::Inline::No, _, _), ) = item.kind { if item.attrs.iter().any(|a| a.has_name(sym::path)) { diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs index 58b4bf8980b..e27fc963eb9 100644 --- a/compiler/rustc_parse/src/parser/item.rs +++ b/compiler/rustc_parse/src/parser/item.rs @@ -45,7 +45,7 @@ impl<'a> Parser<'a> { let (inner_attrs, items, inner_span) = self.parse_mod(&token::CloseDelim(Delimiter::Brace))?; attrs.extend(inner_attrs); - ModKind::Loaded(items, Inline::Yes, inner_span) + ModKind::Loaded(items, Inline::Yes, inner_span, Ok(())) }; Ok((id, ItemKind::Mod(safety, mod_kind))) } diff --git a/compiler/rustc_resolve/src/build_reduced_graph.rs b/compiler/rustc_resolve/src/build_reduced_graph.rs index 293cee500bb..924b8afa329 100644 --- a/compiler/rustc_resolve/src/build_reduced_graph.rs +++ b/compiler/rustc_resolve/src/build_reduced_graph.rs @@ -770,7 +770,7 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> { ); } - ItemKind::Mod(..) => { + ItemKind::Mod(.., ref mod_kind) => { let module = self.r.new_module( Some(parent), ModuleKind::Def(def_kind, def_id, ident.name), @@ -781,6 +781,10 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> { ); self.r.define(parent, ident, TypeNS, (module, vis, sp, expansion)); + if let ast::ModKind::Loaded(_, _, _, Err(_)) = mod_kind { + self.r.mods_with_parse_errors.insert(def_id); + } + // Descend into the module. self.parent_scope.module = module; } diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs index 4c76617a391..368eb3c26c7 100644 --- a/compiler/rustc_resolve/src/diagnostics.rs +++ b/compiler/rustc_resolve/src/diagnostics.rs @@ -3056,7 +3056,7 @@ impl<'tcx> visit::Visitor<'tcx> for UsePlacementFinder { fn visit_item(&mut self, item: &'tcx ast::Item) { if self.target_module == item.id { - if let ItemKind::Mod(_, ModKind::Loaded(items, _inline, mod_spans)) = &item.kind { + if let ItemKind::Mod(_, ModKind::Loaded(items, _inline, mod_spans, _)) = &item.kind { let inject = mod_spans.inject_use_span; if is_span_suitable_for_use_injection(inject) { self.first_legal_span = Some(inject); diff --git a/compiler/rustc_resolve/src/ident.rs b/compiler/rustc_resolve/src/ident.rs index 466e190028a..5906a682f3e 100644 --- a/compiler/rustc_resolve/src/ident.rs +++ b/compiler/rustc_resolve/src/ident.rs @@ -1428,6 +1428,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { ignore_import: Option>, ) -> PathResult<'ra> { let mut module = None; + let mut module_had_parse_errors = false; let mut allow_super = true; let mut second_binding = None; @@ -1471,9 +1472,14 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { continue; } } - return PathResult::failed(ident, false, finalize.is_some(), module, || { - ("there are too many leading `super` keywords".to_string(), None) - }); + return PathResult::failed( + ident, + false, + finalize.is_some(), + module_had_parse_errors, + module, + || ("there are too many leading `super` keywords".to_string(), None), + ); } if segment_idx == 0 { if name == kw::SelfLower { @@ -1511,19 +1517,26 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { // Report special messages for path segment keywords in wrong positions. if ident.is_path_segment_keyword() && segment_idx != 0 { - return PathResult::failed(ident, false, finalize.is_some(), module, || { - let name_str = if name == kw::PathRoot { - "crate root".to_string() - } else { - format!("`{name}`") - }; - let label = if segment_idx == 1 && path[0].ident.name == kw::PathRoot { - format!("global paths cannot start with {name_str}") - } else { - format!("{name_str} in paths can only be used in start position") - }; - (label, None) - }); + return PathResult::failed( + ident, + false, + finalize.is_some(), + module_had_parse_errors, + module, + || { + let name_str = if name == kw::PathRoot { + "crate root".to_string() + } else { + format!("`{name}`") + }; + let label = if segment_idx == 1 && path[0].ident.name == kw::PathRoot { + format!("global paths cannot start with {name_str}") + } else { + format!("{name_str} in paths can only be used in start position") + }; + (label, None) + }, + ); } let binding = if let Some(module) = module { @@ -1589,6 +1602,9 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { let maybe_assoc = opt_ns != Some(MacroNS) && PathSource::Type.is_expected(res); if let Some(next_module) = binding.module() { + if self.mods_with_parse_errors.contains(&next_module.def_id()) { + module_had_parse_errors = true; + } module = Some(ModuleOrUniformRoot::Module(next_module)); record_segment_res(self, res); } else if res == Res::ToolMod && !is_last && opt_ns.is_some() { @@ -1614,6 +1630,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { ident, is_last, finalize.is_some(), + module_had_parse_errors, module, || { let label = format!( @@ -1637,19 +1654,26 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { } } - return PathResult::failed(ident, is_last, finalize.is_some(), module, || { - self.report_path_resolution_error( - path, - opt_ns, - parent_scope, - ribs, - ignore_binding, - ignore_import, - module, - segment_idx, - ident, - ) - }); + return PathResult::failed( + ident, + is_last, + finalize.is_some(), + module_had_parse_errors, + module, + || { + self.report_path_resolution_error( + path, + opt_ns, + parent_scope, + ribs, + ignore_binding, + ignore_import, + module, + segment_idx, + ident, + ) + }, + ); } } } diff --git a/compiler/rustc_resolve/src/imports.rs b/compiler/rustc_resolve/src/imports.rs index 51fbcb8ebb8..5b8eefbb88d 100644 --- a/compiler/rustc_resolve/src/imports.rs +++ b/compiler/rustc_resolve/src/imports.rs @@ -898,6 +898,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { label, suggestion, module, + error_implied_by_parse_error: _, } => { if no_ambiguity { assert!(import.imported_module.get().is_none()); diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 789d74876f7..5cb7bb9b461 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -4395,6 +4395,12 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { PathResult::Module(ModuleOrUniformRoot::Module(module)) if !module.is_normal() => { PartialRes::new(module.res().unwrap()) } + // A part of this path references a `mod` that had a parse error. To avoid resolution + // errors for each reference to that module, we don't emit an error for them until the + // `mod` is fixed. this can have a significant cascade effect. + PathResult::Failed { error_implied_by_parse_error: true, .. } => { + PartialRes::new(Res::Err) + } // In `a(::assoc_item)*` `a` cannot be a module. If `a` does resolve to a module we // don't report an error right away, but try to fallback to a primitive type. // So, we are still able to successfully resolve something like @@ -4443,6 +4449,7 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { suggestion, module, segment_name, + error_implied_by_parse_error: _, } => { return Err(respan(span, ResolutionError::FailedToResolve { segment: Some(segment_name), diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index ca4adce37ce..94adfcd3b91 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -450,6 +450,7 @@ enum PathResult<'ra> { module: Option>, /// The segment name of target segment_name: Symbol, + error_implied_by_parse_error: bool, }, } @@ -458,6 +459,7 @@ impl<'ra> PathResult<'ra> { ident: Ident, is_error_from_last_segment: bool, finalize: bool, + error_implied_by_parse_error: bool, module: Option>, label_and_suggestion: impl FnOnce() -> (String, Option), ) -> PathResult<'ra> { @@ -470,6 +472,7 @@ impl<'ra> PathResult<'ra> { suggestion, is_error_from_last_segment, module, + error_implied_by_parse_error, } } } @@ -1198,6 +1201,8 @@ pub struct Resolver<'ra, 'tcx> { /// This is the `Span` where an `extern crate foo;` suggestion would be inserted, if `foo` /// could be a crate that wasn't imported. For diagnostics use only. current_crate_outer_attr_insert_span: Span, + + mods_with_parse_errors: FxHashSet, } /// This provides memory for the rest of the crate. The `'ra` lifetime that is @@ -1543,6 +1548,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { impl_unexpanded_invocations: Default::default(), impl_binding_keys: Default::default(), current_crate_outer_attr_insert_span, + mods_with_parse_errors: Default::default(), }; let root_parent_scope = ParentScope::module(graph_root, &resolver); diff --git a/compiler/rustc_resolve/src/macros.rs b/compiler/rustc_resolve/src/macros.rs index 0b4d0e04c29..669a9c2428f 100644 --- a/compiler/rustc_resolve/src/macros.rs +++ b/compiler/rustc_resolve/src/macros.rs @@ -166,7 +166,7 @@ fn soft_custom_inner_attributes_gate(path: &ast::Path, invoc: &Invocation) -> bo [seg1, seg2] if seg1.ident.name == sym::rustfmt && seg2.ident.name == sym::skip => { if let InvocationKind::Attr { item, .. } = &invoc.kind { if let Annotatable::Item(item) = item { - if let ItemKind::Mod(_, ModKind::Loaded(_, Inline::No, _)) = item.kind { + if let ItemKind::Mod(_, ModKind::Loaded(_, Inline::No, _, _)) = item.kind { return true; } } diff --git a/src/tools/clippy/clippy_lints/src/duplicate_mod.rs b/src/tools/clippy/clippy_lints/src/duplicate_mod.rs index ed27e38ef2d..1dac7b971f9 100644 --- a/src/tools/clippy/clippy_lints/src/duplicate_mod.rs +++ b/src/tools/clippy/clippy_lints/src/duplicate_mod.rs @@ -63,7 +63,7 @@ impl_lint_pass!(DuplicateMod => [DUPLICATE_MOD]); impl EarlyLintPass for DuplicateMod { fn check_item(&mut self, cx: &EarlyContext<'_>, item: &Item) { - if let ItemKind::Mod(_, ModKind::Loaded(_, Inline::No, mod_spans)) = &item.kind + if let ItemKind::Mod(_, ModKind::Loaded(_, Inline::No, mod_spans, _)) = &item.kind && let FileName::Real(real) = cx.sess().source_map().span_to_filename(mod_spans.inner_span) && let Some(local_path) = real.into_local_path() && let Ok(absolute_path) = local_path.canonicalize() diff --git a/src/tools/clippy/clippy_lints/src/excessive_nesting.rs b/src/tools/clippy/clippy_lints/src/excessive_nesting.rs index ffc76366983..dfea40db182 100644 --- a/src/tools/clippy/clippy_lints/src/excessive_nesting.rs +++ b/src/tools/clippy/clippy_lints/src/excessive_nesting.rs @@ -163,7 +163,7 @@ impl Visitor<'_> for NestingVisitor<'_, '_> { } match &item.kind { - ItemKind::Trait(_) | ItemKind::Impl(_) | ItemKind::Mod(.., ModKind::Loaded(_, Inline::Yes, _)) => { + ItemKind::Trait(_) | ItemKind::Impl(_) | ItemKind::Mod(.., ModKind::Loaded(_, Inline::Yes, _, _)) => { self.nest_level += 1; if !self.check_indent(item.span, item.id) { diff --git a/src/tools/clippy/clippy_utils/src/ast_utils.rs b/src/tools/clippy/clippy_utils/src/ast_utils.rs index 620a9b56eb5..12074dd16e6 100644 --- a/src/tools/clippy/clippy_utils/src/ast_utils.rs +++ b/src/tools/clippy/clippy_utils/src/ast_utils.rs @@ -379,7 +379,7 @@ pub fn eq_item_kind(l: &ItemKind, r: &ItemKind) -> bool { (Mod(lu, lmk), Mod(ru, rmk)) => { lu == ru && match (lmk, rmk) { - (ModKind::Loaded(litems, linline, _), ModKind::Loaded(ritems, rinline, _)) => { + (ModKind::Loaded(litems, linline, _, _), ModKind::Loaded(ritems, rinline, _, _)) => { linline == rinline && over(litems, ritems, |l, r| eq_item(l, r, eq_item_kind)) }, (ModKind::Unloaded, ModKind::Unloaded) => true, diff --git a/src/tools/rustfmt/src/items.rs b/src/tools/rustfmt/src/items.rs index 18932587f1f..c3debc2f4f0 100644 --- a/src/tools/rustfmt/src/items.rs +++ b/src/tools/rustfmt/src/items.rs @@ -3597,7 +3597,7 @@ pub(crate) fn rewrite_extern_crate( pub(crate) fn is_mod_decl(item: &ast::Item) -> bool { !matches!( item.kind, - ast::ItemKind::Mod(_, ast::ModKind::Loaded(_, ast::Inline::Yes, _)) + ast::ItemKind::Mod(_, ast::ModKind::Loaded(_, ast::Inline::Yes, _, _)) ) } diff --git a/src/tools/rustfmt/src/modules.rs b/src/tools/rustfmt/src/modules.rs index 493b04f16c6..a40ee7f66a9 100644 --- a/src/tools/rustfmt/src/modules.rs +++ b/src/tools/rustfmt/src/modules.rs @@ -316,12 +316,11 @@ impl<'ast, 'psess, 'c> ModResolver<'ast, 'psess> { self.directory = directory; } match (sub_mod.ast_mod_kind, sub_mod.items) { - (Some(Cow::Borrowed(ast::ModKind::Loaded(items, _, _))), _) => { + (Some(Cow::Borrowed(ast::ModKind::Loaded(items, _, _, _))), _) => { self.visit_mod_from_ast(items) } - (Some(Cow::Owned(ast::ModKind::Loaded(items, _, _))), _) | (_, Cow::Owned(items)) => { - self.visit_mod_outside_ast(items) - } + (Some(Cow::Owned(ast::ModKind::Loaded(items, _, _, _))), _) + | (_, Cow::Owned(items)) => self.visit_mod_outside_ast(items), (_, _) => Ok(()), } } diff --git a/src/tools/rustfmt/src/visitor.rs b/src/tools/rustfmt/src/visitor.rs index 9b116b620b7..805e13b7803 100644 --- a/src/tools/rustfmt/src/visitor.rs +++ b/src/tools/rustfmt/src/visitor.rs @@ -927,7 +927,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { let ident_str = rewrite_ident(&self.get_context(), ident).to_owned(); self.push_str(&ident_str); - if let ast::ModKind::Loaded(ref items, ast::Inline::Yes, ref spans) = mod_kind { + if let ast::ModKind::Loaded(ref items, ast::Inline::Yes, ref spans, _) = mod_kind { let ast::ModSpans { inner_span, inject_use_span: _, diff --git a/tests/ui/parser/circular_modules_main.stderr b/tests/ui/parser/circular_modules_main.stderr index 2de70789358..e1780fe9fd9 100644 --- a/tests/ui/parser/circular_modules_main.stderr +++ b/tests/ui/parser/circular_modules_main.stderr @@ -4,22 +4,5 @@ error: circular modules: $DIR/circular_modules_main.rs -> $DIR/circular_modules_ LL | mod circular_modules_main; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ -error[E0425]: cannot find function `hi_str` in module `circular_modules_main` - --> $DIR/circular_modules_hello.rs:7:43 - | -LL | println!("{}", circular_modules_main::hi_str()); - | ^^^^^^ not found in `circular_modules_main` - | -help: consider importing this function - | -LL + use hi_str; - | -help: if you import `hi_str`, refer to it directly - | -LL - println!("{}", circular_modules_main::hi_str()); -LL + println!("{}", hi_str()); - | - -error: aborting due to 2 previous errors +error: aborting due to 1 previous error -For more information about this error, try `rustc --explain E0425`. diff --git a/tests/ui/resolve/parse-error-resolve.rs b/tests/ui/resolve/parse-error-resolve.rs index b5b6637bcfa..9cb58f55128 100644 --- a/tests/ui/resolve/parse-error-resolve.rs +++ b/tests/ui/resolve/parse-error-resolve.rs @@ -3,5 +3,5 @@ use parse_error::Canonical; //~ ERROR E0432 fn main() { let _ = "" + 1; //~ ERROR E0369 - parse_error::Canonical.foo(); //~ ERROR E0425 + parse_error::Canonical.foo(); // ok, `parse_error.rs` had parse errors } diff --git a/tests/ui/resolve/parse-error-resolve.stderr b/tests/ui/resolve/parse-error-resolve.stderr index 72456b797d1..c05a9c6dafb 100644 --- a/tests/ui/resolve/parse-error-resolve.stderr +++ b/tests/ui/resolve/parse-error-resolve.stderr @@ -15,12 +15,6 @@ error[E0432]: unresolved import `parse_error::Canonical` LL | use parse_error::Canonical; | ^^^^^^^^^^^^^^^^^^^^^^ no `Canonical` in `parse_error` -error[E0425]: cannot find value `Canonical` in module `parse_error` - --> $DIR/parse-error-resolve.rs:6:18 - | -LL | parse_error::Canonical.foo(); - | ^^^^^^^^^ not found in `parse_error` - error[E0369]: cannot add `{integer}` to `&str` --> $DIR/parse-error-resolve.rs:5:16 | @@ -29,7 +23,7 @@ LL | let _ = "" + 1; | | | &str -error: aborting due to 4 previous errors +error: aborting due to 3 previous errors -Some errors have detailed explanations: E0369, E0425, E0432. +Some errors have detailed explanations: E0369, E0432. For more information about an error, try `rustc --explain E0369`. -- cgit 1.4.1-3-g733a5 From 27420c69d830d7a32544dd42f40c757d9cb4e095 Mon Sep 17 00:00:00 2001 From: Esteban Küber Date: Thu, 5 Dec 2024 21:47:06 +0000 Subject: Silence `use foo::Bar;` error if `Bar` isn't found in `foo` and `foo.rs` has parse errors --- compiler/rustc_resolve/src/imports.rs | 7 ++++++- tests/ui/resolve/parse-error-resolve.rs | 2 +- tests/ui/resolve/parse-error-resolve.stderr | 11 ++--------- 3 files changed, 9 insertions(+), 11 deletions(-) (limited to 'tests') diff --git a/compiler/rustc_resolve/src/imports.rs b/compiler/rustc_resolve/src/imports.rs index 5b8eefbb88d..2ed3f4d2c4f 100644 --- a/compiler/rustc_resolve/src/imports.rs +++ b/compiler/rustc_resolve/src/imports.rs @@ -670,9 +670,14 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { fn throw_unresolved_import_error( &mut self, - errors: Vec<(Import<'_>, UnresolvedImportError)>, + mut errors: Vec<(Import<'_>, UnresolvedImportError)>, glob_error: bool, ) { + errors.retain(|(_import, err)| match err.module { + // Skip `use` errors for `use foo::Bar;` if `foo.rs` has unrecovered parse errors. + Some(def_id) if self.mods_with_parse_errors.contains(&def_id) => false, + _ => true, + }); if errors.is_empty() { return; } diff --git a/tests/ui/resolve/parse-error-resolve.rs b/tests/ui/resolve/parse-error-resolve.rs index 9cb58f55128..1e0772648af 100644 --- a/tests/ui/resolve/parse-error-resolve.rs +++ b/tests/ui/resolve/parse-error-resolve.rs @@ -1,5 +1,5 @@ mod parse_error; -use parse_error::Canonical; //~ ERROR E0432 +use parse_error::Canonical; // ok, `parse_error.rs` had parse errors fn main() { let _ = "" + 1; //~ ERROR E0369 diff --git a/tests/ui/resolve/parse-error-resolve.stderr b/tests/ui/resolve/parse-error-resolve.stderr index c05a9c6dafb..30475aa0ee6 100644 --- a/tests/ui/resolve/parse-error-resolve.stderr +++ b/tests/ui/resolve/parse-error-resolve.stderr @@ -9,12 +9,6 @@ help: you might have meant to end the type parameters here LL | impl>> From for Canonical { | + -error[E0432]: unresolved import `parse_error::Canonical` - --> $DIR/parse-error-resolve.rs:2:5 - | -LL | use parse_error::Canonical; - | ^^^^^^^^^^^^^^^^^^^^^^ no `Canonical` in `parse_error` - error[E0369]: cannot add `{integer}` to `&str` --> $DIR/parse-error-resolve.rs:5:16 | @@ -23,7 +17,6 @@ LL | let _ = "" + 1; | | | &str -error: aborting due to 3 previous errors +error: aborting due to 2 previous errors -Some errors have detailed explanations: E0369, E0432. -For more information about an error, try `rustc --explain E0369`. +For more information about this error, try `rustc --explain E0369`. -- cgit 1.4.1-3-g733a5 From c5d02237d3cf76b0d40724ba6714afaad1947d13 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Tue, 10 Dec 2024 19:42:09 +0000 Subject: Add tests --- compiler/rustc_parse/src/parser/ty.rs | 4 +- .../feature-gates/feature-gate-unsafe-binders.rs | 7 +++ .../feature-gate-unsafe-binders.stderr | 13 +++++ tests/ui/unsafe-binders/expr.rs | 13 +++++ tests/ui/unsafe-binders/expr.stderr | 29 ++++++++++ tests/ui/unsafe-binders/lifetime-resolution.rs | 19 +++++++ tests/ui/unsafe-binders/lifetime-resolution.stderr | 65 ++++++++++++++++++++++ tests/ui/unsafe-binders/simple.rs | 7 +++ tests/ui/unsafe-binders/simple.stderr | 17 ++++++ 9 files changed, 173 insertions(+), 1 deletion(-) create mode 100644 tests/ui/feature-gates/feature-gate-unsafe-binders.rs create mode 100644 tests/ui/feature-gates/feature-gate-unsafe-binders.stderr create mode 100644 tests/ui/unsafe-binders/expr.rs create mode 100644 tests/ui/unsafe-binders/expr.stderr create mode 100644 tests/ui/unsafe-binders/lifetime-resolution.rs create mode 100644 tests/ui/unsafe-binders/lifetime-resolution.stderr create mode 100644 tests/ui/unsafe-binders/simple.rs create mode 100644 tests/ui/unsafe-binders/simple.stderr (limited to 'tests') diff --git a/compiler/rustc_parse/src/parser/ty.rs b/compiler/rustc_parse/src/parser/ty.rs index 92ce57bbc92..f696074e66a 100644 --- a/compiler/rustc_parse/src/parser/ty.rs +++ b/compiler/rustc_parse/src/parser/ty.rs @@ -348,7 +348,9 @@ impl<'a> Parser<'a> { TyKind::Err(guar) } } - } else if self.check_keyword(kw::Unsafe) { + } else if self.check_keyword(kw::Unsafe) + && self.look_ahead(1, |tok| matches!(tok.kind, token::Lt)) + { self.parse_unsafe_binder_ty()? } else { let msg = format!("expected type, found {}", super::token_descr(&self.token)); diff --git a/tests/ui/feature-gates/feature-gate-unsafe-binders.rs b/tests/ui/feature-gates/feature-gate-unsafe-binders.rs new file mode 100644 index 00000000000..a2997ced4fa --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-unsafe-binders.rs @@ -0,0 +1,7 @@ +#[cfg(any())] +fn test() { + let x: unsafe<> (); + //~^ ERROR unsafe binder types are experimental +} + +fn main() {} diff --git a/tests/ui/feature-gates/feature-gate-unsafe-binders.stderr b/tests/ui/feature-gates/feature-gate-unsafe-binders.stderr new file mode 100644 index 00000000000..93997d6c14a --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-unsafe-binders.stderr @@ -0,0 +1,13 @@ +error[E0658]: unsafe binder types are experimental + --> $DIR/feature-gate-unsafe-binders.rs:3:12 + | +LL | let x: unsafe<> (); + | ^^^^^^^^^^^ + | + = note: see issue #130516 for more information + = help: add `#![feature(unsafe_binders)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/unsafe-binders/expr.rs b/tests/ui/unsafe-binders/expr.rs new file mode 100644 index 00000000000..d8c4c2df2cd --- /dev/null +++ b/tests/ui/unsafe-binders/expr.rs @@ -0,0 +1,13 @@ +#![feature(unsafe_binders)] +//~^ WARN the feature `unsafe_binders` is incomplete + +use std::unsafe_binder::{wrap_binder, unwrap_binder}; + +fn main() { + let x = 1; + let binder: unsafe<'a> &'a i32 = wrap_binder!(x); + //~^ ERROR unsafe binders are not yet implemented + //~| ERROR unsafe binders are not yet implemented + let rx = *unwrap_binder!(binder); + //~^ ERROR unsafe binders are not yet implemented +} diff --git a/tests/ui/unsafe-binders/expr.stderr b/tests/ui/unsafe-binders/expr.stderr new file mode 100644 index 00000000000..26fae1958b0 --- /dev/null +++ b/tests/ui/unsafe-binders/expr.stderr @@ -0,0 +1,29 @@ +warning: the feature `unsafe_binders` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/expr.rs:1:12 + | +LL | #![feature(unsafe_binders)] + | ^^^^^^^^^^^^^^ + | + = note: see issue #130516 for more information + = note: `#[warn(incomplete_features)]` on by default + +error: unsafe binders are not yet implemented + --> $DIR/expr.rs:8:17 + | +LL | let binder: unsafe<'a> &'a i32 = wrap_binder!(x); + | ^^^^^^^^^^^^^^^^^^ + +error: unsafe binders are not yet implemented + --> $DIR/expr.rs:8:51 + | +LL | let binder: unsafe<'a> &'a i32 = wrap_binder!(x); + | ^ + +error: unsafe binders are not yet implemented + --> $DIR/expr.rs:11:30 + | +LL | let rx = *unwrap_binder!(binder); + | ^^^^^^ + +error: aborting due to 3 previous errors; 1 warning emitted + diff --git a/tests/ui/unsafe-binders/lifetime-resolution.rs b/tests/ui/unsafe-binders/lifetime-resolution.rs new file mode 100644 index 00000000000..aebed9599d4 --- /dev/null +++ b/tests/ui/unsafe-binders/lifetime-resolution.rs @@ -0,0 +1,19 @@ +#![feature(unsafe_binders)] +//~^ WARN the feature `unsafe_binders` is incomplete + +fn foo<'a>() { + let good: unsafe<'b> &'a &'b (); + //~^ ERROR unsafe binders are not yet implemented + + let missing: unsafe<> &'missing (); + //~^ ERROR unsafe binders are not yet implemented + //~| ERROR use of undeclared lifetime name `'missing` + + fn inner<'b>() { + let outer: unsafe<> &'a &'b (); + //~^ ERROR unsafe binders are not yet implemented + //~| can't use generic parameters from outer item + } +} + +fn main() {} diff --git a/tests/ui/unsafe-binders/lifetime-resolution.stderr b/tests/ui/unsafe-binders/lifetime-resolution.stderr new file mode 100644 index 00000000000..7a8ce929df1 --- /dev/null +++ b/tests/ui/unsafe-binders/lifetime-resolution.stderr @@ -0,0 +1,65 @@ +error[E0261]: use of undeclared lifetime name `'missing` + --> $DIR/lifetime-resolution.rs:8:28 + | +LL | let missing: unsafe<> &'missing (); + | ^^^^^^^^ undeclared lifetime + | + = note: for more information on higher-ranked polymorphism, visit https://doc.rust-lang.org/nomicon/hrtb.html +help: consider making the type lifetime-generic with a new `'missing` lifetime + | +LL | let missing: unsafe<'missing, > &'missing (); + | +++++++++ +help: consider introducing lifetime `'missing` here + | +LL | fn foo<'missing, 'a>() { + | +++++++++ + +error[E0401]: can't use generic parameters from outer item + --> $DIR/lifetime-resolution.rs:13:30 + | +LL | fn foo<'a>() { + | -- lifetime parameter from outer item +... +LL | let outer: unsafe<> &'a &'b (); + | ^^ use of generic parameter from outer item + | +help: consider making the type lifetime-generic with a new `'a` lifetime + | +LL | let outer: unsafe<'a, > &'a &'b (); + | +++ +help: consider introducing lifetime `'a` here + | +LL | fn inner<'a, 'b>() { + | +++ + +warning: the feature `unsafe_binders` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/lifetime-resolution.rs:1:12 + | +LL | #![feature(unsafe_binders)] + | ^^^^^^^^^^^^^^ + | + = note: see issue #130516 for more information + = note: `#[warn(incomplete_features)]` on by default + +error: unsafe binders are not yet implemented + --> $DIR/lifetime-resolution.rs:5:15 + | +LL | let good: unsafe<'b> &'a &'b (); + | ^^^^^^^^^^^^^^^^^^^^^ + +error: unsafe binders are not yet implemented + --> $DIR/lifetime-resolution.rs:8:18 + | +LL | let missing: unsafe<> &'missing (); + | ^^^^^^^^^^^^^^^^^^^^^ + +error: unsafe binders are not yet implemented + --> $DIR/lifetime-resolution.rs:13:20 + | +LL | let outer: unsafe<> &'a &'b (); + | ^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 5 previous errors; 1 warning emitted + +Some errors have detailed explanations: E0261, E0401. +For more information about an error, try `rustc --explain E0261`. diff --git a/tests/ui/unsafe-binders/simple.rs b/tests/ui/unsafe-binders/simple.rs new file mode 100644 index 00000000000..cebff2cbfb8 --- /dev/null +++ b/tests/ui/unsafe-binders/simple.rs @@ -0,0 +1,7 @@ +#![feature(unsafe_binders)] +//~^ WARN the feature `unsafe_binders` is incomplete + +fn main() { + let x: unsafe<'a> &'a (); + //~^ ERROR unsafe binders are not yet implemented +} diff --git a/tests/ui/unsafe-binders/simple.stderr b/tests/ui/unsafe-binders/simple.stderr new file mode 100644 index 00000000000..a21dbd00b4c --- /dev/null +++ b/tests/ui/unsafe-binders/simple.stderr @@ -0,0 +1,17 @@ +warning: the feature `unsafe_binders` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/simple.rs:1:12 + | +LL | #![feature(unsafe_binders)] + | ^^^^^^^^^^^^^^ + | + = note: see issue #130516 for more information + = note: `#[warn(incomplete_features)]` on by default + +error: unsafe binders are not yet implemented + --> $DIR/simple.rs:5:12 + | +LL | let x: unsafe<'a> &'a (); + | ^^^^^^^^^^^^^^^^^ + +error: aborting due to 1 previous error; 1 warning emitted + -- cgit 1.4.1-3-g733a5