From 75563cd7253bb72876c5c97ff2f7813dd1485bc5 Mon Sep 17 00:00:00 2001 From: Christopher Acosta Date: Fri, 27 Jan 2023 22:23:01 +0100 Subject: [PATCH 01/14] Error code E0794 for late-bound lifetime parameter error. --- compiler/rustc_error_codes/src/error_codes.rs | 1 + .../src/error_codes/E0794.md | 64 +++++++++++++++++++ .../src/astconv/generics.rs | 2 +- .../const-arg-in-const-arg.full.stderr | 17 ++--- .../const-arg-in-const-arg.min.stderr | 18 +++--- tests/ui/late-bound-lifetimes/issue-80618.rs | 8 +++ .../late-bound-lifetimes/issue-80618.stderr | 15 +++++ .../method-call-lifetime-args-fail.stderr | 31 ++++----- .../methods/method-call-lifetime-args.stderr | 5 +- 9 files changed, 126 insertions(+), 35 deletions(-) create mode 100644 compiler/rustc_error_codes/src/error_codes/E0794.md create mode 100644 tests/ui/late-bound-lifetimes/issue-80618.rs create mode 100644 tests/ui/late-bound-lifetimes/issue-80618.stderr diff --git a/compiler/rustc_error_codes/src/error_codes.rs b/compiler/rustc_error_codes/src/error_codes.rs index df857be85adab..d104ff0891d34 100644 --- a/compiler/rustc_error_codes/src/error_codes.rs +++ b/compiler/rustc_error_codes/src/error_codes.rs @@ -513,6 +513,7 @@ E0790: include_str!("./error_codes/E0790.md"), E0791: include_str!("./error_codes/E0791.md"), E0792: include_str!("./error_codes/E0792.md"), E0793: include_str!("./error_codes/E0793.md"), +E0794: include_str!("./error_codes/E0794.md"), } // Undocumented removed error codes. Note that many removed error codes are documented. diff --git a/compiler/rustc_error_codes/src/error_codes/E0794.md b/compiler/rustc_error_codes/src/error_codes/E0794.md new file mode 100644 index 0000000000000..a33802885c006 --- /dev/null +++ b/compiler/rustc_error_codes/src/error_codes/E0794.md @@ -0,0 +1,64 @@ +A lifetime parameter of a function definition is called *late-bound* if it both: + +1. appears in an argument type +2. does not appear in a generic type constraint + +You cannot specify lifetime arguments for late-bound lifetime parameters. + +Erroneous code example: + +```compile_fail,E0794 +fn foo<'a>(x: &'a str) -> &'a str { x } +let _ = foo::<'static>; +``` + +The type of a concrete instance of a generic function is universally quantified +over late-bound lifetime parameters. This is because we want the function to +work for any lifetime substituted for the late-bound lifetime parameter, no +matter where the function is called. Consequently, it doesn't make sense to +specify arguments for late-bound lifetime parameters, since they are not +resolved until the function's call site(s). + +To fix the issue, remove the specified lifetime: + +``` +fn foo<'a>(x: &'a str) -> &'a str { x } +let _ = foo; +``` + +### Additional information + +Lifetime parameters that are not late-bound are called *early-bound*. +Confusion may arise from the fact that late-bound and early-bound +lifetime parameters are declared the same way in function definitions. +When referring to a function pointer type, universal quantification over +late-bound lifetime parameters can be made explicit: + +``` +trait BarTrait<'a> {} + +struct Bar<'a> { + s: &'a str +} + +impl<'a> BarTrait<'a> for Bar<'a> {} + +fn bar<'a, 'b, T>(x: &'a str, _t: T) -> &'a str +where T: BarTrait<'b> +{ + x +} + +let bar_fn: for<'a> fn(&'a str, Bar<'static>) -> &'a str = bar; // OK +let bar_fn2 = bar::<'static, Bar>; // Not allowed +let bar_fn3 = bar::; // OK +``` + +In the definition of `bar`, the lifetime parameter `'a` is late-bound, while +`'b` is early-bound. This is reflected in the type annotation for `bar_fn`, +where `'a` is universally quantified and `'b` is substituted by a specific +lifetime. It is not allowed to explicitly specify early-bound lifetime +arguments when late-bound lifetime parameters are present (as for `bar_fn2`, +see issue #42868: https://github.com/rust-lang/rust/issues/42868), although the +types that are constrained by early-bound parameters can be specified (as for +`bar_fn3`). diff --git a/compiler/rustc_hir_analysis/src/astconv/generics.rs b/compiler/rustc_hir_analysis/src/astconv/generics.rs index 7f6518ffd7148..11c5028744ace 100644 --- a/compiler/rustc_hir_analysis/src/astconv/generics.rs +++ b/compiler/rustc_hir_analysis/src/astconv/generics.rs @@ -618,7 +618,7 @@ pub(crate) fn prohibit_explicit_late_bound_lifetimes( if position == GenericArgPosition::Value && args.num_lifetime_params() != param_counts.lifetimes { - let mut err = tcx.sess.struct_span_err(span, msg); + let mut err = struct_span_err!(tcx.sess, span, E0794, "{}", msg); err.span_note(span_late, note); err.emit(); } else { diff --git a/tests/ui/const-generics/const-arg-in-const-arg.full.stderr b/tests/ui/const-generics/const-arg-in-const-arg.full.stderr index 8672e79b3e8c8..463a37d7e3d13 100644 --- a/tests/ui/const-generics/const-arg-in-const-arg.full.stderr +++ b/tests/ui/const-generics/const-arg-in-const-arg.full.stderr @@ -1,4 +1,4 @@ -error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present +error[E0794]: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present --> $DIR/const-arg-in-const-arg.rs:18:23 | LL | let _: [u8; faz::<'a>(&())]; @@ -10,7 +10,7 @@ note: the late bound lifetime parameter is introduced here LL | const fn faz<'a>(_: &'a ()) -> usize { 13 } | ^^ -error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present +error[E0794]: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present --> $DIR/const-arg-in-const-arg.rs:21:23 | LL | let _: [u8; faz::<'b>(&())]; @@ -22,7 +22,7 @@ note: the late bound lifetime parameter is introduced here LL | const fn faz<'a>(_: &'a ()) -> usize { 13 } | ^^ -error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present +error[E0794]: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present --> $DIR/const-arg-in-const-arg.rs:41:24 | LL | let _: Foo<{ faz::<'a>(&()) }>; @@ -34,7 +34,7 @@ note: the late bound lifetime parameter is introduced here LL | const fn faz<'a>(_: &'a ()) -> usize { 13 } | ^^ -error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present +error[E0794]: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present --> $DIR/const-arg-in-const-arg.rs:44:24 | LL | let _: Foo<{ faz::<'b>(&()) }>; @@ -94,7 +94,7 @@ LL | let _ = [0; bar::()]; | = help: try adding a `where` bound using this expression: `where [(); bar::()]:` -error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present +error[E0794]: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present --> $DIR/const-arg-in-const-arg.rs:30:23 | LL | let _ = [0; faz::<'a>(&())]; @@ -106,7 +106,7 @@ note: the late bound lifetime parameter is introduced here LL | const fn faz<'a>(_: &'a ()) -> usize { 13 } | ^^ -error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present +error[E0794]: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present --> $DIR/const-arg-in-const-arg.rs:33:23 | LL | let _ = [0; faz::<'b>(&())]; @@ -134,7 +134,7 @@ LL | let _ = Foo::<{ bar::() }>; | = help: try adding a `where` bound using this expression: `where [(); { bar::() }]:` -error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present +error[E0794]: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present --> $DIR/const-arg-in-const-arg.rs:52:27 | LL | let _ = Foo::<{ faz::<'a>(&()) }>; @@ -146,7 +146,7 @@ note: the late bound lifetime parameter is introduced here LL | const fn faz<'a>(_: &'a ()) -> usize { 13 } | ^^ -error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present +error[E0794]: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present --> $DIR/const-arg-in-const-arg.rs:55:27 | LL | let _ = Foo::<{ faz::<'b>(&()) }>; @@ -160,3 +160,4 @@ LL | const fn faz<'a>(_: &'a ()) -> usize { 13 } error: aborting due to 16 previous errors +For more information about this error, try `rustc --explain E0794`. diff --git a/tests/ui/const-generics/const-arg-in-const-arg.min.stderr b/tests/ui/const-generics/const-arg-in-const-arg.min.stderr index f1353aa99437d..a7bd9c62b0ee3 100644 --- a/tests/ui/const-generics/const-arg-in-const-arg.min.stderr +++ b/tests/ui/const-generics/const-arg-in-const-arg.min.stderr @@ -216,7 +216,7 @@ help: if this generic argument was intended as a const parameter, surround it wi LL | let _: [u8; bar::<{ N }>()]; | + + -error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present +error[E0794]: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present --> $DIR/const-arg-in-const-arg.rs:18:23 | LL | let _: [u8; faz::<'a>(&())]; @@ -228,7 +228,7 @@ note: the late bound lifetime parameter is introduced here LL | const fn faz<'a>(_: &'a ()) -> usize { 13 } | ^^ -error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present +error[E0794]: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present --> $DIR/const-arg-in-const-arg.rs:21:23 | LL | let _: [u8; faz::<'b>(&())]; @@ -251,7 +251,7 @@ help: if this generic argument was intended as a const parameter, surround it wi LL | let _: Foo<{ bar::<{ N }>() }>; | + + -error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present +error[E0794]: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present --> $DIR/const-arg-in-const-arg.rs:41:24 | LL | let _: Foo<{ faz::<'a>(&()) }>; @@ -263,7 +263,7 @@ note: the late bound lifetime parameter is introduced here LL | const fn faz<'a>(_: &'a ()) -> usize { 13 } | ^^ -error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present +error[E0794]: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present --> $DIR/const-arg-in-const-arg.rs:44:24 | LL | let _: Foo<{ faz::<'b>(&()) }>; @@ -294,7 +294,7 @@ help: if this generic argument was intended as a const parameter, surround it wi LL | let _ = [0; bar::<{ N }>()]; | + + -error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present +error[E0794]: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present --> $DIR/const-arg-in-const-arg.rs:30:23 | LL | let _ = [0; faz::<'a>(&())]; @@ -306,7 +306,7 @@ note: the late bound lifetime parameter is introduced here LL | const fn faz<'a>(_: &'a ()) -> usize { 13 } | ^^ -error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present +error[E0794]: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present --> $DIR/const-arg-in-const-arg.rs:33:23 | LL | let _ = [0; faz::<'b>(&())]; @@ -329,7 +329,7 @@ help: if this generic argument was intended as a const parameter, surround it wi LL | let _ = Foo::<{ bar::<{ N }>() }>; | + + -error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present +error[E0794]: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present --> $DIR/const-arg-in-const-arg.rs:52:27 | LL | let _ = Foo::<{ faz::<'a>(&()) }>; @@ -341,7 +341,7 @@ note: the late bound lifetime parameter is introduced here LL | const fn faz<'a>(_: &'a ()) -> usize { 13 } | ^^ -error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present +error[E0794]: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present --> $DIR/const-arg-in-const-arg.rs:55:27 | LL | let _ = Foo::<{ faz::<'b>(&()) }>; @@ -355,5 +355,5 @@ LL | const fn faz<'a>(_: &'a ()) -> usize { 13 } error: aborting due to 36 previous errors -Some errors have detailed explanations: E0658, E0747. +Some errors have detailed explanations: E0658, E0747, E0794. For more information about an error, try `rustc --explain E0658`. diff --git a/tests/ui/late-bound-lifetimes/issue-80618.rs b/tests/ui/late-bound-lifetimes/issue-80618.rs new file mode 100644 index 0000000000000..6aa8ff461a9a9 --- /dev/null +++ b/tests/ui/late-bound-lifetimes/issue-80618.rs @@ -0,0 +1,8 @@ +fn foo<'a>(x: &'a str) -> &'a str { + x +} + +fn main() { + let _ = foo::<'static>; +//~^ ERROR cannot specify lifetime arguments explicitly if late bound lifetime parameters are present [E0794] +} diff --git a/tests/ui/late-bound-lifetimes/issue-80618.stderr b/tests/ui/late-bound-lifetimes/issue-80618.stderr new file mode 100644 index 0000000000000..cf7423fc16feb --- /dev/null +++ b/tests/ui/late-bound-lifetimes/issue-80618.stderr @@ -0,0 +1,15 @@ +error[E0794]: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present + --> $DIR/issue-80618.rs:6:19 + | +LL | let _ = foo::<'static>; + | ^^^^^^^ + | +note: the late bound lifetime parameter is introduced here + --> $DIR/issue-80618.rs:1:8 + | +LL | fn foo<'a>(x: &'a str) -> &'a str { + | ^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0794`. diff --git a/tests/ui/methods/method-call-lifetime-args-fail.stderr b/tests/ui/methods/method-call-lifetime-args-fail.stderr index 34526256f9975..645d8b8d14ad2 100644 --- a/tests/ui/methods/method-call-lifetime-args-fail.stderr +++ b/tests/ui/methods/method-call-lifetime-args-fail.stderr @@ -30,7 +30,7 @@ note: method defined here, with 2 lifetime parameters: `'a`, `'b` LL | fn early<'a, 'b>(self) -> (&'a u8, &'b u8) { loop {} } | ^^^^^ -- -- -error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present +error[E0794]: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present --> $DIR/method-call-lifetime-args-fail.rs:27:15 | LL | S::late::<'static>(S, &0, &0); @@ -42,7 +42,7 @@ note: the late bound lifetime parameter is introduced here LL | fn late<'a, 'b>(self, _: &'a u8, _: &'b u8) {} | ^^ -error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present +error[E0794]: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present --> $DIR/method-call-lifetime-args-fail.rs:29:15 | LL | S::late::<'static, 'static>(S, &0, &0); @@ -54,7 +54,7 @@ note: the late bound lifetime parameter is introduced here LL | fn late<'a, 'b>(self, _: &'a u8, _: &'b u8) {} | ^^ -error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present +error[E0794]: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present --> $DIR/method-call-lifetime-args-fail.rs:31:15 | LL | S::late::<'static, 'static, 'static>(S, &0, &0); @@ -66,7 +66,7 @@ note: the late bound lifetime parameter is introduced here LL | fn late<'a, 'b>(self, _: &'a u8, _: &'b u8) {} | ^^ -error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present +error[E0794]: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present --> $DIR/method-call-lifetime-args-fail.rs:34:21 | LL | S::late_early::<'static, 'static>(S, &0); @@ -78,7 +78,7 @@ note: the late bound lifetime parameter is introduced here LL | fn late_early<'a, 'b>(self, _: &'a u8) -> &'b u8 { loop {} } | ^^ -error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present +error[E0794]: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present --> $DIR/method-call-lifetime-args-fail.rs:36:21 | LL | S::late_early::<'static, 'static, 'static>(S, &0); @@ -90,7 +90,7 @@ note: the late bound lifetime parameter is introduced here LL | fn late_early<'a, 'b>(self, _: &'a u8) -> &'b u8 { loop {} } | ^^ -error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present +error[E0794]: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present --> $DIR/method-call-lifetime-args-fail.rs:40:24 | LL | S::late_implicit::<'static>(S, &0, &0); @@ -102,7 +102,7 @@ note: the late bound lifetime parameter is introduced here LL | fn late_implicit(self, _: &u8, _: &u8) {} | ^ -error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present +error[E0794]: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present --> $DIR/method-call-lifetime-args-fail.rs:42:24 | LL | S::late_implicit::<'static, 'static>(S, &0, &0); @@ -114,7 +114,7 @@ note: the late bound lifetime parameter is introduced here LL | fn late_implicit(self, _: &u8, _: &u8) {} | ^ -error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present +error[E0794]: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present --> $DIR/method-call-lifetime-args-fail.rs:44:24 | LL | S::late_implicit::<'static, 'static, 'static>(S, &0, &0); @@ -126,7 +126,7 @@ note: the late bound lifetime parameter is introduced here LL | fn late_implicit(self, _: &u8, _: &u8) {} | ^ -error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present +error[E0794]: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present --> $DIR/method-call-lifetime-args-fail.rs:47:30 | LL | S::late_implicit_early::<'static, 'static>(S, &0); @@ -138,7 +138,7 @@ note: the late bound lifetime parameter is introduced here LL | fn late_implicit_early<'b>(self, _: &u8) -> &'b u8 { loop {} } | ^ -error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present +error[E0794]: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present --> $DIR/method-call-lifetime-args-fail.rs:49:30 | LL | S::late_implicit_early::<'static, 'static, 'static>(S, &0); @@ -150,7 +150,7 @@ note: the late bound lifetime parameter is introduced here LL | fn late_implicit_early<'b>(self, _: &u8) -> &'b u8 { loop {} } | ^ -error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present +error[E0794]: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present --> $DIR/method-call-lifetime-args-fail.rs:52:35 | LL | S::late_implicit_self_early::<'static, 'static>(&S); @@ -162,7 +162,7 @@ note: the late bound lifetime parameter is introduced here LL | fn late_implicit_self_early<'b>(&self) -> &'b u8 { loop {} } | ^ -error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present +error[E0794]: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present --> $DIR/method-call-lifetime-args-fail.rs:54:35 | LL | S::late_implicit_self_early::<'static, 'static, 'static>(&S); @@ -174,7 +174,7 @@ note: the late bound lifetime parameter is introduced here LL | fn late_implicit_self_early<'b>(&self) -> &'b u8 { loop {} } | ^ -error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present +error[E0794]: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present --> $DIR/method-call-lifetime-args-fail.rs:57:28 | LL | S::late_unused_early::<'static, 'static>(S); @@ -186,7 +186,7 @@ note: the late bound lifetime parameter is introduced here LL | fn late_unused_early<'a, 'b>(self) -> &'b u8 { loop {} } | ^^ -error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present +error[E0794]: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present --> $DIR/method-call-lifetime-args-fail.rs:59:28 | LL | S::late_unused_early::<'static, 'static, 'static>(S); @@ -232,4 +232,5 @@ LL | fn early<'a, 'b>(self) -> (&'a u8, &'b u8) { loop {} } error: aborting due to 18 previous errors -For more information about this error, try `rustc --explain E0107`. +Some errors have detailed explanations: E0107, E0794. +For more information about an error, try `rustc --explain E0107`. diff --git a/tests/ui/methods/method-call-lifetime-args.stderr b/tests/ui/methods/method-call-lifetime-args.stderr index 64ae79e9bb2b7..b215d5832171f 100644 --- a/tests/ui/methods/method-call-lifetime-args.stderr +++ b/tests/ui/methods/method-call-lifetime-args.stderr @@ -1,4 +1,4 @@ -error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present +error[E0794]: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present --> $DIR/method-call-lifetime-args.rs:9:15 | LL | S::late::<'static>(S, &0, &0); @@ -10,7 +10,7 @@ note: the late bound lifetime parameter is introduced here LL | fn late<'a, 'b>(self, _: &'a u8, _: &'b u8) {} | ^^ -error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present +error[E0794]: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present --> $DIR/method-call-lifetime-args.rs:11:24 | LL | S::late_implicit::<'static>(S, &0, &0); @@ -24,3 +24,4 @@ LL | fn late_implicit(self, _: &u8, _: &u8) {} error: aborting due to 2 previous errors +For more information about this error, try `rustc --explain E0794`. From 27b430bcb36e46cc5dcfd88ec6cec2639ad2467c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Mi=C4=85sko?= Date: Thu, 16 Mar 2023 00:00:00 +0000 Subject: [PATCH 02/14] Tweak implementation of overflow checking assertions Extract and reuse logic controlling behaviour of overflow checking assertions instead of duplicating it three times. --- compiler/rustc_codegen_cranelift/src/base.rs | 15 ++++----------- compiler/rustc_codegen_ssa/src/mir/block.rs | 11 ++--------- .../rustc_const_eval/src/interpret/machine.rs | 4 ++-- .../src/interpret/terminator.rs | 8 ++------ compiler/rustc_middle/src/mir/mod.rs | 17 +++++++---------- compiler/rustc_middle/src/mir/syntax.rs | 3 +-- src/tools/miri/src/machine.rs | 2 +- 7 files changed, 19 insertions(+), 41 deletions(-) diff --git a/compiler/rustc_codegen_cranelift/src/base.rs b/compiler/rustc_codegen_cranelift/src/base.rs index d0af3729b237c..1b8e9312e2f58 100644 --- a/compiler/rustc_codegen_cranelift/src/base.rs +++ b/compiler/rustc_codegen_cranelift/src/base.rs @@ -346,17 +346,10 @@ fn codegen_fn_body(fx: &mut FunctionCx<'_, '_, '_>, start_block: Block) { crate::abi::codegen_return(fx); } TerminatorKind::Assert { cond, expected, msg, target, cleanup: _ } => { - if !fx.tcx.sess.overflow_checks() { - let overflow_not_to_check = match msg { - AssertKind::OverflowNeg(..) => true, - AssertKind::Overflow(op, ..) => op.is_checkable(), - _ => false, - }; - if overflow_not_to_check { - let target = fx.get_block(*target); - fx.bcx.ins().jump(target, &[]); - continue; - } + if !fx.tcx.sess.overflow_checks() && msg.is_optional_overflow_check() { + let target = fx.get_block(*target); + fx.bcx.ins().jump(target, &[]); + continue; } let cond = codegen_operand(fx, cond).load_scalar(fx); diff --git a/compiler/rustc_codegen_ssa/src/mir/block.rs b/compiler/rustc_codegen_ssa/src/mir/block.rs index 71c71d59b7ab9..f9aa2aecf65bc 100644 --- a/compiler/rustc_codegen_ssa/src/mir/block.rs +++ b/compiler/rustc_codegen_ssa/src/mir/block.rs @@ -563,15 +563,8 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { // with #[rustc_inherit_overflow_checks] and inlined from // another crate (mostly core::num generic/#[inline] fns), // while the current crate doesn't use overflow checks. - if !bx.cx().check_overflow() { - let overflow_not_to_check = match msg { - AssertKind::OverflowNeg(..) => true, - AssertKind::Overflow(op, ..) => op.is_checkable(), - _ => false, - }; - if overflow_not_to_check { - const_cond = Some(expected); - } + if !bx.cx().check_overflow() && msg.is_optional_overflow_check() { + const_cond = Some(expected); } // Don't codegen the panic block if success if known. diff --git a/compiler/rustc_const_eval/src/interpret/machine.rs b/compiler/rustc_const_eval/src/interpret/machine.rs index 92fa59aec6e5f..c134d3a6b2f2a 100644 --- a/compiler/rustc_const_eval/src/interpret/machine.rs +++ b/compiler/rustc_const_eval/src/interpret/machine.rs @@ -155,7 +155,7 @@ pub trait Machine<'mir, 'tcx>: Sized { /// Whether Assert(OverflowNeg) and Assert(Overflow) MIR terminators should actually /// check for overflow. - fn ignore_checkable_overflow_assertions(_ecx: &InterpCx<'mir, 'tcx, Self>) -> bool; + fn ignore_optional_overflow_checks(_ecx: &InterpCx<'mir, 'tcx, Self>) -> bool; /// Entry point for obtaining the MIR of anything that should get evaluated. /// So not just functions and shims, but also const/static initializers, anonymous @@ -474,7 +474,7 @@ pub macro compile_time_machine(<$mir: lifetime, $tcx: lifetime>) { } #[inline(always)] - fn ignore_checkable_overflow_assertions(_ecx: &InterpCx<$mir, $tcx, Self>) -> bool { + fn ignore_optional_overflow_checks(_ecx: &InterpCx<$mir, $tcx, Self>) -> bool { false } diff --git a/compiler/rustc_const_eval/src/interpret/terminator.rs b/compiler/rustc_const_eval/src/interpret/terminator.rs index 685a5599cdedf..c2d1bc11c37b5 100644 --- a/compiler/rustc_const_eval/src/interpret/terminator.rs +++ b/compiler/rustc_const_eval/src/interpret/terminator.rs @@ -138,12 +138,8 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { } Assert { ref cond, expected, ref msg, target, cleanup } => { - let ignored = M::ignore_checkable_overflow_assertions(self) - && match msg { - mir::AssertKind::OverflowNeg(..) => true, - mir::AssertKind::Overflow(op, ..) => op.is_checkable(), - _ => false, - }; + let ignored = + M::ignore_optional_overflow_checks(self) && msg.is_optional_overflow_check(); let cond_val = self.read_scalar(&self.eval_operand(cond, None)?)?.to_bool()?; if ignored || expected == cond_val { self.go_to_block(target); diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs index b34651c3ea797..3b26eb8a8ed3b 100644 --- a/compiler/rustc_middle/src/mir/mod.rs +++ b/compiler/rustc_middle/src/mir/mod.rs @@ -1274,6 +1274,13 @@ impl<'tcx> BasicBlockData<'tcx> { } impl AssertKind { + /// Returns true if this an overflow checking assertion controlled by -C overflow-checks. + pub fn is_optional_overflow_check(&self) -> bool { + use AssertKind::*; + use BinOp::*; + matches!(self, OverflowNeg(..) | Overflow(Add | Sub | Mul | Shl | Shr, ..)) + } + /// Getting a description does not require `O` to be printable, and does not /// require allocation. /// The caller is expected to handle `BoundsCheck` separately. @@ -1998,16 +2005,6 @@ impl BorrowKind { } } -impl BinOp { - /// The checkable operators are those whose overflow checking behavior is controlled by - /// -Coverflow-checks option. The remaining operators have either no overflow conditions (e.g., - /// BitAnd, BitOr, BitXor) or are always checked for overflow (e.g., Div, Rem). - pub fn is_checkable(self) -> bool { - use self::BinOp::*; - matches!(self, Add | Sub | Mul | Shl | Shr) - } -} - impl<'tcx> Debug for Rvalue<'tcx> { fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result { use self::Rvalue::*; diff --git a/compiler/rustc_middle/src/mir/syntax.rs b/compiler/rustc_middle/src/mir/syntax.rs index a28ecfa9bdc47..b16b6616415aa 100644 --- a/compiler/rustc_middle/src/mir/syntax.rs +++ b/compiler/rustc_middle/src/mir/syntax.rs @@ -646,8 +646,7 @@ pub enum TerminatorKind<'tcx> { /// When overflow checking is disabled and this is run-time MIR (as opposed to compile-time MIR /// that is used for CTFE), the following variants of this terminator behave as `goto target`: /// - `OverflowNeg(..)`, - /// - `Overflow(op, ..)` if op is a "checkable" operation (add, sub, mul, shl, shr, but NOT - /// div or rem). + /// - `Overflow(op, ..)` if op is add, sub, mul, shl, shr, but NOT div or rem. Assert { cond: Operand<'tcx>, expected: bool, diff --git a/src/tools/miri/src/machine.rs b/src/tools/miri/src/machine.rs index 969c81f7e32be..3a14704d9cc4a 100644 --- a/src/tools/miri/src/machine.rs +++ b/src/tools/miri/src/machine.rs @@ -822,7 +822,7 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for MiriMachine<'mir, 'tcx> { } #[inline(always)] - fn ignore_checkable_overflow_assertions(ecx: &MiriInterpCx<'mir, 'tcx>) -> bool { + fn ignore_optional_overflow_checks(ecx: &MiriInterpCx<'mir, 'tcx>) -> bool { !ecx.tcx.sess.overflow_checks() } From c7cc1c7442bc09e3c1a37f737790994c1084ad2a Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Thu, 16 Mar 2023 19:35:27 -0300 Subject: [PATCH 03/14] Fix generics mismatch errors for RPITITs on -Zlower-impl-trait-in-trait-to-assoc-ty --- .../src/check/compare_impl_item.rs | 11 +++++++++++ ...match.stderr => generics-mismatch.current.stderr} | 2 +- .../in-trait/generics-mismatch.next.stderr | 12 ++++++++++++ tests/ui/impl-trait/in-trait/generics-mismatch.rs | 3 +++ 4 files changed, 27 insertions(+), 1 deletion(-) rename tests/ui/impl-trait/in-trait/{generics-mismatch.stderr => generics-mismatch.current.stderr} (90%) create mode 100644 tests/ui/impl-trait/in-trait/generics-mismatch.next.stderr diff --git a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs index 6e6f8c1533bfe..32b6aeed5f8cc 100644 --- a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs +++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs @@ -1205,6 +1205,17 @@ fn compare_number_of_generics<'tcx>( return Ok(()); } + // We never need to emit a separate error for RPITITs, since if an RPITIT + // has mismatched type or const generic arguments, then the method that it's + // inheriting the generics from will also have mismatched arguments, and + // we'll report an error for that instead. Delay a bug for safety, though. + if tcx.opt_rpitit_info(trait_.def_id).is_some() { + return Err(tcx.sess.delay_span_bug( + rustc_span::DUMMY_SP, + "errors comparing numbers of generics of trait/impl functions were not emitted", + )); + } + let matchings = [ ("type", trait_own_counts.types, impl_own_counts.types), ("const", trait_own_counts.consts, impl_own_counts.consts), diff --git a/tests/ui/impl-trait/in-trait/generics-mismatch.stderr b/tests/ui/impl-trait/in-trait/generics-mismatch.current.stderr similarity index 90% rename from tests/ui/impl-trait/in-trait/generics-mismatch.stderr rename to tests/ui/impl-trait/in-trait/generics-mismatch.current.stderr index cd42683e0224d..310edbcb6cd1e 100644 --- a/tests/ui/impl-trait/in-trait/generics-mismatch.stderr +++ b/tests/ui/impl-trait/in-trait/generics-mismatch.current.stderr @@ -1,5 +1,5 @@ error[E0049]: method `bar` has 1 type parameter but its trait declaration has 0 type parameters - --> $DIR/generics-mismatch.rs:11:12 + --> $DIR/generics-mismatch.rs:14:12 | LL | fn bar(&self) -> impl Sized; | - expected 0 type parameters diff --git a/tests/ui/impl-trait/in-trait/generics-mismatch.next.stderr b/tests/ui/impl-trait/in-trait/generics-mismatch.next.stderr new file mode 100644 index 0000000000000..310edbcb6cd1e --- /dev/null +++ b/tests/ui/impl-trait/in-trait/generics-mismatch.next.stderr @@ -0,0 +1,12 @@ +error[E0049]: method `bar` has 1 type parameter but its trait declaration has 0 type parameters + --> $DIR/generics-mismatch.rs:14:12 + | +LL | fn bar(&self) -> impl Sized; + | - expected 0 type parameters +... +LL | fn bar(&self) {} + | ^ found 1 type parameter + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0049`. diff --git a/tests/ui/impl-trait/in-trait/generics-mismatch.rs b/tests/ui/impl-trait/in-trait/generics-mismatch.rs index cc0fc720ebbfd..9259ca193d1de 100644 --- a/tests/ui/impl-trait/in-trait/generics-mismatch.rs +++ b/tests/ui/impl-trait/in-trait/generics-mismatch.rs @@ -1,3 +1,6 @@ +// [next] compile-flags: -Zlower-impl-trait-in-trait-to-assoc-ty +// revisions: current next + #![feature(return_position_impl_trait_in_trait)] #![allow(incomplete_features)] From ae7fa1d269a3346372562570da3c51625027097b Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Thu, 16 Mar 2023 20:41:24 -0300 Subject: [PATCH 04/14] Add generic parameters mismatch test for async in traits --- .../ui/async-await/in-trait/generics-mismatch.rs | 15 +++++++++++++++ .../in-trait/generics-mismatch.stderr | 16 ++++++++++++++++ 2 files changed, 31 insertions(+) create mode 100644 tests/ui/async-await/in-trait/generics-mismatch.rs create mode 100644 tests/ui/async-await/in-trait/generics-mismatch.stderr diff --git a/tests/ui/async-await/in-trait/generics-mismatch.rs b/tests/ui/async-await/in-trait/generics-mismatch.rs new file mode 100644 index 0000000000000..fc29783c0e32e --- /dev/null +++ b/tests/ui/async-await/in-trait/generics-mismatch.rs @@ -0,0 +1,15 @@ +// edition: 2021 + +#![feature(async_fn_in_trait)] +#![allow(incomplete_features)] + +trait Foo { + async fn foo(); +} + +impl Foo for () { + async fn foo() {} + //~^ ERROR: method `foo` has an incompatible generic parameter for trait `Foo` [E0053] +} + +fn main() {} diff --git a/tests/ui/async-await/in-trait/generics-mismatch.stderr b/tests/ui/async-await/in-trait/generics-mismatch.stderr new file mode 100644 index 0000000000000..3518aa05cecc2 --- /dev/null +++ b/tests/ui/async-await/in-trait/generics-mismatch.stderr @@ -0,0 +1,16 @@ +error[E0053]: method `foo` has an incompatible generic parameter for trait `Foo` + --> $DIR/generics-mismatch.rs:11:18 + | +LL | trait Foo { + | --- +LL | async fn foo(); + | - expected type parameter +... +LL | impl Foo for () { + | --------------- +LL | async fn foo() {} + | ^^^^^^^^^^^^^^ found const parameter of type `usize` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0053`. From e0302bbc3bbecd172447f1105f586be3c35e043b Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Thu, 16 Mar 2023 16:29:01 -0300 Subject: [PATCH 05/14] Add revisions for -Zlower-impl-trait-in-trait-to-assoc-ty fixed tests --- .../async-await/async-trait-fn.current.stderr | 42 ++++++++ .../ui/async-await/async-trait-fn.next.stderr | 42 ++++++++ tests/ui/async-await/async-trait-fn.rs | 1 + tests/ui/async-await/async-trait-fn.stderr | 6 +- ...dition-deny-async-fns-2015.current.stderr} | 20 ++-- .../edition-deny-async-fns-2015.next.stderr | 98 +++++++++++++++++++ .../edition-deny-async-fns-2015.rs | 2 + .../in-trait/generics-mismatch.current.stderr | 16 +++ .../in-trait/generics-mismatch.next.stderr | 16 +++ .../async-await/in-trait/generics-mismatch.rs | 15 +++ .../in-trait/generics-mismatch.stderr | 16 +++ ... => return-type-suggestion.current.stderr} | 4 +- .../return-type-suggestion.next.stderr | 23 +++++ .../in-trait/return-type-suggestion.rs | 2 + ... => default-body-with-rpit.current.stderr} | 6 +- .../default-body-with-rpit.next.stderr | 24 +++++ .../in-trait/default-body-with-rpit.rs | 2 + ...y.stderr => doesnt-satisfy.current.stderr} | 4 +- .../in-trait/doesnt-satisfy.next.stderr | 17 ++++ .../ui/impl-trait/in-trait/doesnt-satisfy.rs | 3 + 20 files changed, 339 insertions(+), 20 deletions(-) create mode 100644 tests/ui/async-await/async-trait-fn.current.stderr create mode 100644 tests/ui/async-await/async-trait-fn.next.stderr rename tests/ui/async-await/{edition-deny-async-fns-2015.stderr => edition-deny-async-fns-2015.current.stderr} (87%) create mode 100644 tests/ui/async-await/edition-deny-async-fns-2015.next.stderr create mode 100644 tests/ui/async-await/in-trait/generics-mismatch.current.stderr create mode 100644 tests/ui/async-await/in-trait/generics-mismatch.next.stderr create mode 100644 tests/ui/async-await/in-trait/generics-mismatch.rs create mode 100644 tests/ui/async-await/in-trait/generics-mismatch.stderr rename tests/ui/async-await/in-trait/{return-type-suggestion.stderr => return-type-suggestion.current.stderr} (89%) create mode 100644 tests/ui/async-await/in-trait/return-type-suggestion.next.stderr rename tests/ui/impl-trait/in-trait/{default-body-with-rpit.stderr => default-body-with-rpit.current.stderr} (82%) create mode 100644 tests/ui/impl-trait/in-trait/default-body-with-rpit.next.stderr rename tests/ui/impl-trait/in-trait/{doesnt-satisfy.stderr => doesnt-satisfy.current.stderr} (90%) create mode 100644 tests/ui/impl-trait/in-trait/doesnt-satisfy.next.stderr diff --git a/tests/ui/async-await/async-trait-fn.current.stderr b/tests/ui/async-await/async-trait-fn.current.stderr new file mode 100644 index 0000000000000..7ccf2f2301d24 --- /dev/null +++ b/tests/ui/async-await/async-trait-fn.current.stderr @@ -0,0 +1,42 @@ +error[E0706]: functions in traits cannot be declared `async` + --> $DIR/async-trait-fn.rs:6:5 + | +LL | async fn foo() {} + | -----^^^^^^^^^ + | | + | `async` because of this + | + = note: `async` trait functions are not currently supported + = note: consider using the `async-trait` crate: https://crates.io/crates/async-trait + = note: see issue #91611 for more information + = help: add `#![feature(async_fn_in_trait)]` to the crate attributes to enable + +error[E0706]: functions in traits cannot be declared `async` + --> $DIR/async-trait-fn.rs:7:5 + | +LL | async fn bar(&self) {} + | -----^^^^^^^^^^^^^^ + | | + | `async` because of this + | + = note: `async` trait functions are not currently supported + = note: consider using the `async-trait` crate: https://crates.io/crates/async-trait + = note: see issue #91611 for more information + = help: add `#![feature(async_fn_in_trait)]` to the crate attributes to enable + +error[E0706]: functions in traits cannot be declared `async` + --> $DIR/async-trait-fn.rs:8:5 + | +LL | async fn baz() { + | -----^^^^^^^^^ + | | + | `async` because of this + | + = note: `async` trait functions are not currently supported + = note: consider using the `async-trait` crate: https://crates.io/crates/async-trait + = note: see issue #91611 for more information + = help: add `#![feature(async_fn_in_trait)]` to the crate attributes to enable + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0706`. diff --git a/tests/ui/async-await/async-trait-fn.next.stderr b/tests/ui/async-await/async-trait-fn.next.stderr new file mode 100644 index 0000000000000..7ccf2f2301d24 --- /dev/null +++ b/tests/ui/async-await/async-trait-fn.next.stderr @@ -0,0 +1,42 @@ +error[E0706]: functions in traits cannot be declared `async` + --> $DIR/async-trait-fn.rs:6:5 + | +LL | async fn foo() {} + | -----^^^^^^^^^ + | | + | `async` because of this + | + = note: `async` trait functions are not currently supported + = note: consider using the `async-trait` crate: https://crates.io/crates/async-trait + = note: see issue #91611 for more information + = help: add `#![feature(async_fn_in_trait)]` to the crate attributes to enable + +error[E0706]: functions in traits cannot be declared `async` + --> $DIR/async-trait-fn.rs:7:5 + | +LL | async fn bar(&self) {} + | -----^^^^^^^^^^^^^^ + | | + | `async` because of this + | + = note: `async` trait functions are not currently supported + = note: consider using the `async-trait` crate: https://crates.io/crates/async-trait + = note: see issue #91611 for more information + = help: add `#![feature(async_fn_in_trait)]` to the crate attributes to enable + +error[E0706]: functions in traits cannot be declared `async` + --> $DIR/async-trait-fn.rs:8:5 + | +LL | async fn baz() { + | -----^^^^^^^^^ + | | + | `async` because of this + | + = note: `async` trait functions are not currently supported + = note: consider using the `async-trait` crate: https://crates.io/crates/async-trait + = note: see issue #91611 for more information + = help: add `#![feature(async_fn_in_trait)]` to the crate attributes to enable + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0706`. diff --git a/tests/ui/async-await/async-trait-fn.rs b/tests/ui/async-await/async-trait-fn.rs index e2062e82725c0..04123badb5383 100644 --- a/tests/ui/async-await/async-trait-fn.rs +++ b/tests/ui/async-await/async-trait-fn.rs @@ -1,4 +1,5 @@ // edition:2018 + trait T { async fn foo() {} //~ ERROR functions in traits cannot be declared `async` async fn bar(&self) {} //~ ERROR functions in traits cannot be declared `async` diff --git a/tests/ui/async-await/async-trait-fn.stderr b/tests/ui/async-await/async-trait-fn.stderr index afbe25cf7ab74..68ebe3507ac35 100644 --- a/tests/ui/async-await/async-trait-fn.stderr +++ b/tests/ui/async-await/async-trait-fn.stderr @@ -1,5 +1,5 @@ error[E0706]: functions in traits cannot be declared `async` - --> $DIR/async-trait-fn.rs:3:5 + --> $DIR/async-trait-fn.rs:4:5 | LL | async fn foo() {} | -----^^^^^^^^^ @@ -12,7 +12,7 @@ LL | async fn foo() {} = help: add `#![feature(async_fn_in_trait)]` to the crate attributes to enable error[E0706]: functions in traits cannot be declared `async` - --> $DIR/async-trait-fn.rs:4:5 + --> $DIR/async-trait-fn.rs:5:5 | LL | async fn bar(&self) {} | -----^^^^^^^^^^^^^^ @@ -25,7 +25,7 @@ LL | async fn bar(&self) {} = help: add `#![feature(async_fn_in_trait)]` to the crate attributes to enable error[E0706]: functions in traits cannot be declared `async` - --> $DIR/async-trait-fn.rs:5:5 + --> $DIR/async-trait-fn.rs:6:5 | LL | async fn baz() { | -----^^^^^^^^^ diff --git a/tests/ui/async-await/edition-deny-async-fns-2015.stderr b/tests/ui/async-await/edition-deny-async-fns-2015.current.stderr similarity index 87% rename from tests/ui/async-await/edition-deny-async-fns-2015.stderr rename to tests/ui/async-await/edition-deny-async-fns-2015.current.stderr index ba918eb28def1..c47b99e657e14 100644 --- a/tests/ui/async-await/edition-deny-async-fns-2015.stderr +++ b/tests/ui/async-await/edition-deny-async-fns-2015.current.stderr @@ -1,5 +1,5 @@ error[E0670]: `async fn` is not permitted in Rust 2015 - --> $DIR/edition-deny-async-fns-2015.rs:3:1 + --> $DIR/edition-deny-async-fns-2015.rs:5:1 | LL | async fn foo() {} | ^^^^^ to use `async fn`, switch to Rust 2018 or later @@ -8,7 +8,7 @@ LL | async fn foo() {} = note: for more on editions, read https://doc.rust-lang.org/edition-guide error[E0670]: `async fn` is not permitted in Rust 2015 - --> $DIR/edition-deny-async-fns-2015.rs:5:12 + --> $DIR/edition-deny-async-fns-2015.rs:7:12 | LL | fn baz() { async fn foo() {} } | ^^^^^ to use `async fn`, switch to Rust 2018 or later @@ -17,7 +17,7 @@ LL | fn baz() { async fn foo() {} } = note: for more on editions, read https://doc.rust-lang.org/edition-guide error[E0670]: `async fn` is not permitted in Rust 2015 - --> $DIR/edition-deny-async-fns-2015.rs:7:1 + --> $DIR/edition-deny-async-fns-2015.rs:9:1 | LL | async fn async_baz() { | ^^^^^ to use `async fn`, switch to Rust 2018 or later @@ -26,7 +26,7 @@ LL | async fn async_baz() { = note: for more on editions, read https://doc.rust-lang.org/edition-guide error[E0670]: `async fn` is not permitted in Rust 2015 - --> $DIR/edition-deny-async-fns-2015.rs:8:5 + --> $DIR/edition-deny-async-fns-2015.rs:10:5 | LL | async fn bar() {} | ^^^^^ to use `async fn`, switch to Rust 2018 or later @@ -35,7 +35,7 @@ LL | async fn bar() {} = note: for more on editions, read https://doc.rust-lang.org/edition-guide error[E0670]: `async fn` is not permitted in Rust 2015 - --> $DIR/edition-deny-async-fns-2015.rs:14:5 + --> $DIR/edition-deny-async-fns-2015.rs:16:5 | LL | async fn foo() {} | ^^^^^ to use `async fn`, switch to Rust 2018 or later @@ -44,7 +44,7 @@ LL | async fn foo() {} = note: for more on editions, read https://doc.rust-lang.org/edition-guide error[E0670]: `async fn` is not permitted in Rust 2015 - --> $DIR/edition-deny-async-fns-2015.rs:18:5 + --> $DIR/edition-deny-async-fns-2015.rs:20:5 | LL | async fn foo() {} | ^^^^^ to use `async fn`, switch to Rust 2018 or later @@ -53,7 +53,7 @@ LL | async fn foo() {} = note: for more on editions, read https://doc.rust-lang.org/edition-guide error[E0670]: `async fn` is not permitted in Rust 2015 - --> $DIR/edition-deny-async-fns-2015.rs:36:9 + --> $DIR/edition-deny-async-fns-2015.rs:38:9 | LL | async fn bar() {} | ^^^^^ to use `async fn`, switch to Rust 2018 or later @@ -62,7 +62,7 @@ LL | async fn bar() {} = note: for more on editions, read https://doc.rust-lang.org/edition-guide error[E0670]: `async fn` is not permitted in Rust 2015 - --> $DIR/edition-deny-async-fns-2015.rs:26:9 + --> $DIR/edition-deny-async-fns-2015.rs:28:9 | LL | async fn foo() {} | ^^^^^ to use `async fn`, switch to Rust 2018 or later @@ -71,7 +71,7 @@ LL | async fn foo() {} = note: for more on editions, read https://doc.rust-lang.org/edition-guide error[E0670]: `async fn` is not permitted in Rust 2015 - --> $DIR/edition-deny-async-fns-2015.rs:31:13 + --> $DIR/edition-deny-async-fns-2015.rs:33:13 | LL | async fn bar() {} | ^^^^^ to use `async fn`, switch to Rust 2018 or later @@ -80,7 +80,7 @@ LL | async fn bar() {} = note: for more on editions, read https://doc.rust-lang.org/edition-guide error[E0706]: functions in traits cannot be declared `async` - --> $DIR/edition-deny-async-fns-2015.rs:18:5 + --> $DIR/edition-deny-async-fns-2015.rs:20:5 | LL | async fn foo() {} | -----^^^^^^^^^ diff --git a/tests/ui/async-await/edition-deny-async-fns-2015.next.stderr b/tests/ui/async-await/edition-deny-async-fns-2015.next.stderr new file mode 100644 index 0000000000000..c47b99e657e14 --- /dev/null +++ b/tests/ui/async-await/edition-deny-async-fns-2015.next.stderr @@ -0,0 +1,98 @@ +error[E0670]: `async fn` is not permitted in Rust 2015 + --> $DIR/edition-deny-async-fns-2015.rs:5:1 + | +LL | async fn foo() {} + | ^^^^^ to use `async fn`, switch to Rust 2018 or later + | + = help: pass `--edition 2021` to `rustc` + = note: for more on editions, read https://doc.rust-lang.org/edition-guide + +error[E0670]: `async fn` is not permitted in Rust 2015 + --> $DIR/edition-deny-async-fns-2015.rs:7:12 + | +LL | fn baz() { async fn foo() {} } + | ^^^^^ to use `async fn`, switch to Rust 2018 or later + | + = help: pass `--edition 2021` to `rustc` + = note: for more on editions, read https://doc.rust-lang.org/edition-guide + +error[E0670]: `async fn` is not permitted in Rust 2015 + --> $DIR/edition-deny-async-fns-2015.rs:9:1 + | +LL | async fn async_baz() { + | ^^^^^ to use `async fn`, switch to Rust 2018 or later + | + = help: pass `--edition 2021` to `rustc` + = note: for more on editions, read https://doc.rust-lang.org/edition-guide + +error[E0670]: `async fn` is not permitted in Rust 2015 + --> $DIR/edition-deny-async-fns-2015.rs:10:5 + | +LL | async fn bar() {} + | ^^^^^ to use `async fn`, switch to Rust 2018 or later + | + = help: pass `--edition 2021` to `rustc` + = note: for more on editions, read https://doc.rust-lang.org/edition-guide + +error[E0670]: `async fn` is not permitted in Rust 2015 + --> $DIR/edition-deny-async-fns-2015.rs:16:5 + | +LL | async fn foo() {} + | ^^^^^ to use `async fn`, switch to Rust 2018 or later + | + = help: pass `--edition 2021` to `rustc` + = note: for more on editions, read https://doc.rust-lang.org/edition-guide + +error[E0670]: `async fn` is not permitted in Rust 2015 + --> $DIR/edition-deny-async-fns-2015.rs:20:5 + | +LL | async fn foo() {} + | ^^^^^ to use `async fn`, switch to Rust 2018 or later + | + = help: pass `--edition 2021` to `rustc` + = note: for more on editions, read https://doc.rust-lang.org/edition-guide + +error[E0670]: `async fn` is not permitted in Rust 2015 + --> $DIR/edition-deny-async-fns-2015.rs:38:9 + | +LL | async fn bar() {} + | ^^^^^ to use `async fn`, switch to Rust 2018 or later + | + = help: pass `--edition 2021` to `rustc` + = note: for more on editions, read https://doc.rust-lang.org/edition-guide + +error[E0670]: `async fn` is not permitted in Rust 2015 + --> $DIR/edition-deny-async-fns-2015.rs:28:9 + | +LL | async fn foo() {} + | ^^^^^ to use `async fn`, switch to Rust 2018 or later + | + = help: pass `--edition 2021` to `rustc` + = note: for more on editions, read https://doc.rust-lang.org/edition-guide + +error[E0670]: `async fn` is not permitted in Rust 2015 + --> $DIR/edition-deny-async-fns-2015.rs:33:13 + | +LL | async fn bar() {} + | ^^^^^ to use `async fn`, switch to Rust 2018 or later + | + = help: pass `--edition 2021` to `rustc` + = note: for more on editions, read https://doc.rust-lang.org/edition-guide + +error[E0706]: functions in traits cannot be declared `async` + --> $DIR/edition-deny-async-fns-2015.rs:20:5 + | +LL | async fn foo() {} + | -----^^^^^^^^^ + | | + | `async` because of this + | + = note: `async` trait functions are not currently supported + = note: consider using the `async-trait` crate: https://crates.io/crates/async-trait + = note: see issue #91611 for more information + = help: add `#![feature(async_fn_in_trait)]` to the crate attributes to enable + +error: aborting due to 10 previous errors + +Some errors have detailed explanations: E0670, E0706. +For more information about an error, try `rustc --explain E0670`. diff --git a/tests/ui/async-await/edition-deny-async-fns-2015.rs b/tests/ui/async-await/edition-deny-async-fns-2015.rs index 6bd6d879a4ace..d4c30dc9d828d 100644 --- a/tests/ui/async-await/edition-deny-async-fns-2015.rs +++ b/tests/ui/async-await/edition-deny-async-fns-2015.rs @@ -1,4 +1,6 @@ // edition:2015 +// [next] compile-flags: -Zlower-impl-trait-in-trait-to-assoc-ty +// revisions: current next async fn foo() {} //~ ERROR `async fn` is not permitted in Rust 2015 diff --git a/tests/ui/async-await/in-trait/generics-mismatch.current.stderr b/tests/ui/async-await/in-trait/generics-mismatch.current.stderr new file mode 100644 index 0000000000000..be23384e049da --- /dev/null +++ b/tests/ui/async-await/in-trait/generics-mismatch.current.stderr @@ -0,0 +1,16 @@ +error[E0053]: method `foo` has an incompatible generic parameter for trait `Foo` + --> $DIR/generics-mismatch.rs:13:18 + | +LL | trait Foo { + | --- +LL | async fn foo(); + | - expected type parameter +... +LL | impl Foo for () { + | --------------- +LL | async fn foo() {} + | ^^^^^^^^^^^^^^ found const parameter of type `usize` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0053`. diff --git a/tests/ui/async-await/in-trait/generics-mismatch.next.stderr b/tests/ui/async-await/in-trait/generics-mismatch.next.stderr new file mode 100644 index 0000000000000..be23384e049da --- /dev/null +++ b/tests/ui/async-await/in-trait/generics-mismatch.next.stderr @@ -0,0 +1,16 @@ +error[E0053]: method `foo` has an incompatible generic parameter for trait `Foo` + --> $DIR/generics-mismatch.rs:13:18 + | +LL | trait Foo { + | --- +LL | async fn foo(); + | - expected type parameter +... +LL | impl Foo for () { + | --------------- +LL | async fn foo() {} + | ^^^^^^^^^^^^^^ found const parameter of type `usize` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0053`. diff --git a/tests/ui/async-await/in-trait/generics-mismatch.rs b/tests/ui/async-await/in-trait/generics-mismatch.rs new file mode 100644 index 0000000000000..fc29783c0e32e --- /dev/null +++ b/tests/ui/async-await/in-trait/generics-mismatch.rs @@ -0,0 +1,15 @@ +// edition: 2021 + +#![feature(async_fn_in_trait)] +#![allow(incomplete_features)] + +trait Foo { + async fn foo(); +} + +impl Foo for () { + async fn foo() {} + //~^ ERROR: method `foo` has an incompatible generic parameter for trait `Foo` [E0053] +} + +fn main() {} diff --git a/tests/ui/async-await/in-trait/generics-mismatch.stderr b/tests/ui/async-await/in-trait/generics-mismatch.stderr new file mode 100644 index 0000000000000..3518aa05cecc2 --- /dev/null +++ b/tests/ui/async-await/in-trait/generics-mismatch.stderr @@ -0,0 +1,16 @@ +error[E0053]: method `foo` has an incompatible generic parameter for trait `Foo` + --> $DIR/generics-mismatch.rs:11:18 + | +LL | trait Foo { + | --- +LL | async fn foo(); + | - expected type parameter +... +LL | impl Foo for () { + | --------------- +LL | async fn foo() {} + | ^^^^^^^^^^^^^^ found const parameter of type `usize` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0053`. diff --git a/tests/ui/async-await/in-trait/return-type-suggestion.stderr b/tests/ui/async-await/in-trait/return-type-suggestion.current.stderr similarity index 89% rename from tests/ui/async-await/in-trait/return-type-suggestion.stderr rename to tests/ui/async-await/in-trait/return-type-suggestion.current.stderr index b8d83d0f28a31..a5efc75715656 100644 --- a/tests/ui/async-await/in-trait/return-type-suggestion.stderr +++ b/tests/ui/async-await/in-trait/return-type-suggestion.current.stderr @@ -1,5 +1,5 @@ warning: the feature `async_fn_in_trait` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/return-type-suggestion.rs:3:12 + --> $DIR/return-type-suggestion.rs:5:12 | LL | #![feature(async_fn_in_trait)] | ^^^^^^^^^^^^^^^^^ @@ -8,7 +8,7 @@ LL | #![feature(async_fn_in_trait)] = note: `#[warn(incomplete_features)]` on by default error[E0308]: mismatched types - --> $DIR/return-type-suggestion.rs:8:9 + --> $DIR/return-type-suggestion.rs:10:9 | LL | Ok(()) | ^^^^^^- help: consider using a semicolon here: `;` diff --git a/tests/ui/async-await/in-trait/return-type-suggestion.next.stderr b/tests/ui/async-await/in-trait/return-type-suggestion.next.stderr new file mode 100644 index 0000000000000..a5efc75715656 --- /dev/null +++ b/tests/ui/async-await/in-trait/return-type-suggestion.next.stderr @@ -0,0 +1,23 @@ +warning: the feature `async_fn_in_trait` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/return-type-suggestion.rs:5:12 + | +LL | #![feature(async_fn_in_trait)] + | ^^^^^^^^^^^^^^^^^ + | + = note: see issue #91611 for more information + = note: `#[warn(incomplete_features)]` on by default + +error[E0308]: mismatched types + --> $DIR/return-type-suggestion.rs:10:9 + | +LL | Ok(()) + | ^^^^^^- help: consider using a semicolon here: `;` + | | + | expected `()`, found `Result<(), _>` + | + = note: expected unit type `()` + found enum `Result<(), _>` + +error: aborting due to previous error; 1 warning emitted + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/async-await/in-trait/return-type-suggestion.rs b/tests/ui/async-await/in-trait/return-type-suggestion.rs index 3446761d119da..3de66306d9ab8 100644 --- a/tests/ui/async-await/in-trait/return-type-suggestion.rs +++ b/tests/ui/async-await/in-trait/return-type-suggestion.rs @@ -1,4 +1,6 @@ // edition: 2021 +// [next] compile-flags: -Zlower-impl-trait-in-trait-to-assoc-ty +// revisions: current next #![feature(async_fn_in_trait)] //~^ WARN the feature `async_fn_in_trait` is incomplete and may not be safe to use and/or cause compiler crashes diff --git a/tests/ui/impl-trait/in-trait/default-body-with-rpit.stderr b/tests/ui/impl-trait/in-trait/default-body-with-rpit.current.stderr similarity index 82% rename from tests/ui/impl-trait/in-trait/default-body-with-rpit.stderr rename to tests/ui/impl-trait/in-trait/default-body-with-rpit.current.stderr index b5fc9d44d3687..3c24eff9ae301 100644 --- a/tests/ui/impl-trait/in-trait/default-body-with-rpit.stderr +++ b/tests/ui/impl-trait/in-trait/default-body-with-rpit.current.stderr @@ -1,11 +1,11 @@ error: concrete type differs from previous defining opaque type use - --> $DIR/default-body-with-rpit.rs:11:9 + --> $DIR/default-body-with-rpit.rs:13:9 | LL | "" | ^^ expected `impl Debug`, got `&'static str` | note: previous use here - --> $DIR/default-body-with-rpit.rs:10:39 + --> $DIR/default-body-with-rpit.rs:12:39 | LL | async fn baz(&self) -> impl Debug { | _______________________________________^ @@ -14,7 +14,7 @@ LL | | } | |_____^ error[E0720]: cannot resolve opaque type - --> $DIR/default-body-with-rpit.rs:10:28 + --> $DIR/default-body-with-rpit.rs:12:28 | LL | async fn baz(&self) -> impl Debug { | ^^^^^^^^^^ cannot resolve opaque type diff --git a/tests/ui/impl-trait/in-trait/default-body-with-rpit.next.stderr b/tests/ui/impl-trait/in-trait/default-body-with-rpit.next.stderr new file mode 100644 index 0000000000000..3c24eff9ae301 --- /dev/null +++ b/tests/ui/impl-trait/in-trait/default-body-with-rpit.next.stderr @@ -0,0 +1,24 @@ +error: concrete type differs from previous defining opaque type use + --> $DIR/default-body-with-rpit.rs:13:9 + | +LL | "" + | ^^ expected `impl Debug`, got `&'static str` + | +note: previous use here + --> $DIR/default-body-with-rpit.rs:12:39 + | +LL | async fn baz(&self) -> impl Debug { + | _______________________________________^ +LL | | "" +LL | | } + | |_____^ + +error[E0720]: cannot resolve opaque type + --> $DIR/default-body-with-rpit.rs:12:28 + | +LL | async fn baz(&self) -> impl Debug { + | ^^^^^^^^^^ cannot resolve opaque type + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0720`. diff --git a/tests/ui/impl-trait/in-trait/default-body-with-rpit.rs b/tests/ui/impl-trait/in-trait/default-body-with-rpit.rs index 0558d95128f4a..6bcc7b9ef95f0 100644 --- a/tests/ui/impl-trait/in-trait/default-body-with-rpit.rs +++ b/tests/ui/impl-trait/in-trait/default-body-with-rpit.rs @@ -1,5 +1,7 @@ // edition:2021 // known-bug: #108304 +// [next] compile-flags: -Zlower-impl-trait-in-trait-to-assoc-ty +// revisions: current next #![feature(async_fn_in_trait, return_position_impl_trait_in_trait)] #![allow(incomplete_features)] diff --git a/tests/ui/impl-trait/in-trait/doesnt-satisfy.stderr b/tests/ui/impl-trait/in-trait/doesnt-satisfy.current.stderr similarity index 90% rename from tests/ui/impl-trait/in-trait/doesnt-satisfy.stderr rename to tests/ui/impl-trait/in-trait/doesnt-satisfy.current.stderr index aa5492d285ed6..653016cf009a9 100644 --- a/tests/ui/impl-trait/in-trait/doesnt-satisfy.stderr +++ b/tests/ui/impl-trait/in-trait/doesnt-satisfy.current.stderr @@ -1,5 +1,5 @@ error[E0277]: `()` doesn't implement `std::fmt::Display` - --> $DIR/doesnt-satisfy.rs:9:17 + --> $DIR/doesnt-satisfy.rs:12:17 | LL | fn bar() -> () {} | ^^ `()` cannot be formatted with the default formatter @@ -7,7 +7,7 @@ LL | fn bar() -> () {} = help: the trait `std::fmt::Display` is not implemented for `()` = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead note: required by a bound in `Foo::bar::{opaque#0}` - --> $DIR/doesnt-satisfy.rs:5:22 + --> $DIR/doesnt-satisfy.rs:8:22 | LL | fn bar() -> impl std::fmt::Display; | ^^^^^^^^^^^^^^^^^ required by this bound in `Foo::bar::{opaque#0}` diff --git a/tests/ui/impl-trait/in-trait/doesnt-satisfy.next.stderr b/tests/ui/impl-trait/in-trait/doesnt-satisfy.next.stderr new file mode 100644 index 0000000000000..bbfa089ceef92 --- /dev/null +++ b/tests/ui/impl-trait/in-trait/doesnt-satisfy.next.stderr @@ -0,0 +1,17 @@ +error[E0277]: `()` doesn't implement `std::fmt::Display` + --> $DIR/doesnt-satisfy.rs:12:17 + | +LL | fn bar() -> () {} + | ^^ `()` cannot be formatted with the default formatter + | + = help: the trait `std::fmt::Display` is not implemented for `()` + = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead +note: required by a bound in `Foo::{opaque#0}` + --> $DIR/doesnt-satisfy.rs:8:22 + | +LL | fn bar() -> impl std::fmt::Display; + | ^^^^^^^^^^^^^^^^^ required by this bound in `Foo::` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/impl-trait/in-trait/doesnt-satisfy.rs b/tests/ui/impl-trait/in-trait/doesnt-satisfy.rs index bb4e0d44f3eff..fcd0b51eea4fc 100644 --- a/tests/ui/impl-trait/in-trait/doesnt-satisfy.rs +++ b/tests/ui/impl-trait/in-trait/doesnt-satisfy.rs @@ -1,3 +1,6 @@ +// [next] compile-flags: -Zlower-impl-trait-in-trait-to-assoc-ty +// revisions: current next + #![feature(return_position_impl_trait_in_trait)] #![allow(incomplete_features)] From 8628e27da34f8b64ce4a02a6f2e74a6c4016612f Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Fri, 17 Mar 2023 15:29:47 -0700 Subject: [PATCH 06/14] rustdoc: reduce allocations in `visibility_to_src_with_space` --- src/librustdoc/html/format.rs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs index 27010b771d33b..d526a8be0811a 100644 --- a/src/librustdoc/html/format.rs +++ b/src/librustdoc/html/format.rs @@ -1502,9 +1502,9 @@ pub(crate) fn visibility_to_src_with_space<'a, 'tcx: 'a>( tcx: TyCtxt<'tcx>, item_did: DefId, ) -> impl fmt::Display + 'a + Captures<'tcx> { - let to_print = match visibility { - None => String::new(), - Some(ty::Visibility::Public) => "pub ".to_owned(), + let to_print: Cow<'static, str> = match visibility { + None => "".into(), + Some(ty::Visibility::Public) => "pub ".into(), Some(ty::Visibility::Restricted(vis_did)) => { // FIXME(camelid): This may not work correctly if `item_did` is a module. // However, rustdoc currently never displays a module's @@ -1512,17 +1512,17 @@ pub(crate) fn visibility_to_src_with_space<'a, 'tcx: 'a>( let parent_module = find_nearest_parent_module(tcx, item_did); if vis_did.is_crate_root() { - "pub(crate) ".to_owned() + "pub(crate) ".into() } else if parent_module == Some(vis_did) { // `pub(in foo)` where `foo` is the parent module // is the same as no visibility modifier - String::new() + "".into() } else if parent_module.and_then(|parent| find_nearest_parent_module(tcx, parent)) == Some(vis_did) { - "pub(super) ".to_owned() + "pub(super) ".into() } else { - format!("pub(in {}) ", tcx.def_path_str(vis_did)) + format!("pub(in {}) ", tcx.def_path_str(vis_did)).into() } } }; From 35088797aec481a9549d5d495b27ce9f1e3a39dd Mon Sep 17 00:00:00 2001 From: Scott McMurray Date: Fri, 17 Mar 2023 19:29:23 -0700 Subject: [PATCH 07/14] Use `size_of_val` instead of manual calculation Very minor thing that I happened to notice in passing, but it's both shorter and means it gets `mul nuw`, so why not. --- compiler/rustc_codegen_ssa/src/glue.rs | 2 +- library/core/src/hash/mod.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_codegen_ssa/src/glue.rs b/compiler/rustc_codegen_ssa/src/glue.rs index 0f6e6032f9bff..c34f1dbf8569d 100644 --- a/compiler/rustc_codegen_ssa/src/glue.rs +++ b/compiler/rustc_codegen_ssa/src/glue.rs @@ -46,7 +46,7 @@ pub fn size_and_align_of_dst<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( // NOTE: ideally, we want the effects of both `unchecked_smul` and `unchecked_umul` // (resulting in `mul nsw nuw` in LLVM IR), since we know that the multiplication // cannot signed wrap, and that both operands are non-negative. But at the time of writing, - // `BuilderMethods` can't do this, and it doesn't seem to enable any further optimizations. + // the `LLVM-C` binding can't do this, and it doesn't seem to enable any further optimizations. bx.unchecked_smul(info.unwrap(), bx.const_usize(unit.size.bytes())), bx.const_usize(unit.align.abi.bytes()), ) diff --git a/library/core/src/hash/mod.rs b/library/core/src/hash/mod.rs index 71a0d1825efec..540831c825335 100644 --- a/library/core/src/hash/mod.rs +++ b/library/core/src/hash/mod.rs @@ -834,7 +834,7 @@ mod impls { #[inline] fn hash_slice(data: &[$ty], state: &mut H) { - let newlen = data.len() * mem::size_of::<$ty>(); + let newlen = mem::size_of_val(data); let ptr = data.as_ptr() as *const u8; // SAFETY: `ptr` is valid and aligned, as this macro is only used // for numeric primitives which have no padding. The new slice only From a3f3db842df11849d7060eaa8c2b50d3e49bed03 Mon Sep 17 00:00:00 2001 From: John Millikin Date: Sat, 18 Mar 2023 12:22:53 +0900 Subject: [PATCH 08/14] Stabilise `unix_socket_abstract` Fixes https://github.com/rust-lang/rust/issues/85410 --- library/std/src/os/android/net.rs | 4 ++-- library/std/src/os/linux/net.rs | 4 ++-- library/std/src/os/net/linux_ext/addr.rs | 6 +++--- library/std/src/os/net/linux_ext/mod.rs | 2 +- library/std/src/os/unix/net/addr.rs | 4 ++-- library/std/src/os/unix/net/datagram.rs | 9 +++------ library/std/src/os/unix/net/listener.rs | 3 +-- library/std/src/os/unix/net/stream.rs | 3 +-- 8 files changed, 15 insertions(+), 20 deletions(-) diff --git a/library/std/src/os/android/net.rs b/library/std/src/os/android/net.rs index 7cecd1bbfaa95..4e88ab8ff5c52 100644 --- a/library/std/src/os/android/net.rs +++ b/library/std/src/os/android/net.rs @@ -1,8 +1,8 @@ //! Android-specific networking functionality. -#![unstable(feature = "tcp_quickack", issue = "96256")] +#![stable(feature = "unix_socket_abstract", since = "CURRENT_RUSTC_VERSION")] -#[unstable(feature = "unix_socket_abstract", issue = "85410")] +#[stable(feature = "unix_socket_abstract", since = "CURRENT_RUSTC_VERSION")] pub use crate::os::net::linux_ext::addr::SocketAddrExt; #[unstable(feature = "tcp_quickack", issue = "96256")] diff --git a/library/std/src/os/linux/net.rs b/library/std/src/os/linux/net.rs index 94081c8dd31c5..fcb3bb8348558 100644 --- a/library/std/src/os/linux/net.rs +++ b/library/std/src/os/linux/net.rs @@ -1,8 +1,8 @@ //! Linux-specific networking functionality. -#![unstable(feature = "tcp_quickack", issue = "96256")] +#![stable(feature = "unix_socket_abstract", since = "CURRENT_RUSTC_VERSION")] -#[unstable(feature = "unix_socket_abstract", issue = "85410")] +#[stable(feature = "unix_socket_abstract", since = "CURRENT_RUSTC_VERSION")] pub use crate::os::net::linux_ext::addr::SocketAddrExt; #[unstable(feature = "tcp_quickack", issue = "96256")] diff --git a/library/std/src/os/net/linux_ext/addr.rs b/library/std/src/os/net/linux_ext/addr.rs index 85065984fbbb1..ea8102c9cc0af 100644 --- a/library/std/src/os/net/linux_ext/addr.rs +++ b/library/std/src/os/net/linux_ext/addr.rs @@ -4,7 +4,7 @@ use crate::os::unix::net::SocketAddr; use crate::sealed::Sealed; /// Platform-specific extensions to [`SocketAddr`]. -#[unstable(feature = "unix_socket_abstract", issue = "85410")] +#[stable(feature = "unix_socket_abstract", since = "CURRENT_RUSTC_VERSION")] pub trait SocketAddrExt: Sealed { /// Creates a Unix socket address in the abstract namespace. /// @@ -22,7 +22,6 @@ pub trait SocketAddrExt: Sealed { /// # Examples /// /// ```no_run - /// #![feature(unix_socket_abstract)] /// use std::os::unix::net::{UnixListener, SocketAddr}; /// use std::os::linux::net::SocketAddrExt; /// @@ -38,6 +37,7 @@ pub trait SocketAddrExt: Sealed { /// Ok(()) /// } /// ``` + #[stable(feature = "unix_socket_abstract", since = "CURRENT_RUSTC_VERSION")] fn from_abstract_name(name: N) -> crate::io::Result where N: AsRef<[u8]>; @@ -47,7 +47,6 @@ pub trait SocketAddrExt: Sealed { /// # Examples /// /// ```no_run - /// #![feature(unix_socket_abstract)] /// use std::os::unix::net::{UnixListener, SocketAddr}; /// use std::os::linux::net::SocketAddrExt; /// @@ -60,5 +59,6 @@ pub trait SocketAddrExt: Sealed { /// Ok(()) /// } /// ``` + #[stable(feature = "unix_socket_abstract", since = "CURRENT_RUSTC_VERSION")] fn as_abstract_name(&self) -> Option<&[u8]>; } diff --git a/library/std/src/os/net/linux_ext/mod.rs b/library/std/src/os/net/linux_ext/mod.rs index 318ebacfd7a08..e7423dce6135b 100644 --- a/library/std/src/os/net/linux_ext/mod.rs +++ b/library/std/src/os/net/linux_ext/mod.rs @@ -2,7 +2,7 @@ #![doc(cfg(any(target_os = "linux", target_os = "android")))] -#[unstable(feature = "unix_socket_abstract", issue = "85410")] +#[stable(feature = "unix_socket_abstract", since = "CURRENT_RUSTC_VERSION")] pub(crate) mod addr; #[unstable(feature = "tcp_quickack", issue = "96256")] diff --git a/library/std/src/os/unix/net/addr.rs b/library/std/src/os/unix/net/addr.rs index ece2b33bddf36..52a0da5bf1a65 100644 --- a/library/std/src/os/unix/net/addr.rs +++ b/library/std/src/os/unix/net/addr.rs @@ -245,12 +245,12 @@ impl SocketAddr { } } -#[unstable(feature = "unix_socket_abstract", issue = "85410")] +#[stable(feature = "unix_socket_abstract", since = "CURRENT_RUSTC_VERSION")] impl Sealed for SocketAddr {} #[doc(cfg(any(target_os = "android", target_os = "linux")))] #[cfg(any(doc, target_os = "android", target_os = "linux"))] -#[unstable(feature = "unix_socket_abstract", issue = "85410")] +#[stable(feature = "unix_socket_abstract", since = "CURRENT_RUSTC_VERSION")] impl linux_ext::addr::SocketAddrExt for SocketAddr { fn as_abstract_name(&self) -> Option<&[u8]> { if let AddressKind::Abstract(name) = self.address() { Some(name) } else { None } diff --git a/library/std/src/os/unix/net/datagram.rs b/library/std/src/os/unix/net/datagram.rs index 272b4f5dcd5ad..e64569758a04a 100644 --- a/library/std/src/os/unix/net/datagram.rs +++ b/library/std/src/os/unix/net/datagram.rs @@ -102,7 +102,6 @@ impl UnixDatagram { /// # Examples /// /// ```no_run - /// #![feature(unix_socket_abstract)] /// use std::os::unix::net::{UnixDatagram}; /// /// fn main() -> std::io::Result<()> { @@ -119,7 +118,7 @@ impl UnixDatagram { /// Ok(()) /// } /// ``` - #[unstable(feature = "unix_socket_abstract", issue = "85410")] + #[stable(feature = "unix_socket_abstract", since = "CURRENT_RUSTC_VERSION")] pub fn bind_addr(socket_addr: &SocketAddr) -> io::Result { unsafe { let socket = UnixDatagram::unbound()?; @@ -217,7 +216,6 @@ impl UnixDatagram { /// # Examples /// /// ```no_run - /// #![feature(unix_socket_abstract)] /// use std::os::unix::net::{UnixDatagram}; /// /// fn main() -> std::io::Result<()> { @@ -235,7 +233,7 @@ impl UnixDatagram { /// Ok(()) /// } /// ``` - #[unstable(feature = "unix_socket_abstract", issue = "85410")] + #[stable(feature = "unix_socket_abstract", since = "CURRENT_RUSTC_VERSION")] pub fn connect_addr(&self, socket_addr: &SocketAddr) -> io::Result<()> { unsafe { cvt(libc::connect( @@ -523,7 +521,6 @@ impl UnixDatagram { /// # Examples /// /// ```no_run - /// #![feature(unix_socket_abstract)] /// use std::os::unix::net::{UnixDatagram}; /// /// fn main() -> std::io::Result<()> { @@ -535,7 +532,7 @@ impl UnixDatagram { /// Ok(()) /// } /// ``` - #[unstable(feature = "unix_socket_abstract", issue = "85410")] + #[stable(feature = "unix_socket_abstract", since = "CURRENT_RUSTC_VERSION")] pub fn send_to_addr(&self, buf: &[u8], socket_addr: &SocketAddr) -> io::Result { unsafe { let count = cvt(libc::sendto( diff --git a/library/std/src/os/unix/net/listener.rs b/library/std/src/os/unix/net/listener.rs index 02090afc82f7e..83f0debe6765a 100644 --- a/library/std/src/os/unix/net/listener.rs +++ b/library/std/src/os/unix/net/listener.rs @@ -90,7 +90,6 @@ impl UnixListener { /// # Examples /// /// ```no_run - /// #![feature(unix_socket_abstract)] /// use std::os::unix::net::{UnixListener}; /// /// fn main() -> std::io::Result<()> { @@ -107,7 +106,7 @@ impl UnixListener { /// Ok(()) /// } /// ``` - #[unstable(feature = "unix_socket_abstract", issue = "85410")] + #[stable(feature = "unix_socket_abstract", since = "CURRENT_RUSTC_VERSION")] pub fn bind_addr(socket_addr: &SocketAddr) -> io::Result { unsafe { let inner = Socket::new_raw(libc::AF_UNIX, libc::SOCK_STREAM)?; diff --git a/library/std/src/os/unix/net/stream.rs b/library/std/src/os/unix/net/stream.rs index dff8f6e856750..65cb4ae07a504 100644 --- a/library/std/src/os/unix/net/stream.rs +++ b/library/std/src/os/unix/net/stream.rs @@ -106,7 +106,6 @@ impl UnixStream { /// # Examples /// /// ```no_run - /// #![feature(unix_socket_abstract)] /// use std::os::unix::net::{UnixListener, UnixStream}; /// /// fn main() -> std::io::Result<()> { @@ -123,7 +122,7 @@ impl UnixStream { /// Ok(()) /// } /// ```` - #[unstable(feature = "unix_socket_abstract", issue = "85410")] + #[stable(feature = "unix_socket_abstract", since = "CURRENT_RUSTC_VERSION")] pub fn connect_addr(socket_addr: &SocketAddr) -> io::Result { unsafe { let inner = Socket::new_raw(libc::AF_UNIX, libc::SOCK_STREAM)?; From c76e260fa7b8318216dac0f78fe008ce1e0f8684 Mon Sep 17 00:00:00 2001 From: Joshua Nelson Date: Sun, 5 Mar 2023 07:21:41 -0600 Subject: [PATCH 09/14] Use named threads in tidy This makes it easier to profile. --- src/tools/tidy/src/main.rs | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/src/tools/tidy/src/main.rs b/src/tools/tidy/src/main.rs index d98758ace4fc8..ced1c02401523 100644 --- a/src/tools/tidy/src/main.rs +++ b/src/tools/tidy/src/main.rs @@ -13,7 +13,7 @@ use std::path::PathBuf; use std::process; use std::str::FromStr; use std::sync::atomic::{AtomicBool, Ordering}; -use std::thread::{scope, ScopedJoinHandle}; +use std::thread::{self, scope, ScopedJoinHandle}; fn main() { let root_path: PathBuf = env::args_os().nth(1).expect("need path to root of repo").into(); @@ -55,16 +55,28 @@ fn main() { VecDeque::with_capacity(concurrency.get()); macro_rules! check { - ($p:ident $(, $args:expr)* ) => { + ($p:ident) => { + check!(@ $p, name=format!("{}", stringify!($p))); + }; + ($p:ident, $path:expr $(, $args:expr)* ) => { + let shortened = $path.strip_prefix(&root_path).unwrap(); + let name = if shortened == std::path::Path::new("") { + format!("{} (.)", stringify!($p)) + } else { + format!("{} ({})", stringify!($p), shortened.display()) + }; + check!(@ $p, name=name, $path $(,$args)*); + }; + (@ $p:ident, name=$name:expr $(, $args:expr)* ) => { drain_handles(&mut handles); - let handle = s.spawn(|| { + let handle = thread::Builder::new().name($name).spawn_scoped(s, || { let mut flag = false; $p::check($($args, )* &mut flag); if (flag) { bad.store(true, Ordering::Relaxed); } - }); + }).unwrap(); handles.push_back(handle); } } From 9b606a3203da5141f4922ef405ef0d1b9bf0b8bf Mon Sep 17 00:00:00 2001 From: Joshua Nelson Date: Sun, 5 Mar 2023 06:45:07 -0600 Subject: [PATCH 10/14] Speed up file walking in tidy - Skip files in `skip` wherever possible to avoid reading their contents - Don't look for `tidy-alphabetic-start` in tests. It's never currently used and slows the check down a lot. - Add new `filter_not_rust` helper function --- src/tools/tidy/src/debug_artifacts.rs | 12 +-- src/tools/tidy/src/features.rs | 17 ++-- src/tools/tidy/src/main.rs | 1 - src/tools/tidy/src/style.rs | 26 ++--- src/tools/tidy/src/target_specific_tests.rs | 100 ++++++++++---------- src/tools/tidy/src/walk.rs | 7 +- 6 files changed, 80 insertions(+), 83 deletions(-) diff --git a/src/tools/tidy/src/debug_artifacts.rs b/src/tools/tidy/src/debug_artifacts.rs index 2241375eaae11..84b133068055b 100644 --- a/src/tools/tidy/src/debug_artifacts.rs +++ b/src/tools/tidy/src/debug_artifacts.rs @@ -1,21 +1,15 @@ //! Tidy check to prevent creation of unnecessary debug artifacts while running tests. -use crate::walk::{filter_dirs, walk}; +use crate::walk::{filter_dirs, filter_not_rust, walk}; use std::path::Path; const GRAPHVIZ_POSTFLOW_MSG: &str = "`borrowck_graphviz_postflow` attribute in test"; pub fn check(test_dir: &Path, bad: &mut bool) { - walk(test_dir, filter_dirs, &mut |entry, contents| { - let filename = entry.path(); - let is_rust = filename.extension().map_or(false, |ext| ext == "rs"); - if !is_rust { - return; - } - + walk(test_dir, |path| filter_dirs(path) || filter_not_rust(path), &mut |entry, contents| { for (i, line) in contents.lines().enumerate() { if line.contains("borrowck_graphviz_postflow") { - tidy_error!(bad, "{}:{}: {}", filename.display(), i + 1, GRAPHVIZ_POSTFLOW_MSG); + tidy_error!(bad, "{}:{}: {}", entry.path().display(), i + 1, GRAPHVIZ_POSTFLOW_MSG); } } }); diff --git a/src/tools/tidy/src/features.rs b/src/tools/tidy/src/features.rs index 6d94417a10f1d..f18feda533c9c 100644 --- a/src/tools/tidy/src/features.rs +++ b/src/tools/tidy/src/features.rs @@ -9,8 +9,9 @@ //! * All unstable lang features have tests to ensure they are actually unstable. //! * Language features in a group are sorted by feature name. -use crate::walk::{filter_dirs, walk, walk_many}; +use crate::walk::{filter_dirs, filter_not_rust, walk, walk_many}; use std::collections::hash_map::{Entry, HashMap}; +use std::ffi::OsStr; use std::fmt; use std::fs; use std::num::NonZeroU32; @@ -101,17 +102,15 @@ pub fn check( &tests_path.join("rustdoc-ui"), &tests_path.join("rustdoc"), ], - filter_dirs, + |path| { + filter_dirs(path) + || filter_not_rust(path) + || path.file_name() == Some(OsStr::new("features.rs")) + || path.file_name() == Some(OsStr::new("diagnostic_list.rs")) + }, &mut |entry, contents| { let file = entry.path(); let filename = file.file_name().unwrap().to_string_lossy(); - if !filename.ends_with(".rs") - || filename == "features.rs" - || filename == "diagnostic_list.rs" - { - return; - } - let filen_underscore = filename.replace('-', "_").replace(".rs", ""); let filename_is_gate_test = test_filen_gate(&filen_underscore, &mut features); diff --git a/src/tools/tidy/src/main.rs b/src/tools/tidy/src/main.rs index ced1c02401523..f59406c404bab 100644 --- a/src/tools/tidy/src/main.rs +++ b/src/tools/tidy/src/main.rs @@ -120,7 +120,6 @@ fn main() { check!(edition, &library_path); check!(alphabetical, &src_path); - check!(alphabetical, &tests_path); check!(alphabetical, &compiler_path); check!(alphabetical, &library_path); diff --git a/src/tools/tidy/src/style.rs b/src/tools/tidy/src/style.rs index 75a4586cb7f1c..e3f04840bc71b 100644 --- a/src/tools/tidy/src/style.rs +++ b/src/tools/tidy/src/style.rs @@ -19,7 +19,7 @@ use crate::walk::{filter_dirs, walk}; use regex::{Regex, RegexSet}; -use std::path::Path; +use std::{ffi::OsStr, path::Path}; /// Error code markdown is restricted to 80 columns because they can be /// displayed on the console with --example. @@ -228,21 +228,28 @@ fn is_unexplained_ignore(extension: &str, line: &str) -> bool { pub fn check(path: &Path, bad: &mut bool) { fn skip(path: &Path) -> bool { - filter_dirs(path) || skip_markdown_path(path) + if filter_dirs(path) || skip_markdown_path(path) { + return true; + } + + let extensions = ["rs", "py", "js", "sh", "c", "cpp", "h", "md", "css", "ftl", "goml"]; + if extensions.iter().all(|e| path.extension() != Some(OsStr::new(e))) { + return true; + } + + // We only check CSS files in rustdoc. + path.extension().map_or(false, |e| e == "css") && !is_in(path, "src", "librustdoc") } + let problematic_consts_strings: Vec = (PROBLEMATIC_CONSTS.iter().map(u32::to_string)) .chain(PROBLEMATIC_CONSTS.iter().map(|v| format!("{:x}", v))) .chain(PROBLEMATIC_CONSTS.iter().map(|v| format!("{:X}", v))) .collect(); let problematic_regex = RegexSet::new(problematic_consts_strings.as_slice()).unwrap(); + walk(path, skip, &mut |entry, contents| { let file = entry.path(); let filename = file.file_name().unwrap().to_string_lossy(); - let extensions = - [".rs", ".py", ".js", ".sh", ".c", ".cpp", ".h", ".md", ".css", ".ftl", ".goml"]; - if extensions.iter().all(|e| !filename.ends_with(e)) || filename.starts_with(".#") { - return; - } let is_style_file = filename.ends_with(".css"); let under_rustfmt = filename.ends_with(".rs") && @@ -253,11 +260,6 @@ pub fn check(path: &Path, bad: &mut bool) { a.ends_with("src/doc/book") }); - if is_style_file && !is_in(file, "src", "librustdoc") { - // We only check CSS files in rustdoc. - return; - } - if contents.is_empty() { tidy_error!(bad, "{}: empty file", file.display()); } diff --git a/src/tools/tidy/src/target_specific_tests.rs b/src/tools/tidy/src/target_specific_tests.rs index f41fa4fcce1b5..e0fa6aceb853c 100644 --- a/src/tools/tidy/src/target_specific_tests.rs +++ b/src/tools/tidy/src/target_specific_tests.rs @@ -4,6 +4,8 @@ use std::collections::BTreeMap; use std::path::Path; +use crate::walk::filter_not_rust; + const COMMENT: &str = "//"; const LLVM_COMPONENTS_HEADER: &str = "needs-llvm-components:"; const COMPILE_FLAGS_HEADER: &str = "compile-flags:"; @@ -35,61 +37,57 @@ struct RevisionInfo<'a> { } pub fn check(path: &Path, bad: &mut bool) { - crate::walk::walk( - path, - |path| path.extension().map(|p| p == "rs") == Some(false), - &mut |entry, content| { - let file = entry.path().display(); - let mut header_map = BTreeMap::new(); - iter_header(content, &mut |cfg, directive| { - if let Some(value) = directive.strip_prefix(LLVM_COMPONENTS_HEADER) { - let info = header_map.entry(cfg).or_insert(RevisionInfo::default()); - let comp_vec = info.llvm_components.get_or_insert(Vec::new()); - for component in value.split(' ') { - let component = component.trim(); - if !component.is_empty() { - comp_vec.push(component); - } - } - } else if directive.starts_with(COMPILE_FLAGS_HEADER) { - let compile_flags = &directive[COMPILE_FLAGS_HEADER.len()..]; - if let Some((_, v)) = compile_flags.split_once("--target") { - if let Some((arch, _)) = - v.trim_start_matches(|c| c == ' ' || c == '=').split_once("-") - { - let info = header_map.entry(cfg).or_insert(RevisionInfo::default()); - info.target_arch.replace(arch); - } else { - eprintln!("{file}: seems to have a malformed --target value"); - *bad = true; - } + crate::walk::walk(path, filter_not_rust, &mut |entry, content| { + let file = entry.path().display(); + let mut header_map = BTreeMap::new(); + iter_header(content, &mut |cfg, directive| { + if let Some(value) = directive.strip_prefix(LLVM_COMPONENTS_HEADER) { + let info = header_map.entry(cfg).or_insert(RevisionInfo::default()); + let comp_vec = info.llvm_components.get_or_insert(Vec::new()); + for component in value.split(' ') { + let component = component.trim(); + if !component.is_empty() { + comp_vec.push(component); } } - }); - for (rev, RevisionInfo { target_arch, llvm_components }) in &header_map { - let rev = rev.unwrap_or("[unspecified]"); - match (target_arch, llvm_components) { - (None, None) => {} - (Some(_), None) => { - eprintln!( - "{}: revision {} should specify `{}` as it has `--target` set", - file, rev, LLVM_COMPONENTS_HEADER - ); + } else if directive.starts_with(COMPILE_FLAGS_HEADER) { + let compile_flags = &directive[COMPILE_FLAGS_HEADER.len()..]; + if let Some((_, v)) = compile_flags.split_once("--target") { + if let Some((arch, _)) = + v.trim_start_matches(|c| c == ' ' || c == '=').split_once("-") + { + let info = header_map.entry(cfg).or_insert(RevisionInfo::default()); + info.target_arch.replace(arch); + } else { + eprintln!("{file}: seems to have a malformed --target value"); *bad = true; } - (None, Some(_)) => { - eprintln!( - "{}: revision {} should not specify `{}` as it doesn't need `--target`", - file, rev, LLVM_COMPONENTS_HEADER - ); - *bad = true; - } - (Some(_), Some(_)) => { - // FIXME: check specified components against the target architectures we - // gathered. - } } } - }, - ); + }); + for (rev, RevisionInfo { target_arch, llvm_components }) in &header_map { + let rev = rev.unwrap_or("[unspecified]"); + match (target_arch, llvm_components) { + (None, None) => {} + (Some(_), None) => { + eprintln!( + "{}: revision {} should specify `{}` as it has `--target` set", + file, rev, LLVM_COMPONENTS_HEADER + ); + *bad = true; + } + (None, Some(_)) => { + eprintln!( + "{}: revision {} should not specify `{}` as it doesn't need `--target`", + file, rev, LLVM_COMPONENTS_HEADER + ); + *bad = true; + } + (Some(_), Some(_)) => { + // FIXME: check specified components against the target architectures we + // gathered. + } + } + } + }); } diff --git a/src/tools/tidy/src/walk.rs b/src/tools/tidy/src/walk.rs index 94152e75168f9..90cd62531d0c2 100644 --- a/src/tools/tidy/src/walk.rs +++ b/src/tools/tidy/src/walk.rs @@ -1,6 +1,6 @@ use ignore::DirEntry; -use std::{fs::File, io::Read, path::Path}; +use std::{ffi::OsStr, fs::File, io::Read, path::Path}; /// The default directory filter. pub fn filter_dirs(path: &Path) -> bool { @@ -33,6 +33,11 @@ pub fn filter_dirs(path: &Path) -> bool { skip.iter().any(|p| path.ends_with(p)) } +/// Filter for only files that end in `.rs`. +pub fn filter_not_rust(path: &Path) -> bool { + !path.is_dir() && path.extension() != Some(OsStr::new("rs")) +} + pub fn walk_many( paths: &[&Path], skip: impl Clone + Send + Sync + 'static + Fn(&Path) -> bool, From d26a15563d34c3c77788e48d880d1c39d3770fb3 Mon Sep 17 00:00:00 2001 From: Joshua Nelson Date: Sun, 5 Mar 2023 07:37:44 -0600 Subject: [PATCH 11/14] Make `ui_tests` non-quadratic Previously, it would walk each directory twice: once in the main `Walk` iterator, and once to count the number of entries in the directory. Now it only walks each directory once. --- src/tools/tidy/src/ui_tests.rs | 64 ++++++++++++++++------------------ 1 file changed, 30 insertions(+), 34 deletions(-) diff --git a/src/tools/tidy/src/ui_tests.rs b/src/tools/tidy/src/ui_tests.rs index 15c36923e885f..ec8edf84ef38a 100644 --- a/src/tools/tidy/src/ui_tests.rs +++ b/src/tools/tidy/src/ui_tests.rs @@ -3,50 +3,46 @@ //! - there are no stray `.stderr` files use ignore::Walk; -use ignore::WalkBuilder; +use std::collections::HashMap; use std::fs; -use std::path::Path; +use std::path::{Path, PathBuf}; const ENTRY_LIMIT: usize = 1000; // FIXME: The following limits should be reduced eventually. const ROOT_ENTRY_LIMIT: usize = 940; const ISSUES_ENTRY_LIMIT: usize = 1978; -fn check_entries(path: &Path, bad: &mut bool) { - for dir in Walk::new(&path.join("ui")) { +fn check_entries(tests_path: &Path, bad: &mut bool) { + let mut directories: HashMap = HashMap::new(); + + for dir in Walk::new(&tests_path.join("ui")) { if let Ok(entry) = dir { - if entry.file_type().map(|ft| ft.is_dir()).unwrap_or(false) { - let dir_path = entry.path(); - // Use special values for these dirs. - let is_root = path.join("ui") == dir_path; - let is_issues_dir = path.join("ui/issues") == dir_path; - let limit = if is_root { - ROOT_ENTRY_LIMIT - } else if is_issues_dir { - ISSUES_ENTRY_LIMIT - } else { - ENTRY_LIMIT - }; + let parent = entry.path().parent().unwrap().to_path_buf(); + *directories.entry(parent).or_default() += 1; + } + } - let count = WalkBuilder::new(&dir_path) - .max_depth(Some(1)) - .build() - .into_iter() - .collect::>() - .len() - - 1; // remove the dir itself + for (dir_path, count) in directories { + // Use special values for these dirs. + let is_root = tests_path.join("ui") == dir_path; + let is_issues_dir = tests_path.join("ui/issues") == dir_path; + let limit = if is_root { + ROOT_ENTRY_LIMIT + } else if is_issues_dir { + ISSUES_ENTRY_LIMIT + } else { + ENTRY_LIMIT + }; - if count > limit { - tidy_error!( - bad, - "following path contains more than {} entries, \ - you should move the test to some relevant subdirectory (current: {}): {}", - limit, - count, - dir_path.display() - ); - } - } + if count > limit { + tidy_error!( + bad, + "following path contains more than {} entries, \ + you should move the test to some relevant subdirectory (current: {}): {}", + limit, + count, + dir_path.display() + ); } } } From 19b272a94b6f311affc86d721c34519299144681 Mon Sep 17 00:00:00 2001 From: Joshua Nelson Date: Sun, 5 Mar 2023 07:49:28 -0600 Subject: [PATCH 12/14] Use a single WalkBuilder for multiple paths --- src/tools/tidy/src/bins.rs | 2 +- src/tools/tidy/src/ui_tests.rs | 58 +++++++++++++++++----------------- src/tools/tidy/src/walk.rs | 25 ++++++++------- 3 files changed, 43 insertions(+), 42 deletions(-) diff --git a/src/tools/tidy/src/bins.rs b/src/tools/tidy/src/bins.rs index 2d6abe59343f2..070ce93f97c17 100644 --- a/src/tools/tidy/src/bins.rs +++ b/src/tools/tidy/src/bins.rs @@ -103,7 +103,7 @@ mod os_impl { // FIXME: we don't need to look at all binaries, only files that have been modified in this branch // (e.g. using `git ls-files`). - walk_no_read(path, |path| filter_dirs(path) || path.ends_with("src/etc"), &mut |entry| { + walk_no_read(&[path], |path| filter_dirs(path) || path.ends_with("src/etc"), &mut |entry| { let file = entry.path(); let extension = file.extension(); let scripts = ["py", "sh", "ps1"]; diff --git a/src/tools/tidy/src/ui_tests.rs b/src/tools/tidy/src/ui_tests.rs index ec8edf84ef38a..66f5c932be2a0 100644 --- a/src/tools/tidy/src/ui_tests.rs +++ b/src/tools/tidy/src/ui_tests.rs @@ -49,37 +49,37 @@ fn check_entries(tests_path: &Path, bad: &mut bool) { pub fn check(path: &Path, bad: &mut bool) { check_entries(&path, bad); - for path in &[&path.join("ui"), &path.join("ui-fulldeps")] { - crate::walk::walk_no_read(path, |_| false, &mut |entry| { - let file_path = entry.path(); - if let Some(ext) = file_path.extension() { - if ext == "stderr" || ext == "stdout" { - // Test output filenames have one of the formats: - // ``` - // $testname.stderr - // $testname.$mode.stderr - // $testname.$revision.stderr - // $testname.$revision.$mode.stderr - // ``` - // - // For now, just make sure that there is a corresponding - // `$testname.rs` file. - // - // NB: We do not use file_stem() as some file names have multiple `.`s and we - // must strip all of them. - let testname = - file_path.file_name().unwrap().to_str().unwrap().split_once('.').unwrap().0; - if !file_path.with_file_name(testname).with_extension("rs").exists() { - tidy_error!(bad, "Stray file with UI testing output: {:?}", file_path); - } + let (ui, ui_fulldeps) = (path.join("ui"), path.join("ui-fulldeps")); + let paths = [ui.as_path(), ui_fulldeps.as_path()]; + crate::walk::walk_no_read(&paths, |_| false, &mut |entry| { + let file_path = entry.path(); + if let Some(ext) = file_path.extension() { + if ext == "stderr" || ext == "stdout" { + // Test output filenames have one of the formats: + // ``` + // $testname.stderr + // $testname.$mode.stderr + // $testname.$revision.stderr + // $testname.$revision.$mode.stderr + // ``` + // + // For now, just make sure that there is a corresponding + // `$testname.rs` file. + // + // NB: We do not use file_stem() as some file names have multiple `.`s and we + // must strip all of them. + let testname = + file_path.file_name().unwrap().to_str().unwrap().split_once('.').unwrap().0; + if !file_path.with_file_name(testname).with_extension("rs").exists() { + tidy_error!(bad, "Stray file with UI testing output: {:?}", file_path); + } - if let Ok(metadata) = fs::metadata(file_path) { - if metadata.len() == 0 { - tidy_error!(bad, "Empty file with UI testing output: {:?}", file_path); - } + if let Ok(metadata) = fs::metadata(file_path) { + if metadata.len() == 0 { + tidy_error!(bad, "Empty file with UI testing output: {:?}", file_path); } } } - }); - } + } + }); } diff --git a/src/tools/tidy/src/walk.rs b/src/tools/tidy/src/walk.rs index 90cd62531d0c2..2ade22c209f5a 100644 --- a/src/tools/tidy/src/walk.rs +++ b/src/tools/tidy/src/walk.rs @@ -35,26 +35,24 @@ pub fn filter_dirs(path: &Path) -> bool { /// Filter for only files that end in `.rs`. pub fn filter_not_rust(path: &Path) -> bool { - !path.is_dir() && path.extension() != Some(OsStr::new("rs")) + path.extension() != Some(OsStr::new("rs")) && !path.is_dir() } -pub fn walk_many( - paths: &[&Path], +pub fn walk( + path: &Path, skip: impl Clone + Send + Sync + 'static + Fn(&Path) -> bool, f: &mut dyn FnMut(&DirEntry, &str), ) { - for path in paths { - walk(path, skip.clone(), f); - } + walk_many(&[path], skip, f); } -pub fn walk( - path: &Path, - skip: impl Send + Sync + 'static + Fn(&Path) -> bool, +pub fn walk_many( + paths: &[&Path], + skip: impl Clone + Send + Sync + 'static + Fn(&Path) -> bool, f: &mut dyn FnMut(&DirEntry, &str), ) { let mut contents = Vec::new(); - walk_no_read(path, skip, &mut |entry| { + walk_no_read(paths, skip, &mut |entry| { contents.clear(); let mut file = t!(File::open(entry.path()), entry.path()); t!(file.read_to_end(&mut contents), entry.path()); @@ -67,11 +65,14 @@ pub fn walk( } pub(crate) fn walk_no_read( - path: &Path, + paths: &[&Path], skip: impl Send + Sync + 'static + Fn(&Path) -> bool, f: &mut dyn FnMut(&DirEntry), ) { - let mut walker = ignore::WalkBuilder::new(path); + let mut walker = ignore::WalkBuilder::new(paths[0]); + for path in &paths[1..] { + walker.add(path); + } let walker = walker.filter_entry(move |e| !skip(e.path())); for entry in walker.build() { if let Ok(entry) = entry { From 3a58b2b3b065fcb367357482f636ce918d1080bd Mon Sep 17 00:00:00 2001 From: Joshua Nelson Date: Sun, 5 Mar 2023 07:59:36 -0600 Subject: [PATCH 13/14] Let tidy use more threads This has a significant speedup for me locally, from about 1.3 seconds to .9 seconds. --- src/bootstrap/test.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/bootstrap/test.rs b/src/bootstrap/test.rs index f5d680df1133b..baddc9da48db8 100644 --- a/src/bootstrap/test.rs +++ b/src/bootstrap/test.rs @@ -1118,7 +1118,11 @@ impl Step for Tidy { cmd.arg(&builder.src); cmd.arg(&builder.initial_cargo); cmd.arg(&builder.out); - cmd.arg(builder.jobs().to_string()); + // Tidy is heavily IO constrained. Still respect `-j`, but use a higher limit if `jobs` hasn't been configured. + let jobs = builder.config.jobs.unwrap_or_else(|| { + 8 * std::thread::available_parallelism().map_or(1, std::num::NonZeroUsize::get) as u32 + }); + cmd.arg(jobs.to_string()); if builder.is_verbose() { cmd.arg("--verbose"); } From 675c4aa2c1c142415d4e95bf550ec0b1de2493d0 Mon Sep 17 00:00:00 2001 From: Joshua Nelson Date: Sat, 18 Mar 2023 00:29:53 -0500 Subject: [PATCH 14/14] address review comments --- .gitignore | 1 + .../src/build/expr/as_rvalue.rs | 47 ++++++++++++++----- .../rustc_mir_build/src/build/matches/mod.rs | 4 +- compiler/rustc_mir_build/src/build/mod.rs | 19 ++++---- src/tools/tidy/src/style.rs | 5 ++ 5 files changed, 52 insertions(+), 24 deletions(-) diff --git a/.gitignore b/.gitignore index ce797a7a8371d..04d2597ecc696 100644 --- a/.gitignore +++ b/.gitignore @@ -42,6 +42,7 @@ no_llvm_build /llvm/ /mingw-build/ build/ +!/compiler/rustc_mir_build/src/build/ /build-rust-analyzer/ /dist/ /unicode-downloads diff --git a/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs b/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs index 9f48986b1ad80..140d1154718f7 100644 --- a/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs +++ b/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs @@ -73,19 +73,34 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { } ExprKind::Binary { op, lhs, rhs } => { let lhs = unpack!( - block = - this.as_operand(block, scope, &this.thir[lhs], LocalInfo::Boring, NeedsTemporary::Maybe) + block = this.as_operand( + block, + scope, + &this.thir[lhs], + LocalInfo::Boring, + NeedsTemporary::Maybe + ) ); let rhs = unpack!( - block = - this.as_operand(block, scope, &this.thir[rhs], LocalInfo::Boring, NeedsTemporary::No) + block = this.as_operand( + block, + scope, + &this.thir[rhs], + LocalInfo::Boring, + NeedsTemporary::No + ) ); this.build_binary_op(block, op, expr_span, expr.ty, lhs, rhs) } ExprKind::Unary { op, arg } => { let arg = unpack!( - block = - this.as_operand(block, scope, &this.thir[arg], LocalInfo::Boring, NeedsTemporary::No) + block = this.as_operand( + block, + scope, + &this.thir[arg], + LocalInfo::Boring, + NeedsTemporary::No + ) ); // Check for -MIN on signed integers if this.check_overflow && op == UnOp::Neg && expr.ty.is_signed() { @@ -272,8 +287,13 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { } ExprKind::Pointer { cast, source } => { let source = unpack!( - block = - this.as_operand(block, scope, &this.thir[source], LocalInfo::Boring, NeedsTemporary::No) + block = this.as_operand( + block, + scope, + &this.thir[source], + LocalInfo::Boring, + NeedsTemporary::No + ) ); block.and(Rvalue::Cast(CastKind::Pointer(cast), source, expr.ty)) } @@ -502,8 +522,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { Category::of(&expr.kind), Some(Category::Rvalue(RvalueFunc::AsRvalue) | Category::Constant) )); - let operand = - unpack!(block = this.as_operand(block, scope, expr, LocalInfo::Boring, NeedsTemporary::No)); + let operand = unpack!( + block = + this.as_operand(block, scope, expr, LocalInfo::Boring, NeedsTemporary::No) + ); block.and(Rvalue::Use(operand)) } } @@ -662,8 +684,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { // Repeating a const does nothing } else { // For a non-const, we may need to generate an appropriate `Drop` - let value_operand = - unpack!(block = this.as_operand(block, scope, value, LocalInfo::Boring, NeedsTemporary::No)); + let value_operand = unpack!( + block = this.as_operand(block, scope, value, LocalInfo::Boring, NeedsTemporary::No) + ); if let Operand::Move(to_drop) = value_operand { let success = this.cfg.start_new_block(); this.cfg.terminate( diff --git a/compiler/rustc_mir_build/src/build/matches/mod.rs b/compiler/rustc_mir_build/src/build/matches/mod.rs index 22785dfd2ce0e..2d52102db2cc6 100644 --- a/compiler/rustc_mir_build/src/build/matches/mod.rs +++ b/compiler/rustc_mir_build/src/build/matches/mod.rs @@ -2252,7 +2252,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { user_ty: None, source_info, internal: false, - local_info: ClearCrossCrate::Set(Box::new(LocalInfo::User(BindingForm::RefForGuard))), + local_info: ClearCrossCrate::Set(Box::new(LocalInfo::User( + BindingForm::RefForGuard, + ))), }); self.var_debug_info.push(VarDebugInfo { name, diff --git a/compiler/rustc_mir_build/src/build/mod.rs b/compiler/rustc_mir_build/src/build/mod.rs index 6814fd4cb35e0..80d8b27336c54 100644 --- a/compiler/rustc_mir_build/src/build/mod.rs +++ b/compiler/rustc_mir_build/src/build/mod.rs @@ -876,21 +876,18 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { } => { self.local_decls[local].mutability = mutability; self.local_decls[local].source_info.scope = self.source_scope; - **self.local_decls[local].local_info.as_mut().assert_crate_local() = if let Some(kind) = param.self_kind { - LocalInfo::User( - BindingForm::ImplicitSelf(kind), - ) - } else { - let binding_mode = ty::BindingMode::BindByValue(mutability); - LocalInfo::User(BindingForm::Var( - VarBindingForm { + **self.local_decls[local].local_info.as_mut().assert_crate_local() = + if let Some(kind) = param.self_kind { + LocalInfo::User(BindingForm::ImplicitSelf(kind)) + } else { + let binding_mode = ty::BindingMode::BindByValue(mutability); + LocalInfo::User(BindingForm::Var(VarBindingForm { binding_mode, opt_ty_info: param.ty_span, opt_match_place: Some((None, span)), pat_span: span, - }, - )) - }; + })) + }; self.var_indices.insert(var, LocalsForNode::One(local)); } _ => { diff --git a/src/tools/tidy/src/style.rs b/src/tools/tidy/src/style.rs index e3f04840bc71b..a965c98f48491 100644 --- a/src/tools/tidy/src/style.rs +++ b/src/tools/tidy/src/style.rs @@ -228,6 +228,11 @@ fn is_unexplained_ignore(extension: &str, line: &str) -> bool { pub fn check(path: &Path, bad: &mut bool) { fn skip(path: &Path) -> bool { + if path.file_name().map_or(false, |name| name.to_string_lossy().starts_with(".#")) { + // vim or emacs temporary file + return true; + } + if filter_dirs(path) || skip_markdown_path(path) { return true; }