From 8b494f427cb06896996fb02ac8c3ff745fde4d15 Mon Sep 17 00:00:00 2001 From: Maybe Waffle Date: Wed, 2 Feb 2022 15:09:44 +0300 Subject: [PATCH 01/15] Allow `impl Fn() -> impl Trait` in return position This allows writing the following function signatures: ```rust fn f0() -> impl Fn() -> impl Trait; fn f3() -> &'static dyn Fn() -> impl Trait; ``` These signatures were already allowed for common traits and associated types, there is no reason why `Fn*` traits should be special in this regard. --- compiler/rustc_ast_lowering/src/path.rs | 13 ++- .../ui/impl-trait/impl_fn_associativity.rs | 16 ++++ src/test/ui/impl-trait/nested_impl_trait.rs | 3 +- .../ui/impl-trait/nested_impl_trait.stderr | 8 +- src/test/ui/impl-trait/where-allowed.rs | 6 +- src/test/ui/impl-trait/where-allowed.stderr | 94 ++++++++----------- 6 files changed, 73 insertions(+), 67 deletions(-) create mode 100644 src/test/ui/impl-trait/impl_fn_associativity.rs diff --git a/compiler/rustc_ast_lowering/src/path.rs b/compiler/rustc_ast_lowering/src/path.rs index 888776cccac2d..4b7ef960d4b61 100644 --- a/compiler/rustc_ast_lowering/src/path.rs +++ b/compiler/rustc_ast_lowering/src/path.rs @@ -191,7 +191,9 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { self.lower_angle_bracketed_parameter_data(data, param_mode, itctx) } GenericArgs::Parenthesized(ref data) => match parenthesized_generic_args { - ParenthesizedGenericArgs::Ok => self.lower_parenthesized_parameter_data(data), + ParenthesizedGenericArgs::Ok => { + self.lower_parenthesized_parameter_data(data, itctx) + } ParenthesizedGenericArgs::Err => { // Suggest replacing parentheses with angle brackets `Trait(params...)` to `Trait` let sub = if !data.inputs.is_empty() { @@ -344,6 +346,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { fn lower_parenthesized_parameter_data( &mut self, data: &ParenthesizedArgs, + itctx: ImplTraitContext, ) -> (GenericArgsCtor<'hir>, bool) { // Switch to `PassThrough` mode for anonymous lifetimes; this // means that we permit things like `&Ref`, where `Ref` has @@ -355,6 +358,14 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { self.lower_ty_direct(ty, &ImplTraitContext::Disallowed(ImplTraitPosition::FnTraitParam)) })); let output_ty = match output { + // Only allow `impl Trait` in return position. i.e.: + // ```rust + // fn f(_: impl Fn() -> impl Debug) -> impl Fn() -> impl Debug + // // disallowed --^^^^^^^^^^ allowed --^^^^^^^^^^ + // ``` + FnRetTy::Ty(ty) if matches!(itctx, ImplTraitContext::ReturnPositionOpaqueTy { .. }) => { + self.lower_ty(&ty, itctx) + } FnRetTy::Ty(ty) => { self.lower_ty(&ty, &ImplTraitContext::Disallowed(ImplTraitPosition::FnTraitReturn)) } diff --git a/src/test/ui/impl-trait/impl_fn_associativity.rs b/src/test/ui/impl-trait/impl_fn_associativity.rs new file mode 100644 index 0000000000000..f5f1909cf58b0 --- /dev/null +++ b/src/test/ui/impl-trait/impl_fn_associativity.rs @@ -0,0 +1,16 @@ +// run-pass +use std::fmt::Debug; + +fn f_debug() -> impl Fn() -> impl Debug { + || () +} + +fn ff_debug() -> impl Fn() -> impl Fn() -> impl Debug { + || f_debug() +} + +fn main() { + // Check that `ff_debug` is `() -> (() -> Debug)` and not `(() -> ()) -> Debug` + let debug = ff_debug()()(); + assert_eq!(format!("{:?}", debug), "()"); +} diff --git a/src/test/ui/impl-trait/nested_impl_trait.rs b/src/test/ui/impl-trait/nested_impl_trait.rs index 85c6f8c462cbb..9b0dbacaded8d 100644 --- a/src/test/ui/impl-trait/nested_impl_trait.rs +++ b/src/test/ui/impl-trait/nested_impl_trait.rs @@ -25,8 +25,7 @@ fn allowed_in_assoc_type() -> impl Iterator { } fn allowed_in_ret_type() -> impl Fn() -> impl Into { -//~^ `impl Trait` only allowed in function and inherent method return types - || 5 + || 5u8 } fn main() {} diff --git a/src/test/ui/impl-trait/nested_impl_trait.stderr b/src/test/ui/impl-trait/nested_impl_trait.stderr index 3291cad6882e1..e2ce7d15a0697 100644 --- a/src/test/ui/impl-trait/nested_impl_trait.stderr +++ b/src/test/ui/impl-trait/nested_impl_trait.stderr @@ -40,12 +40,6 @@ error[E0562]: `impl Trait` only allowed in function and inherent method return t LL | fn bad_in_fn_syntax(x: fn() -> impl Into) {} | ^^^^^^^^^^^^^^^^^^^^^ -error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `Fn` trait return - --> $DIR/nested_impl_trait.rs:27:42 - | -LL | fn allowed_in_ret_type() -> impl Fn() -> impl Into { - | ^^^^^^^^^^^^^^ - error[E0277]: the trait bound `impl Debug: From>` is not satisfied --> $DIR/nested_impl_trait.rs:5:46 | @@ -64,7 +58,7 @@ LL | fn bad(x: impl Into) -> impl Into { x } = help: the trait `Into` is implemented for `T` = note: required for `impl Into` to implement `Into` -error: aborting due to 8 previous errors +error: aborting due to 7 previous errors Some errors have detailed explanations: E0277, E0562, E0666. For more information about an error, try `rustc --explain E0277`. diff --git a/src/test/ui/impl-trait/where-allowed.rs b/src/test/ui/impl-trait/where-allowed.rs index c1dd46c7ff7fd..d337ab422d746 100644 --- a/src/test/ui/impl-trait/where-allowed.rs +++ b/src/test/ui/impl-trait/where-allowed.rs @@ -39,9 +39,8 @@ fn in_dyn_Fn_return_in_parameters(_: &dyn Fn() -> impl Debug) { panic!() } fn in_dyn_Fn_parameter_in_return() -> &'static dyn Fn(impl Debug) { panic!() } //~^ ERROR `impl Trait` only allowed in function and inherent method return types -// Disallowed +// Allowed fn in_dyn_Fn_return_in_return() -> &'static dyn Fn() -> impl Debug { panic!() } -//~^ ERROR `impl Trait` only allowed in function and inherent method return types // Disallowed fn in_impl_Fn_parameter_in_parameters(_: &impl Fn(impl Debug)) { panic!() } @@ -57,9 +56,8 @@ fn in_impl_Fn_parameter_in_return() -> &'static impl Fn(impl Debug) { panic!() } //~^ ERROR `impl Trait` only allowed in function and inherent method return types //~| ERROR nested `impl Trait` is not allowed -// Disallowed +// Allowed fn in_impl_Fn_return_in_return() -> &'static impl Fn() -> impl Debug { panic!() } -//~^ ERROR `impl Trait` only allowed in function and inherent method return types // Disallowed fn in_Fn_parameter_in_generics (_: F) { panic!() } diff --git a/src/test/ui/impl-trait/where-allowed.stderr b/src/test/ui/impl-trait/where-allowed.stderr index 2e7c7ca40ddb3..1b704d0d92465 100644 --- a/src/test/ui/impl-trait/where-allowed.stderr +++ b/src/test/ui/impl-trait/where-allowed.stderr @@ -1,5 +1,5 @@ error[E0666]: nested `impl Trait` is not allowed - --> $DIR/where-allowed.rs:47:51 + --> $DIR/where-allowed.rs:46:51 | LL | fn in_impl_Fn_parameter_in_parameters(_: &impl Fn(impl Debug)) { panic!() } | --------^^^^^^^^^^- @@ -8,7 +8,7 @@ LL | fn in_impl_Fn_parameter_in_parameters(_: &impl Fn(impl Debug)) { panic!() } | outer `impl Trait` error[E0666]: nested `impl Trait` is not allowed - --> $DIR/where-allowed.rs:56:57 + --> $DIR/where-allowed.rs:55:57 | LL | fn in_impl_Fn_parameter_in_return() -> &'static impl Fn(impl Debug) { panic!() } | --------^^^^^^^^^^- @@ -17,7 +17,7 @@ LL | fn in_impl_Fn_parameter_in_return() -> &'static impl Fn(impl Debug) { panic | outer `impl Trait` error[E0658]: `impl Trait` in type aliases is unstable - --> $DIR/where-allowed.rs:119:16 + --> $DIR/where-allowed.rs:117:16 | LL | type Out = impl Debug; | ^^^^^^^^^^ @@ -26,7 +26,7 @@ LL | type Out = impl Debug; = help: add `#![feature(type_alias_impl_trait)]` to the crate attributes to enable error[E0658]: `impl Trait` in type aliases is unstable - --> $DIR/where-allowed.rs:154:23 + --> $DIR/where-allowed.rs:152:23 | LL | type InTypeAlias = impl Debug; | ^^^^^^^^^^ @@ -35,7 +35,7 @@ LL | type InTypeAlias = impl Debug; = help: add `#![feature(type_alias_impl_trait)]` to the crate attributes to enable error[E0658]: `impl Trait` in type aliases is unstable - --> $DIR/where-allowed.rs:157:39 + --> $DIR/where-allowed.rs:155:39 | LL | type InReturnInTypeAlias = fn() -> impl Debug; | ^^^^^^^^^^ @@ -85,80 +85,68 @@ error[E0562]: `impl Trait` only allowed in function and inherent method return t LL | fn in_dyn_Fn_parameter_in_return() -> &'static dyn Fn(impl Debug) { panic!() } | ^^^^^^^^^^ -error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `Fn` trait return - --> $DIR/where-allowed.rs:43:57 - | -LL | fn in_dyn_Fn_return_in_return() -> &'static dyn Fn() -> impl Debug { panic!() } - | ^^^^^^^^^^ - error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `Fn` trait param - --> $DIR/where-allowed.rs:47:51 + --> $DIR/where-allowed.rs:46:51 | LL | fn in_impl_Fn_parameter_in_parameters(_: &impl Fn(impl Debug)) { panic!() } | ^^^^^^^^^^ error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `Fn` trait return - --> $DIR/where-allowed.rs:52:53 + --> $DIR/where-allowed.rs:51:53 | LL | fn in_impl_Fn_return_in_parameters(_: &impl Fn() -> impl Debug) { panic!() } | ^^^^^^^^^^ error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `Fn` trait param - --> $DIR/where-allowed.rs:56:57 + --> $DIR/where-allowed.rs:55:57 | LL | fn in_impl_Fn_parameter_in_return() -> &'static impl Fn(impl Debug) { panic!() } | ^^^^^^^^^^ -error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `Fn` trait return - --> $DIR/where-allowed.rs:61:59 - | -LL | fn in_impl_Fn_return_in_return() -> &'static impl Fn() -> impl Debug { panic!() } - | ^^^^^^^^^^ - error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `Fn` trait param - --> $DIR/where-allowed.rs:65:38 + --> $DIR/where-allowed.rs:63:38 | LL | fn in_Fn_parameter_in_generics (_: F) { panic!() } | ^^^^^^^^^^ error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `Fn` trait return - --> $DIR/where-allowed.rs:69:40 + --> $DIR/where-allowed.rs:67:40 | LL | fn in_Fn_return_in_generics impl Debug> (_: F) { panic!() } | ^^^^^^^^^^ error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in type - --> $DIR/where-allowed.rs:82:32 + --> $DIR/where-allowed.rs:80:32 | LL | struct InBraceStructField { x: impl Debug } | ^^^^^^^^^^ error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in path - --> $DIR/where-allowed.rs:86:41 + --> $DIR/where-allowed.rs:84:41 | LL | struct InAdtInBraceStructField { x: Vec } | ^^^^^^^^^^ error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in type - --> $DIR/where-allowed.rs:90:27 + --> $DIR/where-allowed.rs:88:27 | LL | struct InTupleStructField(impl Debug); | ^^^^^^^^^^ error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in type - --> $DIR/where-allowed.rs:95:25 + --> $DIR/where-allowed.rs:93:25 | LL | InBraceVariant { x: impl Debug }, | ^^^^^^^^^^ error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in type - --> $DIR/where-allowed.rs:97:20 + --> $DIR/where-allowed.rs:95:20 | LL | InTupleVariant(impl Debug), | ^^^^^^^^^^ error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in trait method return - --> $DIR/where-allowed.rs:108:23 + --> $DIR/where-allowed.rs:106:23 | LL | fn in_return() -> impl Debug; | ^^^^^^^^^^ @@ -167,7 +155,7 @@ LL | fn in_return() -> impl Debug; = help: add `#![feature(return_position_impl_trait_in_trait)]` to the crate attributes to enable error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `impl` method return - --> $DIR/where-allowed.rs:125:34 + --> $DIR/where-allowed.rs:123:34 | LL | fn in_trait_impl_return() -> impl Debug { () } | ^^^^^^^^^^ @@ -176,127 +164,127 @@ LL | fn in_trait_impl_return() -> impl Debug { () } = help: add `#![feature(return_position_impl_trait_in_trait)]` to the crate attributes to enable error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `extern fn` param - --> $DIR/where-allowed.rs:138:33 + --> $DIR/where-allowed.rs:136:33 | LL | fn in_foreign_parameters(_: impl Debug); | ^^^^^^^^^^ error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `extern fn` return - --> $DIR/where-allowed.rs:141:31 + --> $DIR/where-allowed.rs:139:31 | LL | fn in_foreign_return() -> impl Debug; | ^^^^^^^^^^ error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `fn` pointer return - --> $DIR/where-allowed.rs:157:39 + --> $DIR/where-allowed.rs:155:39 | LL | type InReturnInTypeAlias = fn() -> impl Debug; | ^^^^^^^^^^ error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in trait - --> $DIR/where-allowed.rs:162:16 + --> $DIR/where-allowed.rs:160:16 | LL | impl PartialEq for () { | ^^^^^^^^^^ error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in type - --> $DIR/where-allowed.rs:167:24 + --> $DIR/where-allowed.rs:165:24 | LL | impl PartialEq<()> for impl Debug { | ^^^^^^^^^^ error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in type - --> $DIR/where-allowed.rs:172:6 + --> $DIR/where-allowed.rs:170:6 | LL | impl impl Debug { | ^^^^^^^^^^ error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in type - --> $DIR/where-allowed.rs:178:24 + --> $DIR/where-allowed.rs:176:24 | LL | impl InInherentImplAdt { | ^^^^^^^^^^ error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in type - --> $DIR/where-allowed.rs:184:11 + --> $DIR/where-allowed.rs:182:11 | LL | where impl Debug: Debug | ^^^^^^^^^^ error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in type - --> $DIR/where-allowed.rs:191:15 + --> $DIR/where-allowed.rs:189:15 | LL | where Vec: Debug | ^^^^^^^^^^ error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in bound - --> $DIR/where-allowed.rs:198:24 + --> $DIR/where-allowed.rs:196:24 | LL | where T: PartialEq | ^^^^^^^^^^ error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `Fn` trait param - --> $DIR/where-allowed.rs:205:17 + --> $DIR/where-allowed.rs:203:17 | LL | where T: Fn(impl Debug) | ^^^^^^^^^^ error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `Fn` trait return - --> $DIR/where-allowed.rs:212:22 + --> $DIR/where-allowed.rs:210:22 | LL | where T: Fn() -> impl Debug | ^^^^^^^^^^ error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in type - --> $DIR/where-allowed.rs:218:40 + --> $DIR/where-allowed.rs:216:40 | LL | struct InStructGenericParamDefault(T); | ^^^^^^^^^^ error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in type - --> $DIR/where-allowed.rs:222:36 + --> $DIR/where-allowed.rs:220:36 | LL | enum InEnumGenericParamDefault { Variant(T) } | ^^^^^^^^^^ error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in type - --> $DIR/where-allowed.rs:226:38 + --> $DIR/where-allowed.rs:224:38 | LL | trait InTraitGenericParamDefault {} | ^^^^^^^^^^ error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in type - --> $DIR/where-allowed.rs:230:41 + --> $DIR/where-allowed.rs:228:41 | LL | type InTypeAliasGenericParamDefault = T; | ^^^^^^^^^^ error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in type - --> $DIR/where-allowed.rs:234:11 + --> $DIR/where-allowed.rs:232:11 | LL | impl T {} | ^^^^^^^^^^ error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in type - --> $DIR/where-allowed.rs:241:40 + --> $DIR/where-allowed.rs:239:40 | LL | fn in_method_generic_param_default(_: T) {} | ^^^^^^^^^^ error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in variable binding - --> $DIR/where-allowed.rs:247:29 + --> $DIR/where-allowed.rs:245:29 | LL | let _in_local_variable: impl Fn() = || {}; | ^^^^^^^^^ error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in closure return - --> $DIR/where-allowed.rs:249:46 + --> $DIR/where-allowed.rs:247:46 | LL | let _in_return_in_local_variable = || -> impl Fn() { || {} }; | ^^^^^^^^^ error: defaults for type parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions - --> $DIR/where-allowed.rs:234:7 + --> $DIR/where-allowed.rs:232:7 | LL | impl T {} | ^^^^^^^^^^^^^^ @@ -306,7 +294,7 @@ LL | impl T {} = note: `#[deny(invalid_type_param_default)]` on by default error: defaults for type parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions - --> $DIR/where-allowed.rs:241:36 + --> $DIR/where-allowed.rs:239:36 | LL | fn in_method_generic_param_default(_: T) {} | ^^^^^^^^^^^^^^ @@ -315,14 +303,14 @@ LL | fn in_method_generic_param_default(_: T) {} = note: for more information, see issue #36887 error[E0118]: no nominal type found for inherent implementation - --> $DIR/where-allowed.rs:234:23 + --> $DIR/where-allowed.rs:232:23 | LL | impl T {} | ^ impl requires a nominal type | = note: either implement a trait on it or create a newtype to wrap it instead -error: aborting due to 49 previous errors +error: aborting due to 47 previous errors Some errors have detailed explanations: E0118, E0562, E0658, E0666. For more information about an error, try `rustc --explain E0118`. From 7a4ba2ffdee0e63fe62f7543589faec9ad29fb9c Mon Sep 17 00:00:00 2001 From: Maybe Waffle Date: Thu, 23 Jun 2022 19:00:03 +0400 Subject: [PATCH 02/15] Add more tests for `impl Fn() -> impl Trait` --- .../ui/impl-trait/impl-fn-hrtb-bounds-2.rs | 7 +++++ .../impl-trait/impl-fn-hrtb-bounds-2.stderr | 11 ++++++++ src/test/ui/impl-trait/impl-fn-hrtb-bounds.rs | 13 ++++++++++ .../ui/impl-trait/impl-fn-hrtb-bounds.stderr | 26 +++++++++++++++++++ .../impl-trait/impl-fn-parsing-ambiguities.rs | 14 ++++++++++ .../impl-fn-parsing-ambiguities.stderr | 26 +++++++++++++++++++ .../ui/impl-trait/impl_fn_associativity.rs | 9 +++++++ 7 files changed, 106 insertions(+) create mode 100644 src/test/ui/impl-trait/impl-fn-hrtb-bounds-2.rs create mode 100644 src/test/ui/impl-trait/impl-fn-hrtb-bounds-2.stderr create mode 100644 src/test/ui/impl-trait/impl-fn-hrtb-bounds.rs create mode 100644 src/test/ui/impl-trait/impl-fn-hrtb-bounds.stderr create mode 100644 src/test/ui/impl-trait/impl-fn-parsing-ambiguities.rs create mode 100644 src/test/ui/impl-trait/impl-fn-parsing-ambiguities.stderr diff --git a/src/test/ui/impl-trait/impl-fn-hrtb-bounds-2.rs b/src/test/ui/impl-trait/impl-fn-hrtb-bounds-2.rs new file mode 100644 index 0000000000000..688ae1da5e30f --- /dev/null +++ b/src/test/ui/impl-trait/impl-fn-hrtb-bounds-2.rs @@ -0,0 +1,7 @@ +use std::fmt::Debug; + +fn a() -> impl Fn(&u8) -> impl Debug { + |x| x //~ ERROR lifetime may not live long enough +} + +fn main() {} diff --git a/src/test/ui/impl-trait/impl-fn-hrtb-bounds-2.stderr b/src/test/ui/impl-trait/impl-fn-hrtb-bounds-2.stderr new file mode 100644 index 0000000000000..57f618d11f904 --- /dev/null +++ b/src/test/ui/impl-trait/impl-fn-hrtb-bounds-2.stderr @@ -0,0 +1,11 @@ +error: lifetime may not live long enough + --> $DIR/impl-fn-hrtb-bounds-2.rs:4:9 + | +LL | |x| x + | -- ^ returning this value requires that `'1` must outlive `'2` + | || + | |return type of closure is &'2 u8 + | has type `&'1 u8` + +error: aborting due to previous error + diff --git a/src/test/ui/impl-trait/impl-fn-hrtb-bounds.rs b/src/test/ui/impl-trait/impl-fn-hrtb-bounds.rs new file mode 100644 index 0000000000000..f7d9430a22637 --- /dev/null +++ b/src/test/ui/impl-trait/impl-fn-hrtb-bounds.rs @@ -0,0 +1,13 @@ +use std::fmt::Debug; + +fn a() -> impl Fn(&u8) -> (impl Debug + '_) { + //~^ ERROR higher kinded lifetime bounds on nested opaque types are not supported yet + |x| x +} + +fn b() -> impl for<'a> Fn(&'a u8) -> (impl Debug + 'a) { + //~^ ERROR higher kinded lifetime bounds on nested opaque types are not supported yet + |x| x +} + +fn main() {} diff --git a/src/test/ui/impl-trait/impl-fn-hrtb-bounds.stderr b/src/test/ui/impl-trait/impl-fn-hrtb-bounds.stderr new file mode 100644 index 0000000000000..6fe4534d9281f --- /dev/null +++ b/src/test/ui/impl-trait/impl-fn-hrtb-bounds.stderr @@ -0,0 +1,26 @@ +error: higher kinded lifetime bounds on nested opaque types are not supported yet + --> $DIR/impl-fn-hrtb-bounds.rs:3:41 + | +LL | fn a() -> impl Fn(&u8) -> (impl Debug + '_) { + | ^^ + | +note: lifetime declared here + --> $DIR/impl-fn-hrtb-bounds.rs:3:19 + | +LL | fn a() -> impl Fn(&u8) -> (impl Debug + '_) { + | ^ + +error: higher kinded lifetime bounds on nested opaque types are not supported yet + --> $DIR/impl-fn-hrtb-bounds.rs:8:52 + | +LL | fn b() -> impl for<'a> Fn(&'a u8) -> (impl Debug + 'a) { + | ^^ + | +note: lifetime declared here + --> $DIR/impl-fn-hrtb-bounds.rs:8:20 + | +LL | fn b() -> impl for<'a> Fn(&'a u8) -> (impl Debug + 'a) { + | ^^ + +error: aborting due to 2 previous errors + diff --git a/src/test/ui/impl-trait/impl-fn-parsing-ambiguities.rs b/src/test/ui/impl-trait/impl-fn-parsing-ambiguities.rs new file mode 100644 index 0000000000000..053912aa8166a --- /dev/null +++ b/src/test/ui/impl-trait/impl-fn-parsing-ambiguities.rs @@ -0,0 +1,14 @@ +use std::fmt::Debug; + +fn a() -> impl Fn(&u8) -> impl Debug + '_ { + //~^ ERROR ambiguous `+` in a type + //~^^ ERROR higher kinded lifetime bounds on nested opaque types are not supported yet + |x| x +} + +fn b() -> impl Fn() -> impl Debug + Send { + //~^ ERROR ambiguous `+` in a type + || () +} + +fn main() {} diff --git a/src/test/ui/impl-trait/impl-fn-parsing-ambiguities.stderr b/src/test/ui/impl-trait/impl-fn-parsing-ambiguities.stderr new file mode 100644 index 0000000000000..e54864443ae04 --- /dev/null +++ b/src/test/ui/impl-trait/impl-fn-parsing-ambiguities.stderr @@ -0,0 +1,26 @@ +error: ambiguous `+` in a type + --> $DIR/impl-fn-parsing-ambiguities.rs:3:27 + | +LL | fn a() -> impl Fn(&u8) -> impl Debug + '_ { + | ^^^^^^^^^^^^^^^ help: use parentheses to disambiguate: `(impl Debug + '_)` + +error: ambiguous `+` in a type + --> $DIR/impl-fn-parsing-ambiguities.rs:9:24 + | +LL | fn b() -> impl Fn() -> impl Debug + Send { + | ^^^^^^^^^^^^^^^^^ help: use parentheses to disambiguate: `(impl Debug + Send)` + +error: higher kinded lifetime bounds on nested opaque types are not supported yet + --> $DIR/impl-fn-parsing-ambiguities.rs:3:40 + | +LL | fn a() -> impl Fn(&u8) -> impl Debug + '_ { + | ^^ + | +note: lifetime declared here + --> $DIR/impl-fn-parsing-ambiguities.rs:3:19 + | +LL | fn a() -> impl Fn(&u8) -> impl Debug + '_ { + | ^ + +error: aborting due to 3 previous errors + diff --git a/src/test/ui/impl-trait/impl_fn_associativity.rs b/src/test/ui/impl-trait/impl_fn_associativity.rs index f5f1909cf58b0..6accaed98c9ab 100644 --- a/src/test/ui/impl-trait/impl_fn_associativity.rs +++ b/src/test/ui/impl-trait/impl_fn_associativity.rs @@ -9,8 +9,17 @@ fn ff_debug() -> impl Fn() -> impl Fn() -> impl Debug { || f_debug() } +fn multi() -> impl Fn() -> (impl Debug + Send) { + || () +} + fn main() { // Check that `ff_debug` is `() -> (() -> Debug)` and not `(() -> ()) -> Debug` let debug = ff_debug()()(); assert_eq!(format!("{:?}", debug), "()"); + + let x = multi()(); + assert_eq!(format!("{:?}", x), "()"); + fn assert_send(_: &impl Send) {} + assert_send(&x); } From 00f22771f6fb625fd66122fded49d5bee7083707 Mon Sep 17 00:00:00 2001 From: Maybe Waffle Date: Thu, 23 Jun 2022 19:12:13 +0400 Subject: [PATCH 03/15] Add even more tests for `impl Fn() -> impl Trait` --- src/test/ui/impl-trait/impl-fn-hrtb-bounds.rs | 10 ++++++ .../ui/impl-trait/impl-fn-hrtb-bounds.stderr | 32 ++++++++++++++++++- .../impl-fn-predefined-lifetimes.rs | 12 +++++++ 3 files changed, 53 insertions(+), 1 deletion(-) create mode 100644 src/test/ui/impl-trait/impl-fn-predefined-lifetimes.rs diff --git a/src/test/ui/impl-trait/impl-fn-hrtb-bounds.rs b/src/test/ui/impl-trait/impl-fn-hrtb-bounds.rs index f7d9430a22637..25144c090485e 100644 --- a/src/test/ui/impl-trait/impl-fn-hrtb-bounds.rs +++ b/src/test/ui/impl-trait/impl-fn-hrtb-bounds.rs @@ -10,4 +10,14 @@ fn b() -> impl for<'a> Fn(&'a u8) -> (impl Debug + 'a) { |x| x } +fn c() -> impl for<'a> Fn(&'a u8) -> (impl Debug + '_) { + //~^ ERROR higher kinded lifetime bounds on nested opaque types are not supported yet + |x| x +} + +fn d() -> impl Fn() -> (impl Debug + '_) { + //~^ ERROR missing lifetime specifier + || () +} + fn main() {} diff --git a/src/test/ui/impl-trait/impl-fn-hrtb-bounds.stderr b/src/test/ui/impl-trait/impl-fn-hrtb-bounds.stderr index 6fe4534d9281f..6985c66df8791 100644 --- a/src/test/ui/impl-trait/impl-fn-hrtb-bounds.stderr +++ b/src/test/ui/impl-trait/impl-fn-hrtb-bounds.stderr @@ -22,5 +22,35 @@ note: lifetime declared here LL | fn b() -> impl for<'a> Fn(&'a u8) -> (impl Debug + 'a) { | ^^ -error: aborting due to 2 previous errors +error: higher kinded lifetime bounds on nested opaque types are not supported yet + --> $DIR/impl-fn-hrtb-bounds.rs:13:52 + | +LL | fn c() -> impl for<'a> Fn(&'a u8) -> (impl Debug + '_) { + | ^^ + | +note: lifetime declared here + --> $DIR/impl-fn-hrtb-bounds.rs:13:20 + | +LL | fn c() -> impl for<'a> Fn(&'a u8) -> (impl Debug + '_) { + | ^^ + +error[E0106]: missing lifetime specifier + --> $DIR/impl-fn-hrtb-bounds.rs:18:38 + | +LL | fn d() -> impl Fn() -> (impl Debug + '_) { + | ^^ expected named lifetime parameter + | + = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from + = note: for more information on higher-ranked polymorphism, visit https://doc.rust-lang.org/nomicon/hrtb.html +help: consider making the bound lifetime-generic with a new `'a` lifetime + | +LL | fn d() -> impl for<'a> Fn() -> (impl Debug + 'a) { + | +++++++ ~~ +help: consider using the `'static` lifetime + | +LL | fn d() -> impl Fn() -> (impl Debug + 'static) { + | ~~~~~~~ + +error: aborting due to 4 previous errors +For more information about this error, try `rustc --explain E0106`. diff --git a/src/test/ui/impl-trait/impl-fn-predefined-lifetimes.rs b/src/test/ui/impl-trait/impl-fn-predefined-lifetimes.rs new file mode 100644 index 0000000000000..e2f6e600da433 --- /dev/null +++ b/src/test/ui/impl-trait/impl-fn-predefined-lifetimes.rs @@ -0,0 +1,12 @@ +// check-pass +use std::fmt::Debug; + +fn a<'a>() -> impl Fn(&'a u8) -> (impl Debug + '_) { + |x| x +} + +fn _b<'a>() -> impl Fn(&'a u8) -> (impl Debug + 'a) { + a() +} + +fn main() {} From cc752f56650c123d702d027aeb154eafbe3fdd50 Mon Sep 17 00:00:00 2001 From: Maybe Waffle Date: Mon, 25 Jul 2022 01:54:47 +0400 Subject: [PATCH 04/15] Feature gate `impl_trait_in_fn_trait_return` --- compiler/rustc_ast_lowering/src/path.rs | 5 ++++- compiler/rustc_feature/src/active.rs | 2 ++ compiler/rustc_span/src/symbol.rs | 1 + 3 files changed, 7 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_ast_lowering/src/path.rs b/compiler/rustc_ast_lowering/src/path.rs index 4b7ef960d4b61..b7cda13fa4b70 100644 --- a/compiler/rustc_ast_lowering/src/path.rs +++ b/compiler/rustc_ast_lowering/src/path.rs @@ -363,7 +363,10 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { // fn f(_: impl Fn() -> impl Debug) -> impl Fn() -> impl Debug // // disallowed --^^^^^^^^^^ allowed --^^^^^^^^^^ // ``` - FnRetTy::Ty(ty) if matches!(itctx, ImplTraitContext::ReturnPositionOpaqueTy { .. }) => { + FnRetTy::Ty(ty) + if matches!(itctx, ImplTraitContext::ReturnPositionOpaqueTy { .. }) + && self.tcx.features().impl_trait_in_fn_trait_return => + { self.lower_ty(&ty, itctx) } FnRetTy::Ty(ty) => { diff --git a/compiler/rustc_feature/src/active.rs b/compiler/rustc_feature/src/active.rs index 1b8d683b13361..5656409c0d471 100644 --- a/compiler/rustc_feature/src/active.rs +++ b/compiler/rustc_feature/src/active.rs @@ -414,6 +414,8 @@ declare_features! ( (active, half_open_range_patterns_in_slices, "CURRENT_RUSTC_VERSION", Some(67264), None), /// Allows `if let` guard in match arms. (active, if_let_guard, "1.47.0", Some(51114), None), + /// Allows `impl Trait` as output type in `Fn` traits in return position of functions. + (active, impl_trait_in_fn_trait_return, "1.64.0", Some(99697), None), /// Allows using imported `main` function (active, imported_main, "1.53.0", Some(28937), None), /// Allows associated types in inherent impls. diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 3fe79370c374d..21016602ff8d2 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -813,6 +813,7 @@ symbols! { impl_lint_pass, impl_macros, impl_trait_in_bindings, + impl_trait_in_fn_trait_return, implied_by, import, import_name_type, From d116859ad78efa743726acd91d05d5a0bc64c0fe Mon Sep 17 00:00:00 2001 From: Maybe Waffle Date: Fri, 29 Jul 2022 00:18:32 +0400 Subject: [PATCH 05/15] --bless --- .../ui/impl-trait/impl-fn-hrtb-bounds-2.rs | 3 +- .../impl-trait/impl-fn-hrtb-bounds-2.stderr | 12 +-- src/test/ui/impl-trait/impl-fn-hrtb-bounds.rs | 1 + .../ui/impl-trait/impl-fn-hrtb-bounds.stderr | 41 ++++---- .../impl-trait/impl-fn-parsing-ambiguities.rs | 1 + .../impl-fn-parsing-ambiguities.stderr | 8 +- .../impl-fn-predefined-lifetimes.rs | 3 +- .../impl-fn-predefined-lifetimes.stderr | 15 +++ .../ui/impl-trait/impl_fn_associativity.rs | 1 + src/test/ui/impl-trait/nested_impl_trait.rs | 1 + .../ui/impl-trait/nested_impl_trait.stderr | 14 +-- src/test/ui/impl-trait/where-allowed.rs | 1 + src/test/ui/impl-trait/where-allowed.stderr | 94 +++++++++---------- 13 files changed, 106 insertions(+), 89 deletions(-) create mode 100644 src/test/ui/impl-trait/impl-fn-predefined-lifetimes.stderr diff --git a/src/test/ui/impl-trait/impl-fn-hrtb-bounds-2.rs b/src/test/ui/impl-trait/impl-fn-hrtb-bounds-2.rs index 688ae1da5e30f..b0aeded0ef75a 100644 --- a/src/test/ui/impl-trait/impl-fn-hrtb-bounds-2.rs +++ b/src/test/ui/impl-trait/impl-fn-hrtb-bounds-2.rs @@ -1,7 +1,8 @@ +#![feature(impl_trait_in_fn_trait_return)] use std::fmt::Debug; fn a() -> impl Fn(&u8) -> impl Debug { - |x| x //~ ERROR lifetime may not live long enough + |x| x //~ ERROR hidden type for `impl Debug` captures lifetime that does not appear in bounds } fn main() {} diff --git a/src/test/ui/impl-trait/impl-fn-hrtb-bounds-2.stderr b/src/test/ui/impl-trait/impl-fn-hrtb-bounds-2.stderr index 57f618d11f904..433b76b7afaa2 100644 --- a/src/test/ui/impl-trait/impl-fn-hrtb-bounds-2.stderr +++ b/src/test/ui/impl-trait/impl-fn-hrtb-bounds-2.stderr @@ -1,11 +1,11 @@ -error: lifetime may not live long enough - --> $DIR/impl-fn-hrtb-bounds-2.rs:4:9 +error[E0700]: hidden type for `impl Debug` captures lifetime that does not appear in bounds + --> $DIR/impl-fn-hrtb-bounds-2.rs:5:9 | LL | |x| x - | -- ^ returning this value requires that `'1` must outlive `'2` - | || - | |return type of closure is &'2 u8 - | has type `&'1 u8` + | --- ^ + | | + | hidden type `&u8` captures the anonymous lifetime #1 defined here error: aborting due to previous error +For more information about this error, try `rustc --explain E0700`. diff --git a/src/test/ui/impl-trait/impl-fn-hrtb-bounds.rs b/src/test/ui/impl-trait/impl-fn-hrtb-bounds.rs index 25144c090485e..527a4586fd7e0 100644 --- a/src/test/ui/impl-trait/impl-fn-hrtb-bounds.rs +++ b/src/test/ui/impl-trait/impl-fn-hrtb-bounds.rs @@ -1,3 +1,4 @@ +#![feature(impl_trait_in_fn_trait_return)] use std::fmt::Debug; fn a() -> impl Fn(&u8) -> (impl Debug + '_) { diff --git a/src/test/ui/impl-trait/impl-fn-hrtb-bounds.stderr b/src/test/ui/impl-trait/impl-fn-hrtb-bounds.stderr index 6985c66df8791..443ffeb55cdee 100644 --- a/src/test/ui/impl-trait/impl-fn-hrtb-bounds.stderr +++ b/src/test/ui/impl-trait/impl-fn-hrtb-bounds.stderr @@ -1,56 +1,51 @@ +error[E0106]: missing lifetime specifier + --> $DIR/impl-fn-hrtb-bounds.rs:19:38 + | +LL | fn d() -> impl Fn() -> (impl Debug + '_) { + | ^^ expected named lifetime parameter + | + = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from +help: consider using the `'static` lifetime + | +LL | fn d() -> impl Fn() -> (impl Debug + 'static) { + | ~~~~~~~ + error: higher kinded lifetime bounds on nested opaque types are not supported yet - --> $DIR/impl-fn-hrtb-bounds.rs:3:41 + --> $DIR/impl-fn-hrtb-bounds.rs:4:41 | LL | fn a() -> impl Fn(&u8) -> (impl Debug + '_) { | ^^ | note: lifetime declared here - --> $DIR/impl-fn-hrtb-bounds.rs:3:19 + --> $DIR/impl-fn-hrtb-bounds.rs:4:19 | LL | fn a() -> impl Fn(&u8) -> (impl Debug + '_) { | ^ error: higher kinded lifetime bounds on nested opaque types are not supported yet - --> $DIR/impl-fn-hrtb-bounds.rs:8:52 + --> $DIR/impl-fn-hrtb-bounds.rs:9:52 | LL | fn b() -> impl for<'a> Fn(&'a u8) -> (impl Debug + 'a) { | ^^ | note: lifetime declared here - --> $DIR/impl-fn-hrtb-bounds.rs:8:20 + --> $DIR/impl-fn-hrtb-bounds.rs:9:20 | LL | fn b() -> impl for<'a> Fn(&'a u8) -> (impl Debug + 'a) { | ^^ error: higher kinded lifetime bounds on nested opaque types are not supported yet - --> $DIR/impl-fn-hrtb-bounds.rs:13:52 + --> $DIR/impl-fn-hrtb-bounds.rs:14:52 | LL | fn c() -> impl for<'a> Fn(&'a u8) -> (impl Debug + '_) { | ^^ | note: lifetime declared here - --> $DIR/impl-fn-hrtb-bounds.rs:13:20 + --> $DIR/impl-fn-hrtb-bounds.rs:14:20 | LL | fn c() -> impl for<'a> Fn(&'a u8) -> (impl Debug + '_) { | ^^ -error[E0106]: missing lifetime specifier - --> $DIR/impl-fn-hrtb-bounds.rs:18:38 - | -LL | fn d() -> impl Fn() -> (impl Debug + '_) { - | ^^ expected named lifetime parameter - | - = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from - = note: for more information on higher-ranked polymorphism, visit https://doc.rust-lang.org/nomicon/hrtb.html -help: consider making the bound lifetime-generic with a new `'a` lifetime - | -LL | fn d() -> impl for<'a> Fn() -> (impl Debug + 'a) { - | +++++++ ~~ -help: consider using the `'static` lifetime - | -LL | fn d() -> impl Fn() -> (impl Debug + 'static) { - | ~~~~~~~ - error: aborting due to 4 previous errors For more information about this error, try `rustc --explain E0106`. diff --git a/src/test/ui/impl-trait/impl-fn-parsing-ambiguities.rs b/src/test/ui/impl-trait/impl-fn-parsing-ambiguities.rs index 053912aa8166a..3e760710797eb 100644 --- a/src/test/ui/impl-trait/impl-fn-parsing-ambiguities.rs +++ b/src/test/ui/impl-trait/impl-fn-parsing-ambiguities.rs @@ -1,3 +1,4 @@ +#![feature(impl_trait_in_fn_trait_return)] use std::fmt::Debug; fn a() -> impl Fn(&u8) -> impl Debug + '_ { diff --git a/src/test/ui/impl-trait/impl-fn-parsing-ambiguities.stderr b/src/test/ui/impl-trait/impl-fn-parsing-ambiguities.stderr index e54864443ae04..cf6e5ef7baceb 100644 --- a/src/test/ui/impl-trait/impl-fn-parsing-ambiguities.stderr +++ b/src/test/ui/impl-trait/impl-fn-parsing-ambiguities.stderr @@ -1,23 +1,23 @@ error: ambiguous `+` in a type - --> $DIR/impl-fn-parsing-ambiguities.rs:3:27 + --> $DIR/impl-fn-parsing-ambiguities.rs:4:27 | LL | fn a() -> impl Fn(&u8) -> impl Debug + '_ { | ^^^^^^^^^^^^^^^ help: use parentheses to disambiguate: `(impl Debug + '_)` error: ambiguous `+` in a type - --> $DIR/impl-fn-parsing-ambiguities.rs:9:24 + --> $DIR/impl-fn-parsing-ambiguities.rs:10:24 | LL | fn b() -> impl Fn() -> impl Debug + Send { | ^^^^^^^^^^^^^^^^^ help: use parentheses to disambiguate: `(impl Debug + Send)` error: higher kinded lifetime bounds on nested opaque types are not supported yet - --> $DIR/impl-fn-parsing-ambiguities.rs:3:40 + --> $DIR/impl-fn-parsing-ambiguities.rs:4:40 | LL | fn a() -> impl Fn(&u8) -> impl Debug + '_ { | ^^ | note: lifetime declared here - --> $DIR/impl-fn-parsing-ambiguities.rs:3:19 + --> $DIR/impl-fn-parsing-ambiguities.rs:4:19 | LL | fn a() -> impl Fn(&u8) -> impl Debug + '_ { | ^ diff --git a/src/test/ui/impl-trait/impl-fn-predefined-lifetimes.rs b/src/test/ui/impl-trait/impl-fn-predefined-lifetimes.rs index e2f6e600da433..5e2379b2f9af6 100644 --- a/src/test/ui/impl-trait/impl-fn-predefined-lifetimes.rs +++ b/src/test/ui/impl-trait/impl-fn-predefined-lifetimes.rs @@ -1,7 +1,8 @@ -// check-pass +#![feature(impl_trait_in_fn_trait_return)] use std::fmt::Debug; fn a<'a>() -> impl Fn(&'a u8) -> (impl Debug + '_) { + //~^ ERROR hidden type for `impl Debug` captures lifetime that does not appear in bounds |x| x } diff --git a/src/test/ui/impl-trait/impl-fn-predefined-lifetimes.stderr b/src/test/ui/impl-trait/impl-fn-predefined-lifetimes.stderr new file mode 100644 index 0000000000000..1247ffad7c324 --- /dev/null +++ b/src/test/ui/impl-trait/impl-fn-predefined-lifetimes.stderr @@ -0,0 +1,15 @@ +error[E0700]: hidden type for `impl Debug` captures lifetime that does not appear in bounds + --> $DIR/impl-fn-predefined-lifetimes.rs:4:35 + | +LL | fn a<'a>() -> impl Fn(&'a u8) -> (impl Debug + '_) { + | ^^^^^^^^^^^^^^^ + | +note: hidden type `&' u8` captures lifetime smaller than the function body + --> $DIR/impl-fn-predefined-lifetimes.rs:4:35 + | +LL | fn a<'a>() -> impl Fn(&'a u8) -> (impl Debug + '_) { + | ^^^^^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0700`. diff --git a/src/test/ui/impl-trait/impl_fn_associativity.rs b/src/test/ui/impl-trait/impl_fn_associativity.rs index 6accaed98c9ab..71a8f9c77960d 100644 --- a/src/test/ui/impl-trait/impl_fn_associativity.rs +++ b/src/test/ui/impl-trait/impl_fn_associativity.rs @@ -1,4 +1,5 @@ // run-pass +#![feature(impl_trait_in_fn_trait_return)] use std::fmt::Debug; fn f_debug() -> impl Fn() -> impl Debug { diff --git a/src/test/ui/impl-trait/nested_impl_trait.rs b/src/test/ui/impl-trait/nested_impl_trait.rs index 9b0dbacaded8d..e95fab3b65057 100644 --- a/src/test/ui/impl-trait/nested_impl_trait.rs +++ b/src/test/ui/impl-trait/nested_impl_trait.rs @@ -1,3 +1,4 @@ +#![feature(impl_trait_in_fn_trait_return)] use std::fmt::Debug; fn fine(x: impl Into) -> impl Into { x } diff --git a/src/test/ui/impl-trait/nested_impl_trait.stderr b/src/test/ui/impl-trait/nested_impl_trait.stderr index e2ce7d15a0697..9a8f5a3406813 100644 --- a/src/test/ui/impl-trait/nested_impl_trait.stderr +++ b/src/test/ui/impl-trait/nested_impl_trait.stderr @@ -1,5 +1,5 @@ error[E0666]: nested `impl Trait` is not allowed - --> $DIR/nested_impl_trait.rs:5:56 + --> $DIR/nested_impl_trait.rs:6:56 | LL | fn bad_in_ret_position(x: impl Into) -> impl Into { x } | ----------^^^^^^^^^^- @@ -8,7 +8,7 @@ LL | fn bad_in_ret_position(x: impl Into) -> impl Into { x } | outer `impl Trait` error[E0666]: nested `impl Trait` is not allowed - --> $DIR/nested_impl_trait.rs:9:42 + --> $DIR/nested_impl_trait.rs:10:42 | LL | fn bad_in_fn_syntax(x: fn() -> impl Into) {} | ----------^^^^^^^^^^- @@ -17,7 +17,7 @@ LL | fn bad_in_fn_syntax(x: fn() -> impl Into) {} | outer `impl Trait` error[E0666]: nested `impl Trait` is not allowed - --> $DIR/nested_impl_trait.rs:13:37 + --> $DIR/nested_impl_trait.rs:14:37 | LL | fn bad_in_arg_position(_: impl Into) { } | ----------^^^^^^^^^^- @@ -26,7 +26,7 @@ LL | fn bad_in_arg_position(_: impl Into) { } | outer `impl Trait` error[E0666]: nested `impl Trait` is not allowed - --> $DIR/nested_impl_trait.rs:18:44 + --> $DIR/nested_impl_trait.rs:19:44 | LL | fn bad(x: impl Into) -> impl Into { x } | ----------^^^^^^^^^^- @@ -35,13 +35,13 @@ LL | fn bad(x: impl Into) -> impl Into { x } | outer `impl Trait` error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `fn` pointer return - --> $DIR/nested_impl_trait.rs:9:32 + --> $DIR/nested_impl_trait.rs:10:32 | LL | fn bad_in_fn_syntax(x: fn() -> impl Into) {} | ^^^^^^^^^^^^^^^^^^^^^ error[E0277]: the trait bound `impl Debug: From>` is not satisfied - --> $DIR/nested_impl_trait.rs:5:46 + --> $DIR/nested_impl_trait.rs:6:46 | LL | fn bad_in_ret_position(x: impl Into) -> impl Into { x } | ^^^^^^^^^^^^^^^^^^^^^ the trait `From>` is not implemented for `impl Debug` @@ -50,7 +50,7 @@ LL | fn bad_in_ret_position(x: impl Into) -> impl Into { x } = note: required for `impl Into` to implement `Into` error[E0277]: the trait bound `impl Debug: From>` is not satisfied - --> $DIR/nested_impl_trait.rs:18:34 + --> $DIR/nested_impl_trait.rs:19:34 | LL | fn bad(x: impl Into) -> impl Into { x } | ^^^^^^^^^^^^^^^^^^^^^ the trait `From>` is not implemented for `impl Debug` diff --git a/src/test/ui/impl-trait/where-allowed.rs b/src/test/ui/impl-trait/where-allowed.rs index d337ab422d746..ff63b04c2680d 100644 --- a/src/test/ui/impl-trait/where-allowed.rs +++ b/src/test/ui/impl-trait/where-allowed.rs @@ -1,5 +1,6 @@ //! A simple test for testing many permutations of allowedness of //! impl Trait +#![feature(impl_trait_in_fn_trait_return)] use std::fmt::Debug; // Allowed diff --git a/src/test/ui/impl-trait/where-allowed.stderr b/src/test/ui/impl-trait/where-allowed.stderr index 1b704d0d92465..3ad0a9f9d5c8b 100644 --- a/src/test/ui/impl-trait/where-allowed.stderr +++ b/src/test/ui/impl-trait/where-allowed.stderr @@ -1,5 +1,5 @@ error[E0666]: nested `impl Trait` is not allowed - --> $DIR/where-allowed.rs:46:51 + --> $DIR/where-allowed.rs:47:51 | LL | fn in_impl_Fn_parameter_in_parameters(_: &impl Fn(impl Debug)) { panic!() } | --------^^^^^^^^^^- @@ -8,7 +8,7 @@ LL | fn in_impl_Fn_parameter_in_parameters(_: &impl Fn(impl Debug)) { panic!() } | outer `impl Trait` error[E0666]: nested `impl Trait` is not allowed - --> $DIR/where-allowed.rs:55:57 + --> $DIR/where-allowed.rs:56:57 | LL | fn in_impl_Fn_parameter_in_return() -> &'static impl Fn(impl Debug) { panic!() } | --------^^^^^^^^^^- @@ -17,7 +17,7 @@ LL | fn in_impl_Fn_parameter_in_return() -> &'static impl Fn(impl Debug) { panic | outer `impl Trait` error[E0658]: `impl Trait` in type aliases is unstable - --> $DIR/where-allowed.rs:117:16 + --> $DIR/where-allowed.rs:118:16 | LL | type Out = impl Debug; | ^^^^^^^^^^ @@ -26,7 +26,7 @@ LL | type Out = impl Debug; = help: add `#![feature(type_alias_impl_trait)]` to the crate attributes to enable error[E0658]: `impl Trait` in type aliases is unstable - --> $DIR/where-allowed.rs:152:23 + --> $DIR/where-allowed.rs:153:23 | LL | type InTypeAlias = impl Debug; | ^^^^^^^^^^ @@ -35,7 +35,7 @@ LL | type InTypeAlias = impl Debug; = help: add `#![feature(type_alias_impl_trait)]` to the crate attributes to enable error[E0658]: `impl Trait` in type aliases is unstable - --> $DIR/where-allowed.rs:155:39 + --> $DIR/where-allowed.rs:156:39 | LL | type InReturnInTypeAlias = fn() -> impl Debug; | ^^^^^^^^^^ @@ -44,109 +44,109 @@ LL | type InReturnInTypeAlias = fn() -> impl Debug; = help: add `#![feature(type_alias_impl_trait)]` to the crate attributes to enable error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `fn` pointer param - --> $DIR/where-allowed.rs:15:40 + --> $DIR/where-allowed.rs:16:40 | LL | fn in_fn_parameter_in_parameters(_: fn(impl Debug)) { panic!() } | ^^^^^^^^^^ error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `fn` pointer return - --> $DIR/where-allowed.rs:19:42 + --> $DIR/where-allowed.rs:20:42 | LL | fn in_fn_return_in_parameters(_: fn() -> impl Debug) { panic!() } | ^^^^^^^^^^ error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `fn` pointer param - --> $DIR/where-allowed.rs:23:38 + --> $DIR/where-allowed.rs:24:38 | LL | fn in_fn_parameter_in_return() -> fn(impl Debug) { panic!() } | ^^^^^^^^^^ error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `fn` pointer return - --> $DIR/where-allowed.rs:27:40 + --> $DIR/where-allowed.rs:28:40 | LL | fn in_fn_return_in_return() -> fn() -> impl Debug { panic!() } | ^^^^^^^^^^ error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `Fn` trait param - --> $DIR/where-allowed.rs:31:49 + --> $DIR/where-allowed.rs:32:49 | LL | fn in_dyn_Fn_parameter_in_parameters(_: &dyn Fn(impl Debug)) { panic!() } | ^^^^^^^^^^ error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `Fn` trait return - --> $DIR/where-allowed.rs:35:51 + --> $DIR/where-allowed.rs:36:51 | LL | fn in_dyn_Fn_return_in_parameters(_: &dyn Fn() -> impl Debug) { panic!() } | ^^^^^^^^^^ error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `Fn` trait param - --> $DIR/where-allowed.rs:39:55 + --> $DIR/where-allowed.rs:40:55 | LL | fn in_dyn_Fn_parameter_in_return() -> &'static dyn Fn(impl Debug) { panic!() } | ^^^^^^^^^^ error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `Fn` trait param - --> $DIR/where-allowed.rs:46:51 + --> $DIR/where-allowed.rs:47:51 | LL | fn in_impl_Fn_parameter_in_parameters(_: &impl Fn(impl Debug)) { panic!() } | ^^^^^^^^^^ error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `Fn` trait return - --> $DIR/where-allowed.rs:51:53 + --> $DIR/where-allowed.rs:52:53 | LL | fn in_impl_Fn_return_in_parameters(_: &impl Fn() -> impl Debug) { panic!() } | ^^^^^^^^^^ error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `Fn` trait param - --> $DIR/where-allowed.rs:55:57 + --> $DIR/where-allowed.rs:56:57 | LL | fn in_impl_Fn_parameter_in_return() -> &'static impl Fn(impl Debug) { panic!() } | ^^^^^^^^^^ error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `Fn` trait param - --> $DIR/where-allowed.rs:63:38 + --> $DIR/where-allowed.rs:64:38 | LL | fn in_Fn_parameter_in_generics (_: F) { panic!() } | ^^^^^^^^^^ error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `Fn` trait return - --> $DIR/where-allowed.rs:67:40 + --> $DIR/where-allowed.rs:68:40 | LL | fn in_Fn_return_in_generics impl Debug> (_: F) { panic!() } | ^^^^^^^^^^ error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in type - --> $DIR/where-allowed.rs:80:32 + --> $DIR/where-allowed.rs:81:32 | LL | struct InBraceStructField { x: impl Debug } | ^^^^^^^^^^ error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in path - --> $DIR/where-allowed.rs:84:41 + --> $DIR/where-allowed.rs:85:41 | LL | struct InAdtInBraceStructField { x: Vec } | ^^^^^^^^^^ error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in type - --> $DIR/where-allowed.rs:88:27 + --> $DIR/where-allowed.rs:89:27 | LL | struct InTupleStructField(impl Debug); | ^^^^^^^^^^ error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in type - --> $DIR/where-allowed.rs:93:25 + --> $DIR/where-allowed.rs:94:25 | LL | InBraceVariant { x: impl Debug }, | ^^^^^^^^^^ error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in type - --> $DIR/where-allowed.rs:95:20 + --> $DIR/where-allowed.rs:96:20 | LL | InTupleVariant(impl Debug), | ^^^^^^^^^^ error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in trait method return - --> $DIR/where-allowed.rs:106:23 + --> $DIR/where-allowed.rs:107:23 | LL | fn in_return() -> impl Debug; | ^^^^^^^^^^ @@ -155,7 +155,7 @@ LL | fn in_return() -> impl Debug; = help: add `#![feature(return_position_impl_trait_in_trait)]` to the crate attributes to enable error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `impl` method return - --> $DIR/where-allowed.rs:123:34 + --> $DIR/where-allowed.rs:124:34 | LL | fn in_trait_impl_return() -> impl Debug { () } | ^^^^^^^^^^ @@ -164,127 +164,127 @@ LL | fn in_trait_impl_return() -> impl Debug { () } = help: add `#![feature(return_position_impl_trait_in_trait)]` to the crate attributes to enable error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `extern fn` param - --> $DIR/where-allowed.rs:136:33 + --> $DIR/where-allowed.rs:137:33 | LL | fn in_foreign_parameters(_: impl Debug); | ^^^^^^^^^^ error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `extern fn` return - --> $DIR/where-allowed.rs:139:31 + --> $DIR/where-allowed.rs:140:31 | LL | fn in_foreign_return() -> impl Debug; | ^^^^^^^^^^ error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `fn` pointer return - --> $DIR/where-allowed.rs:155:39 + --> $DIR/where-allowed.rs:156:39 | LL | type InReturnInTypeAlias = fn() -> impl Debug; | ^^^^^^^^^^ error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in trait - --> $DIR/where-allowed.rs:160:16 + --> $DIR/where-allowed.rs:161:16 | LL | impl PartialEq for () { | ^^^^^^^^^^ error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in type - --> $DIR/where-allowed.rs:165:24 + --> $DIR/where-allowed.rs:166:24 | LL | impl PartialEq<()> for impl Debug { | ^^^^^^^^^^ error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in type - --> $DIR/where-allowed.rs:170:6 + --> $DIR/where-allowed.rs:171:6 | LL | impl impl Debug { | ^^^^^^^^^^ error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in type - --> $DIR/where-allowed.rs:176:24 + --> $DIR/where-allowed.rs:177:24 | LL | impl InInherentImplAdt { | ^^^^^^^^^^ error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in type - --> $DIR/where-allowed.rs:182:11 + --> $DIR/where-allowed.rs:183:11 | LL | where impl Debug: Debug | ^^^^^^^^^^ error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in type - --> $DIR/where-allowed.rs:189:15 + --> $DIR/where-allowed.rs:190:15 | LL | where Vec: Debug | ^^^^^^^^^^ error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in bound - --> $DIR/where-allowed.rs:196:24 + --> $DIR/where-allowed.rs:197:24 | LL | where T: PartialEq | ^^^^^^^^^^ error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `Fn` trait param - --> $DIR/where-allowed.rs:203:17 + --> $DIR/where-allowed.rs:204:17 | LL | where T: Fn(impl Debug) | ^^^^^^^^^^ error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `Fn` trait return - --> $DIR/where-allowed.rs:210:22 + --> $DIR/where-allowed.rs:211:22 | LL | where T: Fn() -> impl Debug | ^^^^^^^^^^ error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in type - --> $DIR/where-allowed.rs:216:40 + --> $DIR/where-allowed.rs:217:40 | LL | struct InStructGenericParamDefault(T); | ^^^^^^^^^^ error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in type - --> $DIR/where-allowed.rs:220:36 + --> $DIR/where-allowed.rs:221:36 | LL | enum InEnumGenericParamDefault { Variant(T) } | ^^^^^^^^^^ error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in type - --> $DIR/where-allowed.rs:224:38 + --> $DIR/where-allowed.rs:225:38 | LL | trait InTraitGenericParamDefault {} | ^^^^^^^^^^ error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in type - --> $DIR/where-allowed.rs:228:41 + --> $DIR/where-allowed.rs:229:41 | LL | type InTypeAliasGenericParamDefault = T; | ^^^^^^^^^^ error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in type - --> $DIR/where-allowed.rs:232:11 + --> $DIR/where-allowed.rs:233:11 | LL | impl T {} | ^^^^^^^^^^ error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in type - --> $DIR/where-allowed.rs:239:40 + --> $DIR/where-allowed.rs:240:40 | LL | fn in_method_generic_param_default(_: T) {} | ^^^^^^^^^^ error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in variable binding - --> $DIR/where-allowed.rs:245:29 + --> $DIR/where-allowed.rs:246:29 | LL | let _in_local_variable: impl Fn() = || {}; | ^^^^^^^^^ error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in closure return - --> $DIR/where-allowed.rs:247:46 + --> $DIR/where-allowed.rs:248:46 | LL | let _in_return_in_local_variable = || -> impl Fn() { || {} }; | ^^^^^^^^^ error: defaults for type parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions - --> $DIR/where-allowed.rs:232:7 + --> $DIR/where-allowed.rs:233:7 | LL | impl T {} | ^^^^^^^^^^^^^^ @@ -294,7 +294,7 @@ LL | impl T {} = note: `#[deny(invalid_type_param_default)]` on by default error: defaults for type parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions - --> $DIR/where-allowed.rs:239:36 + --> $DIR/where-allowed.rs:240:36 | LL | fn in_method_generic_param_default(_: T) {} | ^^^^^^^^^^^^^^ @@ -303,7 +303,7 @@ LL | fn in_method_generic_param_default(_: T) {} = note: for more information, see issue #36887 error[E0118]: no nominal type found for inherent implementation - --> $DIR/where-allowed.rs:232:23 + --> $DIR/where-allowed.rs:233:23 | LL | impl T {} | ^ impl requires a nominal type From 690e0370081d39c2a4c459e5fd74a6e3728b73a9 Mon Sep 17 00:00:00 2001 From: Maybe Waffle Date: Fri, 29 Jul 2022 02:28:36 +0400 Subject: [PATCH 06/15] add a test for gate `impl_trait_in_fn_trait_return` --- .../feature-gate-impl_trait_in_fn_trait_return.rs | 6 ++++++ ...ture-gate-impl_trait_in_fn_trait_return.stderr | 15 +++++++++++++++ 2 files changed, 21 insertions(+) create mode 100644 src/test/ui/feature-gates/feature-gate-impl_trait_in_fn_trait_return.rs create mode 100644 src/test/ui/feature-gates/feature-gate-impl_trait_in_fn_trait_return.stderr diff --git a/src/test/ui/feature-gates/feature-gate-impl_trait_in_fn_trait_return.rs b/src/test/ui/feature-gates/feature-gate-impl_trait_in_fn_trait_return.rs new file mode 100644 index 0000000000000..0db8088f7eea4 --- /dev/null +++ b/src/test/ui/feature-gates/feature-gate-impl_trait_in_fn_trait_return.rs @@ -0,0 +1,6 @@ +fn f() -> impl Fn() -> impl Sized { || () } +//~^ ERROR `impl Trait` only allowed in function and inherent method return types, not in `Fn` trait return +fn g() -> &'static dyn Fn() -> impl Sized { &|| () } +//~^ ERROR `impl Trait` only allowed in function and inherent method return types, not in `Fn` trait return + +fn main() {} diff --git a/src/test/ui/feature-gates/feature-gate-impl_trait_in_fn_trait_return.stderr b/src/test/ui/feature-gates/feature-gate-impl_trait_in_fn_trait_return.stderr new file mode 100644 index 0000000000000..c485bc5c3ab90 --- /dev/null +++ b/src/test/ui/feature-gates/feature-gate-impl_trait_in_fn_trait_return.stderr @@ -0,0 +1,15 @@ +error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `Fn` trait return + --> $DIR/feature-gate-impl_trait_in_fn_trait_return.rs:1:24 + | +LL | fn f() -> impl Fn() -> impl Sized { || () } + | ^^^^^^^^^^ + +error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `Fn` trait return + --> $DIR/feature-gate-impl_trait_in_fn_trait_return.rs:3:32 + | +LL | fn g() -> &'static dyn Fn() -> impl Sized { &|| () } + | ^^^^^^^^^^ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0562`. From e93982a78fc7725f4fd01c39b2c48b6a2028893f Mon Sep 17 00:00:00 2001 From: Maybe Waffle Date: Tue, 25 Oct 2022 13:47:43 +0000 Subject: [PATCH 07/15] adopt to compiler changes --- compiler/rustc_ast_lowering/src/path.rs | 2 +- .../impl-fn-predefined-lifetimes.rs | 4 ++- .../impl-fn-predefined-lifetimes.stderr | 25 +++++++++++++------ 3 files changed, 21 insertions(+), 10 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/path.rs b/compiler/rustc_ast_lowering/src/path.rs index b7cda13fa4b70..c6955741fd4c2 100644 --- a/compiler/rustc_ast_lowering/src/path.rs +++ b/compiler/rustc_ast_lowering/src/path.rs @@ -346,7 +346,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { fn lower_parenthesized_parameter_data( &mut self, data: &ParenthesizedArgs, - itctx: ImplTraitContext, + itctx: &ImplTraitContext, ) -> (GenericArgsCtor<'hir>, bool) { // Switch to `PassThrough` mode for anonymous lifetimes; this // means that we permit things like `&Ref`, where `Ref` has diff --git a/src/test/ui/impl-trait/impl-fn-predefined-lifetimes.rs b/src/test/ui/impl-trait/impl-fn-predefined-lifetimes.rs index 5e2379b2f9af6..1577866237544 100644 --- a/src/test/ui/impl-trait/impl-fn-predefined-lifetimes.rs +++ b/src/test/ui/impl-trait/impl-fn-predefined-lifetimes.rs @@ -2,8 +2,10 @@ use std::fmt::Debug; fn a<'a>() -> impl Fn(&'a u8) -> (impl Debug + '_) { - //~^ ERROR hidden type for `impl Debug` captures lifetime that does not appear in bounds + //~^ ERROR cannot resolve opaque type + |x| x + //~^ ERROR concrete type differs from previous defining opaque type use } fn _b<'a>() -> impl Fn(&'a u8) -> (impl Debug + 'a) { diff --git a/src/test/ui/impl-trait/impl-fn-predefined-lifetimes.stderr b/src/test/ui/impl-trait/impl-fn-predefined-lifetimes.stderr index 1247ffad7c324..7747319c1539b 100644 --- a/src/test/ui/impl-trait/impl-fn-predefined-lifetimes.stderr +++ b/src/test/ui/impl-trait/impl-fn-predefined-lifetimes.stderr @@ -1,15 +1,24 @@ -error[E0700]: hidden type for `impl Debug` captures lifetime that does not appear in bounds - --> $DIR/impl-fn-predefined-lifetimes.rs:4:35 +error: concrete type differs from previous defining opaque type use + --> $DIR/impl-fn-predefined-lifetimes.rs:7:9 | -LL | fn a<'a>() -> impl Fn(&'a u8) -> (impl Debug + '_) { - | ^^^^^^^^^^^^^^^ +LL | |x| x + | ^ expected `impl Debug + '_`, got `&u8` | -note: hidden type `&' u8` captures lifetime smaller than the function body +note: previous use here + --> $DIR/impl-fn-predefined-lifetimes.rs:7:5 + | +LL | |x| x + | ^^^^^ + +error[E0720]: cannot resolve opaque type --> $DIR/impl-fn-predefined-lifetimes.rs:4:35 | LL | fn a<'a>() -> impl Fn(&'a u8) -> (impl Debug + '_) { - | ^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^ recursive opaque type +... +LL | |x| x + | ----- returning here with type `[closure@$DIR/impl-fn-predefined-lifetimes.rs:7:5: 7:8]` -error: aborting due to previous error +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0700`. +For more information about this error, try `rustc --explain E0720`. From be61f0237b95083d26ce32fb0934dd42caf6ea07 Mon Sep 17 00:00:00 2001 From: Byron Zhong Date: Tue, 25 Oct 2022 01:14:39 -0500 Subject: [PATCH 08/15] Add Span in TypoSuggestion and TypoCandidate --- compiler/rustc_resolve/src/diagnostics.rs | 45 +++++++++++++------ .../rustc_resolve/src/late/diagnostics.rs | 24 ++++------ 2 files changed, 39 insertions(+), 30 deletions(-) diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs index 5d868ebec9448..5029c33996329 100644 --- a/compiler/rustc_resolve/src/diagnostics.rs +++ b/compiler/rustc_resolve/src/diagnostics.rs @@ -58,16 +58,32 @@ pub(crate) enum SuggestionTarget { #[derive(Debug)] pub(crate) struct TypoSuggestion { pub candidate: Symbol, + /// The source location where the name is defined; None if the name is not defined + /// in source e.g. primitives + pub span: Option, pub res: Res, pub target: SuggestionTarget, } impl TypoSuggestion { - pub(crate) fn typo_from_res(candidate: Symbol, res: Res) -> TypoSuggestion { - Self { candidate, res, target: SuggestionTarget::SimilarlyNamed } + pub(crate) fn typo_from_ident(ident: Ident, res: Res) -> TypoSuggestion { + Self { + candidate: ident.name, + span: Some(ident.span), + res, + target: SuggestionTarget::SimilarlyNamed, + } + } + pub(crate) fn typo_from_name(candidate: Symbol, res: Res) -> TypoSuggestion { + Self { candidate, span: None, res, target: SuggestionTarget::SimilarlyNamed } } - pub(crate) fn single_item_from_res(candidate: Symbol, res: Res) -> TypoSuggestion { - Self { candidate, res, target: SuggestionTarget::SingleItem } + pub(crate) fn single_item_from_ident(ident: Ident, res: Res) -> TypoSuggestion { + Self { + candidate: ident.name, + span: Some(ident.span), + res, + target: SuggestionTarget::SingleItem, + } } } @@ -490,7 +506,7 @@ impl<'a> Resolver<'a> { if let Some(binding) = resolution.borrow().binding { let res = binding.res(); if filter_fn(res) && ctxt.map_or(true, |ctxt| ctxt == key.ident.span.ctxt()) { - names.push(TypoSuggestion::typo_from_res(key.ident.name, res)); + names.push(TypoSuggestion::typo_from_ident(key.ident, res)); } } } @@ -1145,7 +1161,7 @@ impl<'a> Resolver<'a> { .get(&expn_id) .into_iter() .flatten() - .map(|ident| TypoSuggestion::typo_from_res(ident.name, res)), + .map(|ident| TypoSuggestion::typo_from_ident(*ident, res)), ); } } @@ -1164,7 +1180,7 @@ impl<'a> Resolver<'a> { suggestions.extend( ext.helper_attrs .iter() - .map(|name| TypoSuggestion::typo_from_res(*name, res)), + .map(|name| TypoSuggestion::typo_from_name(*name, res)), ); } } @@ -1174,8 +1190,8 @@ impl<'a> Resolver<'a> { if let MacroRulesScope::Binding(macro_rules_binding) = macro_rules_scope.get() { let res = macro_rules_binding.binding.res(); if filter_fn(res) { - suggestions.push(TypoSuggestion::typo_from_res( - macro_rules_binding.ident.name, + suggestions.push(TypoSuggestion::typo_from_ident( + macro_rules_binding.ident, res, )) } @@ -1193,7 +1209,7 @@ impl<'a> Resolver<'a> { suggestions.extend(this.macro_use_prelude.iter().filter_map( |(name, binding)| { let res = binding.res(); - filter_fn(res).then_some(TypoSuggestion::typo_from_res(*name, res)) + filter_fn(res).then_some(TypoSuggestion::typo_from_name(*name, res)) }, )); } @@ -1203,14 +1219,14 @@ impl<'a> Resolver<'a> { suggestions.extend( BUILTIN_ATTRIBUTES .iter() - .map(|attr| TypoSuggestion::typo_from_res(attr.name, res)), + .map(|attr| TypoSuggestion::typo_from_name(attr.name, res)), ); } } Scope::ExternPrelude => { suggestions.extend(this.extern_prelude.iter().filter_map(|(ident, _)| { let res = Res::Def(DefKind::Mod, CRATE_DEF_ID.to_def_id()); - filter_fn(res).then_some(TypoSuggestion::typo_from_res(ident.name, res)) + filter_fn(res).then_some(TypoSuggestion::typo_from_ident(*ident, res)) })); } Scope::ToolPrelude => { @@ -1218,7 +1234,7 @@ impl<'a> Resolver<'a> { suggestions.extend( this.registered_tools .iter() - .map(|ident| TypoSuggestion::typo_from_res(ident.name, res)), + .map(|ident| TypoSuggestion::typo_from_ident(*ident, res)), ); } Scope::StdLibPrelude => { @@ -1235,7 +1251,8 @@ impl<'a> Resolver<'a> { Scope::BuiltinTypes => { suggestions.extend(PrimTy::ALL.iter().filter_map(|prim_ty| { let res = Res::PrimTy(*prim_ty); - filter_fn(res).then_some(TypoSuggestion::typo_from_res(prim_ty.name(), res)) + filter_fn(res) + .then_some(TypoSuggestion::typo_from_name(prim_ty.name(), res)) })) } } diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs index 850f023b1c16b..8da09489b1f18 100644 --- a/compiler/rustc_resolve/src/late/diagnostics.rs +++ b/compiler/rustc_resolve/src/late/diagnostics.rs @@ -150,7 +150,7 @@ struct BaseError { #[derive(Debug)] enum TypoCandidate { Typo(TypoSuggestion), - Shadowed(Res), + Shadowed(Res, Option), None, } @@ -158,7 +158,7 @@ impl TypoCandidate { fn to_opt_suggestion(self) -> Option { match self { TypoCandidate::Typo(sugg) => Some(sugg), - TypoCandidate::Shadowed(_) | TypoCandidate::None => None, + TypoCandidate::Shadowed(_, _) | TypoCandidate::None => None, } } } @@ -691,10 +691,7 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> { let is_expected = &|res| source.is_expected(res); let ident_span = path.last().map_or(span, |ident| ident.ident.span); let typo_sugg = self.lookup_typo_candidate(path, source.namespace(), is_expected); - if let TypoCandidate::Shadowed(res) = typo_sugg - && let Some(id) = res.opt_def_id() - && let Some(sugg_span) = self.r.opt_span(id) - { + if let TypoCandidate::Shadowed(res, Some(sugg_span)) = typo_sugg { err.span_label( sugg_span, format!("you might have meant to refer to this {}", res.descr()), @@ -973,10 +970,7 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> { .collect(); if targets.len() == 1 { let target = targets[0]; - return Some(TypoSuggestion::single_item_from_res( - target.0.ident.name, - target.1, - )); + return Some(TypoSuggestion::single_item_from_ident(target.0.ident, target.1)); } } } @@ -1618,7 +1612,7 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> { // Locals and type parameters for (ident, &res) in &rib.bindings { if filter_fn(res) && ident.span.ctxt() == rib_ctxt { - names.push(TypoSuggestion::typo_from_res(ident.name, res)); + names.push(TypoSuggestion::typo_from_ident(*ident, res)); } } @@ -1647,9 +1641,7 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> { Res::Def(DefKind::Mod, crate_id.as_def_id()); if filter_fn(crate_mod) { - Some(TypoSuggestion::typo_from_res( - ident.name, crate_mod, - )) + Some(TypoSuggestion::typo_from_ident(*ident, crate_mod)) } else { None } @@ -1668,7 +1660,7 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> { // Add primitive types to the mix if filter_fn(Res::PrimTy(PrimTy::Bool)) { names.extend(PrimTy::ALL.iter().map(|prim_ty| { - TypoSuggestion::typo_from_res(prim_ty.name(), Res::PrimTy(*prim_ty)) + TypoSuggestion::typo_from_name(prim_ty.name(), Res::PrimTy(*prim_ty)) })) } } else { @@ -1695,7 +1687,7 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> { return TypoCandidate::None; }; if found == name { - TypoCandidate::Shadowed(sugg.res) + TypoCandidate::Shadowed(sugg.res, sugg.span) } else { TypoCandidate::Typo(sugg) } From 0b936d2da702848a4d537e745921636490e93060 Mon Sep 17 00:00:00 2001 From: Byron Zhong Date: Tue, 25 Oct 2022 12:35:04 -0500 Subject: [PATCH 09/15] Add check to only output 'you might have meant' when the candidate name is in the same crate --- compiler/rustc_resolve/src/late/diagnostics.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs index 8da09489b1f18..dfbd982bb7c32 100644 --- a/compiler/rustc_resolve/src/late/diagnostics.rs +++ b/compiler/rustc_resolve/src/late/diagnostics.rs @@ -691,7 +691,8 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> { let is_expected = &|res| source.is_expected(res); let ident_span = path.last().map_or(span, |ident| ident.ident.span); let typo_sugg = self.lookup_typo_candidate(path, source.namespace(), is_expected); - if let TypoCandidate::Shadowed(res, Some(sugg_span)) = typo_sugg { + let is_local = &|res: Res| res.opt_def_id().map_or(false, |id| id.is_local()); + if let TypoCandidate::Shadowed(res, Some(sugg_span)) = typo_sugg && is_local(res) { err.span_label( sugg_span, format!("you might have meant to refer to this {}", res.descr()), From 775328c290599a05f42ee2fd7ed0a414847995fc Mon Sep 17 00:00:00 2001 From: Byron Zhong Date: Tue, 25 Oct 2022 17:29:29 -0500 Subject: [PATCH 10/15] Modify check to output 'you might have meant' for indirect reference --- compiler/rustc_resolve/src/late/diagnostics.rs | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs index dfbd982bb7c32..dea025310d3ca 100644 --- a/compiler/rustc_resolve/src/late/diagnostics.rs +++ b/compiler/rustc_resolve/src/late/diagnostics.rs @@ -691,8 +691,21 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> { let is_expected = &|res| source.is_expected(res); let ident_span = path.last().map_or(span, |ident| ident.ident.span); let typo_sugg = self.lookup_typo_candidate(path, source.namespace(), is_expected); - let is_local = &|res: Res| res.opt_def_id().map_or(false, |id| id.is_local()); - if let TypoCandidate::Shadowed(res, Some(sugg_span)) = typo_sugg && is_local(res) { + let is_in_same_file = &|sp1, sp2| { + let source_map = self.r.session.source_map(); + let file1 = source_map.span_to_filename(sp1); + let file2 = source_map.span_to_filename(sp2); + file1 == file2 + }; + // print 'you might have meant' if the candidate is (1) is a shadowed name with + // accessible definition and (2) either defined in the same crate as the typo + // (could be in a different file) or introduced in the same file as the typo + // (could belong to a different crate) + if let TypoCandidate::Shadowed(res, Some(sugg_span)) = typo_sugg + && res + .opt_def_id() + .map_or(false, |id| id.is_local() || is_in_same_file(span, sugg_span)) + { err.span_label( sugg_span, format!("you might have meant to refer to this {}", res.descr()), From 0eaf6d518026ccc4bd97444cd6a485accdc79878 Mon Sep 17 00:00:00 2001 From: Byron Zhong Date: Tue, 25 Oct 2022 17:50:11 -0500 Subject: [PATCH 11/15] Modify ui tests to reflect the change --- src/test/ui/lexical-scopes.stderr | 2 +- ...-type-parameter-shadowing-another-type.stderr | 16 +++++++--------- src/test/ui/span/issue-35987.stderr | 3 +++ 3 files changed, 11 insertions(+), 10 deletions(-) diff --git a/src/test/ui/lexical-scopes.stderr b/src/test/ui/lexical-scopes.stderr index 535985452232d..f0eaa1a5c64c4 100644 --- a/src/test/ui/lexical-scopes.stderr +++ b/src/test/ui/lexical-scopes.stderr @@ -2,7 +2,7 @@ error[E0574]: expected struct, variant or union type, found type parameter `T` --> $DIR/lexical-scopes.rs:3:13 | LL | struct T { i: i32 } - | ------------------- you might have meant to refer to this struct + | - you might have meant to refer to this struct LL | fn f() { | - found this type parameter LL | let t = T { i: 0 }; diff --git a/src/test/ui/resolve/point-at-type-parameter-shadowing-another-type.stderr b/src/test/ui/resolve/point-at-type-parameter-shadowing-another-type.stderr index eb26cd9cabb82..5790e425c0a23 100644 --- a/src/test/ui/resolve/point-at-type-parameter-shadowing-another-type.stderr +++ b/src/test/ui/resolve/point-at-type-parameter-shadowing-another-type.stderr @@ -1,16 +1,14 @@ error[E0574]: expected struct, variant or union type, found type parameter `Baz` --> $DIR/point-at-type-parameter-shadowing-another-type.rs:16:13 | -LL | / struct Baz { -LL | | num: usize, -LL | | } - | |_- you might have meant to refer to this struct -LL | -LL | impl Foo for Bar { - | --- found this type parameter +LL | struct Baz { + | --- you might have meant to refer to this struct ... -LL | Baz { num } => num, - | ^^^ not a struct, variant or union type +LL | impl Foo for Bar { + | --- found this type parameter +... +LL | Baz { num } => num, + | ^^^ not a struct, variant or union type error: aborting due to previous error diff --git a/src/test/ui/span/issue-35987.stderr b/src/test/ui/span/issue-35987.stderr index d8fddc8007f50..057d40ac0cb92 100644 --- a/src/test/ui/span/issue-35987.stderr +++ b/src/test/ui/span/issue-35987.stderr @@ -1,6 +1,9 @@ error[E0404]: expected trait, found type parameter `Add` --> $DIR/issue-35987.rs:5:21 | +LL | use std::ops::Add; + | --- you might have meant to refer to this trait +LL | LL | impl Add for Foo { | --- ^^^ not a trait | | From ddba6c1e6c7b6e2f1bdff54e314831cec8a4a954 Mon Sep 17 00:00:00 2001 From: Weihang Lo Date: Wed, 26 Oct 2022 23:59:27 +0800 Subject: [PATCH 12/15] doc(rustdoc): redirect more urls --- src/doc/rustdoc/book.toml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/doc/rustdoc/book.toml b/src/doc/rustdoc/book.toml index 45405a11765cc..dfa6857850083 100644 --- a/src/doc/rustdoc/book.toml +++ b/src/doc/rustdoc/book.toml @@ -6,5 +6,9 @@ title = "The rustdoc book" git-repository-url = "https://github.com/rust-lang/rust/tree/master/src/doc/rustdoc" [output.html.redirect] +"/what-to-include.html" = "write-documentation/what-to-include.html" "/the-doc-attribute.html" = "write-documentation/the-doc-attribute.html" +"/linking-to-items-by-name.html" = "write-documentation/linking-to-items-by-name.html" "/documentation-tests.html" = "write-documentation/documentation-tests.html" +"/website-features.html" = "advanced-features.html#custom-search-engines" +"/passes.html" = "deprecated-features.html#passes" From 06692ea4441b168b279ec6fbdd8311d0444cbc4c Mon Sep 17 00:00:00 2001 From: Weihang Lo Date: Thu, 27 Oct 2022 00:01:15 +0800 Subject: [PATCH 13/15] fix(rustdoc): add missing URL component for error messages --- src/librustdoc/passes/collect_intra_doc_links.rs | 2 +- .../intra-doc/unknown-disambiguator.stderr | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs index 3513c13d522f1..70ae5e9d99de3 100644 --- a/src/librustdoc/passes/collect_intra_doc_links.rs +++ b/src/librustdoc/passes/collect_intra_doc_links.rs @@ -1893,7 +1893,7 @@ fn disambiguator_error( diag_info.link_range = disambiguator_range; report_diagnostic(cx.tcx, BROKEN_INTRA_DOC_LINKS, msg, &diag_info, |diag, _sp| { let msg = format!( - "see {}/rustdoc/linking-to-items-by-name.html#namespaces-and-disambiguators for more info about disambiguators", + "see {}/rustdoc/write-documentation/linking-to-items-by-name.html#namespaces-and-disambiguators for more info about disambiguators", crate::DOC_RUST_LANG_ORG_CHANNEL ); diag.note(&msg); diff --git a/src/test/rustdoc-ui/intra-doc/unknown-disambiguator.stderr b/src/test/rustdoc-ui/intra-doc/unknown-disambiguator.stderr index e7b4c43e790ed..19e541736bd04 100644 --- a/src/test/rustdoc-ui/intra-doc/unknown-disambiguator.stderr +++ b/src/test/rustdoc-ui/intra-doc/unknown-disambiguator.stderr @@ -4,7 +4,7 @@ error: unknown disambiguator `foo` LL | //! Linking to [foo@banana] and [`bar@banana!()`]. | ^^^ | - = note: see https://doc.rust-lang.org/$CHANNEL/rustdoc/linking-to-items-by-name.html#namespaces-and-disambiguators for more info about disambiguators + = note: see https://doc.rust-lang.org/$CHANNEL/rustdoc/write-documentation/linking-to-items-by-name.html#namespaces-and-disambiguators for more info about disambiguators note: the lint level is defined here --> $DIR/unknown-disambiguator.rs:2:9 | @@ -18,7 +18,7 @@ error: unknown disambiguator `bar` LL | //! Linking to [foo@banana] and [`bar@banana!()`]. | ^^^ | - = note: see https://doc.rust-lang.org/$CHANNEL/rustdoc/linking-to-items-by-name.html#namespaces-and-disambiguators for more info about disambiguators + = note: see https://doc.rust-lang.org/$CHANNEL/rustdoc/write-documentation/linking-to-items-by-name.html#namespaces-and-disambiguators for more info about disambiguators error: unknown disambiguator `foo` --> $DIR/unknown-disambiguator.rs:10:34 @@ -26,7 +26,7 @@ error: unknown disambiguator `foo` LL | //! And with weird backticks: [``foo@hello``] [foo`@`hello]. | ^^^ | - = note: see https://doc.rust-lang.org/$CHANNEL/rustdoc/linking-to-items-by-name.html#namespaces-and-disambiguators for more info about disambiguators + = note: see https://doc.rust-lang.org/$CHANNEL/rustdoc/write-documentation/linking-to-items-by-name.html#namespaces-and-disambiguators for more info about disambiguators error: unknown disambiguator `foo` --> $DIR/unknown-disambiguator.rs:10:48 @@ -34,7 +34,7 @@ error: unknown disambiguator `foo` LL | //! And with weird backticks: [``foo@hello``] [foo`@`hello]. | ^^^ | - = note: see https://doc.rust-lang.org/$CHANNEL/rustdoc/linking-to-items-by-name.html#namespaces-and-disambiguators for more info about disambiguators + = note: see https://doc.rust-lang.org/$CHANNEL/rustdoc/write-documentation/linking-to-items-by-name.html#namespaces-and-disambiguators for more info about disambiguators error: unknown disambiguator `` --> $DIR/unknown-disambiguator.rs:7:31 @@ -42,7 +42,7 @@ error: unknown disambiguator `` LL | //! And to [no disambiguator](@nectarine) and [another](@apricot!()). | ^ | - = note: see https://doc.rust-lang.org/$CHANNEL/rustdoc/linking-to-items-by-name.html#namespaces-and-disambiguators for more info about disambiguators + = note: see https://doc.rust-lang.org/$CHANNEL/rustdoc/write-documentation/linking-to-items-by-name.html#namespaces-and-disambiguators for more info about disambiguators error: unknown disambiguator `` --> $DIR/unknown-disambiguator.rs:7:57 @@ -50,7 +50,7 @@ error: unknown disambiguator `` LL | //! And to [no disambiguator](@nectarine) and [another](@apricot!()). | ^ | - = note: see https://doc.rust-lang.org/$CHANNEL/rustdoc/linking-to-items-by-name.html#namespaces-and-disambiguators for more info about disambiguators + = note: see https://doc.rust-lang.org/$CHANNEL/rustdoc/write-documentation/linking-to-items-by-name.html#namespaces-and-disambiguators for more info about disambiguators error: aborting due to 6 previous errors From 17b86cb6116ab25d5fdd9ec406738ad0720c702c Mon Sep 17 00:00:00 2001 From: Ben Kimock Date: Tue, 26 Jul 2022 17:40:48 -0400 Subject: [PATCH 14/15] Do fewer passes and generally be more efficient when filtering tests --- library/test/src/console.rs | 6 +-- library/test/src/event.rs | 2 +- library/test/src/lib.rs | 87 ++++++++++++++++++++++++++----------- 3 files changed, 66 insertions(+), 29 deletions(-) diff --git a/library/test/src/console.rs b/library/test/src/console.rs index b1270c272710d..8cb88016b23ad 100644 --- a/library/test/src/console.rs +++ b/library/test/src/console.rs @@ -228,9 +228,9 @@ fn on_test_event( out: &mut dyn OutputFormatter, ) -> io::Result<()> { match (*event).clone() { - TestEvent::TeFiltered(ref filtered_tests, shuffle_seed) => { - st.total = filtered_tests.len(); - out.write_run_start(filtered_tests.len(), shuffle_seed)?; + TestEvent::TeFiltered(filtered_tests, shuffle_seed) => { + st.total = filtered_tests; + out.write_run_start(filtered_tests, shuffle_seed)?; } TestEvent::TeFilteredOut(filtered_out) => { st.filtered_out = filtered_out; diff --git a/library/test/src/event.rs b/library/test/src/event.rs index 6ff1a615eb4d0..80281ebd2d4cd 100644 --- a/library/test/src/event.rs +++ b/library/test/src/event.rs @@ -28,7 +28,7 @@ impl CompletedTest { #[derive(Debug, Clone)] pub enum TestEvent { - TeFiltered(Vec, Option), + TeFiltered(usize, Option), TeWait(TestDesc), TeResult(CompletedTest), TeTimeout(TestDesc), diff --git a/library/test/src/lib.rs b/library/test/src/lib.rs index 141f16d17f022..56a8d92f55db2 100644 --- a/library/test/src/lib.rs +++ b/library/test/src/lib.rs @@ -219,6 +219,35 @@ pub fn assert_test_result(result: T) -> Result<(), String> { } } +struct FilteredTests { + tests: Vec<(TestId, TestDescAndFn)>, + benchs: Vec<(TestId, TestDescAndFn)>, + next_id: usize, +} + +impl FilteredTests { + fn add_bench(&mut self, desc: TestDesc, testfn: TestFn) { + let test = TestDescAndFn { desc, testfn }; + self.benchs.push((TestId(self.next_id), test)); + self.next_id += 1; + } + fn add_test(&mut self, desc: TestDesc, testfn: TestFn) { + let test = TestDescAndFn { desc, testfn }; + self.tests.push((TestId(self.next_id), test)); + self.next_id += 1; + } + fn add_bench_as_test( + &mut self, + desc: TestDesc, + benchfn: impl Fn(&mut Bencher) -> Result<(), String> + Send + 'static, + ) { + let testfn = DynTestFn(Box::new(move || { + bench::run_once(|b| __rust_begin_short_backtrace(|| benchfn(b))) + })); + self.add_test(desc, testfn); + } +} + pub fn run_tests( opts: &TestOpts, tests: Vec, @@ -247,45 +276,51 @@ where let tests_len = tests.len(); - let mut filtered_tests = filter_tests(opts, tests); - if !opts.bench_benchmarks { - filtered_tests = convert_benchmarks_to_tests(filtered_tests); - } + let mut filtered = FilteredTests { tests: Vec::new(), benchs: Vec::new(), next_id: 0 }; - let filtered_tests = { - let mut filtered_tests = filtered_tests; - for test in filtered_tests.iter_mut() { - test.desc.name = test.desc.name.with_padding(test.testfn.padding()); - } + for test in filter_tests(opts, tests) { + let mut desc = test.desc; + desc.name = desc.name.with_padding(test.testfn.padding()); - filtered_tests - }; + match test.testfn { + DynBenchFn(benchfn) => { + if opts.bench_benchmarks { + filtered.add_bench(desc, DynBenchFn(benchfn)); + } else { + filtered.add_bench_as_test(desc, benchfn); + } + } + StaticBenchFn(benchfn) => { + if opts.bench_benchmarks { + filtered.add_bench(desc, StaticBenchFn(benchfn)); + } else { + filtered.add_bench_as_test(desc, benchfn); + } + } + testfn => { + filtered.add_test(desc, testfn); + } + }; + } - let filtered_out = tests_len - filtered_tests.len(); + let filtered_out = tests_len - filtered.tests.len(); let event = TestEvent::TeFilteredOut(filtered_out); notify_about_test_event(event)?; - let filtered_descs = filtered_tests.iter().map(|t| t.desc.clone()).collect(); - let shuffle_seed = get_shuffle_seed(opts); - let event = TestEvent::TeFiltered(filtered_descs, shuffle_seed); + let event = TestEvent::TeFiltered(filtered.tests.len(), shuffle_seed); notify_about_test_event(event)?; - let (mut filtered_tests, filtered_benchs): (Vec<_>, _) = filtered_tests - .into_iter() - .enumerate() - .map(|(i, e)| (TestId(i), e)) - .partition(|(_, e)| matches!(e.testfn, StaticTestFn(_) | DynTestFn(_))); - let concurrency = opts.test_threads.unwrap_or_else(get_concurrency); + let mut remaining = filtered.tests; if let Some(shuffle_seed) = shuffle_seed { - shuffle_tests(shuffle_seed, &mut filtered_tests); + shuffle_tests(shuffle_seed, &mut remaining); } // Store the tests in a VecDeque so we can efficiently remove the first element to run the // tests in the order they were passed (unless shuffled). - let mut remaining = VecDeque::from(filtered_tests); + let mut remaining = VecDeque::from(remaining); let mut pending = 0; let (tx, rx) = channel::(); @@ -402,7 +437,7 @@ where if opts.bench_benchmarks { // All benchmarks run at the end, in serial. - for (id, b) in filtered_benchs { + for (id, b) in filtered.benchs { let event = TestEvent::TeWait(b.desc.clone()); notify_about_test_event(event)?; run_test(opts, false, id, b, run_strategy, tx.clone(), Concurrent::No); @@ -432,7 +467,9 @@ pub fn filter_tests(opts: &TestOpts, tests: Vec) -> Vec Date: Sat, 29 Oct 2022 09:59:53 -0700 Subject: [PATCH 15/15] rustdoc: remove unnecessary `.search-results { padding-bottom }` There's nothing underneath it anyway. The conversation on b615c0c85469c94041a5e68b9d8b68dcf799f9f1 never really spelled out why it was added. --- src/librustdoc/html/static/css/rustdoc.css | 1 - 1 file changed, 1 deletion(-) diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css index 09371dc027b80..f301776aa7d11 100644 --- a/src/librustdoc/html/static/css/rustdoc.css +++ b/src/librustdoc/html/static/css/rustdoc.css @@ -878,7 +878,6 @@ so that we can apply CSS-filters to change the arrow color in themes */ .search-results { display: none; - padding-bottom: 2em; } .search-results.active {