From 8b494f427cb06896996fb02ac8c3ff745fde4d15 Mon Sep 17 00:00:00 2001 From: Maybe Waffle Date: Wed, 2 Feb 2022 15:09:44 +0300 Subject: [PATCH 1/7] 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 888776cccac..4b7ef960d4b 100644 --- a/compiler/rustc_ast_lowering/src/path.rs +++ b/compiler/rustc_ast_lowering/src/path.rs @@ -191,7 +191,9 @@ pub(crate) fn lower_path_segment( 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 @@ pub(crate) fn lower_angle_bracketed_parameter_data( 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 @@ fn lower_parenthesized_parameter_data( 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 00000000000..f5f1909cf58 --- /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 85c6f8c462c..9b0dbacaded 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 3291cad6882..e2ce7d15a06 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 c1dd46c7ff7..d337ab422d7 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 2e7c7ca40dd..1b704d0d924 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 2/7] 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 00000000000..688ae1da5e3 --- /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 00000000000..57f618d11f9 --- /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 00000000000..f7d9430a226 --- /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 00000000000..6fe4534d928 --- /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 00000000000..053912aa816 --- /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 00000000000..e54864443ae --- /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 f5f1909cf58..6accaed98c9 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 3/7] 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 f7d9430a226..25144c09048 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 6fe4534d928..6985c66df87 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 00000000000..e2f6e600da4 --- /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 4/7] 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 4b7ef960d4b..b7cda13fa4b 100644 --- a/compiler/rustc_ast_lowering/src/path.rs +++ b/compiler/rustc_ast_lowering/src/path.rs @@ -363,7 +363,10 @@ fn lower_parenthesized_parameter_data( // 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 1b8d683b133..5656409c0d4 100644 --- a/compiler/rustc_feature/src/active.rs +++ b/compiler/rustc_feature/src/active.rs @@ -414,6 +414,8 @@ pub fn set(&self, features: &mut Features, span: Span) { (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 3fe79370c37..21016602ff8 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -813,6 +813,7 @@ 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 5/7] --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 | 79 ++++++++-------- .../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, 125 insertions(+), 108 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 688ae1da5e3..b0aeded0ef7 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 57f618d11f9..433b76b7afa 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 25144c09048..527a4586fd7 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 6985c66df87..443ffeb55cd 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: 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: 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 + --> $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 - = 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: higher kinded lifetime bounds on nested opaque types are not supported yet + --> $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: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:9:52 + | +LL | fn b() -> impl for<'a> Fn(&'a u8) -> (impl Debug + 'a) { + | ^^ + | +note: lifetime declared here + --> $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:14:52 + | +LL | fn c() -> impl for<'a> Fn(&'a u8) -> (impl Debug + '_) { + | ^^ + | +note: lifetime declared here + --> $DIR/impl-fn-hrtb-bounds.rs:14:20 + | +LL | fn c() -> impl for<'a> Fn(&'a u8) -> (impl Debug + '_) { + | ^^ + 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 053912aa816..3e760710797 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 e54864443ae..cf6e5ef7bac 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 e2f6e600da4..5e2379b2f9a 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 00000000000..1247ffad7c3 --- /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 6accaed98c9..71a8f9c7796 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 9b0dbacaded..e95fab3b650 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 e2ce7d15a06..9a8f5a34068 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 d337ab422d7..ff63b04c268 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 1b704d0d924..3ad0a9f9d5c 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 6/7] 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 00000000000..0db8088f7ee --- /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 00000000000..c485bc5c3ab --- /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 7/7] adopt to compiler changes --- compiler/rustc_ast_lowering/src/path.rs | 2 +- .../impl-fn-predefined-lifetimes.rs | 4 ++- .../impl-fn-predefined-lifetimes.stderr | 29 ++++++++++++------- 3 files changed, 23 insertions(+), 12 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/path.rs b/compiler/rustc_ast_lowering/src/path.rs index b7cda13fa4b..c6955741fd4 100644 --- a/compiler/rustc_ast_lowering/src/path.rs +++ b/compiler/rustc_ast_lowering/src/path.rs @@ -346,7 +346,7 @@ pub(crate) fn lower_angle_bracketed_parameter_data( 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 5e2379b2f9a..15778662375 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 1247ffad7c3..7747319c153 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 +error: concrete type differs from previous defining opaque type use + --> $DIR/impl-fn-predefined-lifetimes.rs:7:9 + | +LL | |x| x + | ^ expected `impl Debug + '_`, got `&u8` + | +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 + '_) { - | ^^^^^^^^^^^^^^^ - | -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 + '_) { - | ^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^ 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`.