From 75f72c0de141573eef56f13fd48a3af12deaee4f Mon Sep 17 00:00:00 2001 From: Taylor Cramer Date: Thu, 8 Feb 2018 15:40:27 -0800 Subject: [PATCH 1/5] Make nested impl Trait a hard error --- src/librustc_passes/ast_validation.rs | 69 ++++++++++++++++++ src/librustc_passes/diagnostics.rs | 1 + src/libsyntax/feature_gate.rs | 70 +------------------ .../compile-fail/impl-trait/where-allowed.rs | 4 +- src/test/run-pass/impl-trait/lifetimes.rs | 11 ++- src/test/ui/error-codes/E0657.rs | 6 +- .../nested_impl_trait.rs} | 10 +-- src/test/ui/nested_impl_trait.stderr | 50 +++++++++++++ 8 files changed, 138 insertions(+), 83 deletions(-) rename src/test/{compile-fail/feature-gate-nested_impl_trait.rs => ui/nested_impl_trait.rs} (80%) create mode 100644 src/test/ui/nested_impl_trait.stderr diff --git a/src/librustc_passes/ast_validation.rs b/src/librustc_passes/ast_validation.rs index 6971033c8994b..826f27c2ddbf4 100644 --- a/src/librustc_passes/ast_validation.rs +++ b/src/librustc_passes/ast_validation.rs @@ -420,6 +420,75 @@ impl<'a> Visitor<'a> for AstValidator<'a> { } } +// Bans nested `impl Trait`, e.g. `impl Into`. +// Nested `impl Trait` _is_ allowed in associated type position, +// e.g `impl Iterator` +struct NestedImplTraitVisitor<'a> { + session: &'a Session, + outer_impl_trait: Option, +} + +impl<'a> NestedImplTraitVisitor<'a> { + fn with_impl_trait(&mut self, outer_impl_trait: Option, f: F) + where F: FnOnce(&mut NestedImplTraitVisitor<'a>) + { + let old_outer_impl_trait = self.outer_impl_trait; + self.outer_impl_trait = outer_impl_trait; + f(self); + self.outer_impl_trait = old_outer_impl_trait; + } +} + + +impl<'a> Visitor<'a> for NestedImplTraitVisitor<'a> { + fn visit_ty(&mut self, t: &'a Ty) { + if let TyKind::ImplTrait(_) = t.node { + if let Some(outer_impl_trait) = self.outer_impl_trait { + struct_span_err!(self.session, t.span, E0666, + "nested `impl Trait` is not allowed") + .span_label(outer_impl_trait, "outer `impl Trait`") + .span_label(t.span, "devilishly nested `impl Trait` here") + .emit(); + + } + self.with_impl_trait(Some(t.span), |this| visit::walk_ty(this, t)); + } else { + visit::walk_ty(self, t); + } + } + fn visit_path_parameters(&mut self, _: Span, path_parameters: &'a PathParameters) { + match *path_parameters { + PathParameters::AngleBracketed(ref params) => { + for type_ in ¶ms.types { + self.visit_ty(type_); + } + for type_binding in ¶ms.bindings { + // Type bindings such as `Item=impl Debug` in `Iterator` + // are allowed to contain nested `impl Trait`. + self.with_impl_trait(None, |this| visit::walk_ty(this, &type_binding.ty)); + } + } + PathParameters::Parenthesized(ref params) => { + for type_ in ¶ms.inputs { + self.visit_ty(type_); + } + if let Some(ref type_) = params.output { + // `-> Foo` syntax is essentially an associated type binding, + // so it is also allowed to contain nested `impl Trait`. + self.with_impl_trait(None, |this| visit::walk_ty(this, type_)); + } + } + } + } +} + + pub fn check_crate(session: &Session, krate: &Crate) { + visit::walk_crate( + &mut NestedImplTraitVisitor { + session, + outer_impl_trait: None, + }, krate); + visit::walk_crate(&mut AstValidator { session: session }, krate) } diff --git a/src/librustc_passes/diagnostics.rs b/src/librustc_passes/diagnostics.rs index 743f7b7326e9e..6dfc52f842e16 100644 --- a/src/librustc_passes/diagnostics.rs +++ b/src/librustc_passes/diagnostics.rs @@ -320,4 +320,5 @@ register_diagnostics! { E0567, // auto traits can not have generic parameters E0568, // auto traits can not have super traits E0642, // patterns aren't allowed in methods without bodies + E0666, // nested `impl Trait` is illegal } diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index ea916d5168c33..a3eba63706cb0 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -432,9 +432,6 @@ declare_features! ( // `foo.rs` as an alternative to `foo/mod.rs` (active, non_modrs_mods, "1.24.0", Some(44660)), - // Nested `impl Trait` - (active, nested_impl_trait, "1.24.0", Some(34511)), - // Termination trait in main (RFC 1937) (active, termination_trait, "1.24.0", Some(43301)), @@ -1352,73 +1349,8 @@ fn contains_novel_literal(item: &ast::MetaItem) -> bool { } } -// Bans nested `impl Trait`, e.g. `impl Into`. -// Nested `impl Trait` _is_ allowed in associated type position, -// e.g `impl Iterator` -struct NestedImplTraitVisitor<'a> { - context: &'a Context<'a>, - is_in_impl_trait: bool, -} - -impl<'a> NestedImplTraitVisitor<'a> { - fn with_impl_trait(&mut self, is_in_impl_trait: bool, f: F) - where F: FnOnce(&mut NestedImplTraitVisitor<'a>) - { - let old_is_in_impl_trait = self.is_in_impl_trait; - self.is_in_impl_trait = is_in_impl_trait; - f(self); - self.is_in_impl_trait = old_is_in_impl_trait; - } -} - - -impl<'a> Visitor<'a> for NestedImplTraitVisitor<'a> { - fn visit_ty(&mut self, t: &'a ast::Ty) { - if let ast::TyKind::ImplTrait(_) = t.node { - if self.is_in_impl_trait { - gate_feature_post!(&self, nested_impl_trait, t.span, - "nested `impl Trait` is experimental" - ); - } - self.with_impl_trait(true, |this| visit::walk_ty(this, t)); - } else { - visit::walk_ty(self, t); - } - } - fn visit_path_parameters(&mut self, _: Span, path_parameters: &'a ast::PathParameters) { - match *path_parameters { - ast::PathParameters::AngleBracketed(ref params) => { - for type_ in ¶ms.types { - self.visit_ty(type_); - } - for type_binding in ¶ms.bindings { - // Type bindings such as `Item=impl Debug` in `Iterator` - // are allowed to contain nested `impl Trait`. - self.with_impl_trait(false, |this| visit::walk_ty(this, &type_binding.ty)); - } - } - ast::PathParameters::Parenthesized(ref params) => { - for type_ in ¶ms.inputs { - self.visit_ty(type_); - } - if let Some(ref type_) = params.output { - // `-> Foo` syntax is essentially an associated type binding, - // so it is also allowed to contain nested `impl Trait`. - self.with_impl_trait(false, |this| visit::walk_ty(this, type_)); - } - } - } - } -} - impl<'a> PostExpansionVisitor<'a> { - fn whole_crate_feature_gates(&mut self, krate: &ast::Crate) { - visit::walk_crate( - &mut NestedImplTraitVisitor { - context: self.context, - is_in_impl_trait: false, - }, krate); - + fn whole_crate_feature_gates(&mut self, _krate: &ast::Crate) { for &(ident, span) in &*self.context.parse_sess.non_modrs_mods.borrow() { if !span.allows_unstable() { let cx = &self.context; diff --git a/src/test/compile-fail/impl-trait/where-allowed.rs b/src/test/compile-fail/impl-trait/where-allowed.rs index a9fe1e04664e9..52c5471681df3 100644 --- a/src/test/compile-fail/impl-trait/where-allowed.rs +++ b/src/test/compile-fail/impl-trait/where-allowed.rs @@ -10,7 +10,7 @@ //! A simple test for testing many permutations of allowedness of //! impl Trait -#![feature(conservative_impl_trait, nested_impl_trait, universal_impl_trait, dyn_trait)] +#![feature(conservative_impl_trait, universal_impl_trait, dyn_trait)] use std::fmt::Debug; // Allowed @@ -60,6 +60,7 @@ fn in_dyn_Fn_return_in_return() -> &'static dyn Fn() -> impl Debug { panic!() } // Disallowed fn in_impl_Fn_parameter_in_parameters(_: &impl Fn(impl Debug)) { panic!() } //~^ ERROR `impl Trait` not allowed outside of function and inherent method return types +//~^^ ERROR nested `impl Trait` is not allowed // Disallowed fn in_impl_Fn_return_in_parameters(_: &impl Fn() -> impl Debug) { panic!() } @@ -68,6 +69,7 @@ fn in_impl_Fn_return_in_parameters(_: &impl Fn() -> impl Debug) { panic!() } // Disallowed fn in_impl_Fn_parameter_in_return() -> &'static impl Fn(impl Debug) { panic!() } //~^ ERROR `impl Trait` not allowed outside of function and inherent method return types +//~^^ ERROR nested `impl Trait` is not allowed // Disallowed fn in_impl_Fn_return_in_return() -> &'static impl Fn() -> impl Debug { panic!() } diff --git a/src/test/run-pass/impl-trait/lifetimes.rs b/src/test/run-pass/impl-trait/lifetimes.rs index 1f2d76f289472..4d40e707ddcb9 100644 --- a/src/test/run-pass/impl-trait/lifetimes.rs +++ b/src/test/run-pass/impl-trait/lifetimes.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(conservative_impl_trait, underscore_lifetimes, universal_impl_trait, nested_impl_trait)] +#![feature(conservative_impl_trait, underscore_lifetimes, universal_impl_trait)] #![allow(warnings)] use std::fmt::Debug; @@ -55,12 +55,11 @@ fn pass_through_elision_with_fn_ptr(x: &fn(&u32) -> &u32) -> impl Into<&fn(&u32) fn pass_through_elision_with_fn_path &u32>( x: &T -) -> impl Into<&impl Fn(&u32) -> &u32> { x } +) -> &impl Fn(&u32) -> &u32 { x } -fn foo(x: &impl Debug) -> impl Into<&impl Debug> { x } -fn foo_explicit_lifetime<'a>(x: &'a impl Debug) -> impl Into<&'a impl Debug> { x } -fn foo_no_outer_impl(x: &impl Debug) -> &impl Debug { x } -fn foo_explicit_arg(x: &T) -> impl Into<&impl Debug> { x } +fn foo(x: &impl Debug) -> &impl Debug { x } +fn foo_explicit_lifetime<'a>(x: &'a impl Debug) -> &'a impl Debug { x } +fn foo_explicit_arg(x: &T) -> &impl Debug { x } fn mixed_lifetimes<'a>() -> impl for<'b: 'a> Fn(&'b u32) { |_| () } fn mixed_as_static() -> impl Fn(&'static u32) { mixed_lifetimes() } diff --git a/src/test/ui/error-codes/E0657.rs b/src/test/ui/error-codes/E0657.rs index 4595e413081a5..31b3acd86ef55 100644 --- a/src/test/ui/error-codes/E0657.rs +++ b/src/test/ui/error-codes/E0657.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. #![allow(warnings)] -#![feature(conservative_impl_trait, nested_impl_trait)] +#![feature(conservative_impl_trait)] trait Id {} trait Lt<'a> {} @@ -17,7 +17,7 @@ impl<'a> Lt<'a> for () {} impl Id for T {} fn free_fn_capture_hrtb_in_impl_trait() - -> impl for<'a> Id> + -> Box Id>> //~^ ERROR `impl Trait` can only capture lifetimes bound at the fn or impl level [E0657] { () @@ -26,7 +26,7 @@ fn free_fn_capture_hrtb_in_impl_trait() struct Foo; impl Foo { fn impl_fn_capture_hrtb_in_impl_trait() - -> impl for<'a> Id> + -> Box Id>> //~^ ERROR `impl Trait` can only capture lifetimes bound at the fn or impl level { () diff --git a/src/test/compile-fail/feature-gate-nested_impl_trait.rs b/src/test/ui/nested_impl_trait.rs similarity index 80% rename from src/test/compile-fail/feature-gate-nested_impl_trait.rs rename to src/test/ui/nested_impl_trait.rs index 7c35263d05dd7..f6302c0f3b3e2 100644 --- a/src/test/compile-fail/feature-gate-nested_impl_trait.rs +++ b/src/test/ui/nested_impl_trait.rs @@ -14,18 +14,19 @@ use std::fmt::Debug; fn fine(x: impl Into) -> impl Into { x } fn bad_in_ret_position(x: impl Into) -> impl Into { x } -//~^ ERROR nested `impl Trait` is experimental +//~^ ERROR nested `impl Trait` is not allowed fn bad_in_fn_syntax(x: fn() -> impl Into) {} -//~^ ERROR nested `impl Trait` is experimental +//~^ ERROR nested `impl Trait` is not allowed +//~^^ `impl Trait` not allowed fn bad_in_arg_position(_: impl Into) { } -//~^ ERROR nested `impl Trait` is experimental +//~^ ERROR nested `impl Trait` is not allowed struct X; impl X { fn bad(x: impl Into) -> impl Into { x } - //~^ ERROR nested `impl Trait` is experimental + //~^ ERROR nested `impl Trait` is not allowed } fn allowed_in_assoc_type() -> impl Iterator { @@ -33,6 +34,7 @@ fn allowed_in_assoc_type() -> impl Iterator { } fn allowed_in_ret_type() -> impl Fn() -> impl Into { +//~^ `impl Trait` not allowed || 5 } diff --git a/src/test/ui/nested_impl_trait.stderr b/src/test/ui/nested_impl_trait.stderr new file mode 100644 index 0000000000000..6649f9ab99cc1 --- /dev/null +++ b/src/test/ui/nested_impl_trait.stderr @@ -0,0 +1,50 @@ +error[E0666]: nested `impl Trait` is not allowed + --> $DIR/nested_impl_trait.rs:16:56 + | +16 | fn bad_in_ret_position(x: impl Into) -> impl Into { x } + | ----------^^^^^^^^^^- + | | | + | | devilishly nested `impl Trait` here + | outer `impl Trait` + +error[E0666]: nested `impl Trait` is not allowed + --> $DIR/nested_impl_trait.rs:19:42 + | +19 | fn bad_in_fn_syntax(x: fn() -> impl Into) {} + | ----------^^^^^^^^^^- + | | | + | | devilishly nested `impl Trait` here + | outer `impl Trait` + +error[E0666]: nested `impl Trait` is not allowed + --> $DIR/nested_impl_trait.rs:23:37 + | +23 | fn bad_in_arg_position(_: impl Into) { } + | ----------^^^^^^^^^^- + | | | + | | devilishly nested `impl Trait` here + | outer `impl Trait` + +error[E0666]: nested `impl Trait` is not allowed + --> $DIR/nested_impl_trait.rs:28:44 + | +28 | fn bad(x: impl Into) -> impl Into { x } + | ----------^^^^^^^^^^- + | | | + | | devilishly nested `impl Trait` here + | outer `impl Trait` + +error[E0562]: `impl Trait` not allowed outside of function and inherent method return types + --> $DIR/nested_impl_trait.rs:19:32 + | +19 | fn bad_in_fn_syntax(x: fn() -> impl Into) {} + | ^^^^^^^^^^^^^^^^^^^^^ + +error[E0562]: `impl Trait` not allowed outside of function and inherent method return types + --> $DIR/nested_impl_trait.rs:36:42 + | +36 | fn allowed_in_ret_type() -> impl Fn() -> impl Into { + | ^^^^^^^^^^^^^^ + +error: aborting due to 6 previous errors + From 70e1f4fc6d951dfc0547ff5acb3d8780d16635e6 Mon Sep 17 00:00:00 2001 From: Taylor Cramer Date: Thu, 8 Feb 2018 16:50:14 -0800 Subject: [PATCH 2/5] Disallow projections from impl Trait types --- src/librustc_passes/ast_validation.rs | 68 ++++++++++++++++++++++- src/librustc_passes/diagnostics.rs | 1 + src/test/ui/impl_trait_projections.rs | 43 ++++++++++++++ src/test/ui/impl_trait_projections.stderr | 28 ++++++++++ 4 files changed, 139 insertions(+), 1 deletion(-) create mode 100644 src/test/ui/impl_trait_projections.rs create mode 100644 src/test/ui/impl_trait_projections.stderr diff --git a/src/librustc_passes/ast_validation.rs b/src/librustc_passes/ast_validation.rs index 826f27c2ddbf4..14ea5c0ce7982 100644 --- a/src/librustc_passes/ast_validation.rs +++ b/src/librustc_passes/ast_validation.rs @@ -447,7 +447,7 @@ impl<'a> Visitor<'a> for NestedImplTraitVisitor<'a> { struct_span_err!(self.session, t.span, E0666, "nested `impl Trait` is not allowed") .span_label(outer_impl_trait, "outer `impl Trait`") - .span_label(t.span, "devilishly nested `impl Trait` here") + .span_label(t.span, "nested `impl Trait` here") .emit(); } @@ -482,6 +482,66 @@ impl<'a> Visitor<'a> for NestedImplTraitVisitor<'a> { } } +// Bans `impl Trait` in path projections like `::Item` or `Foo::Bar`. +struct ImplTraitProjectionVisitor<'a> { + session: &'a Session, + is_banned: bool, +} + +impl<'a> ImplTraitProjectionVisitor<'a> { + fn with_ban(&mut self, f: F) + where F: FnOnce(&mut ImplTraitProjectionVisitor<'a>) + { + let old_is_banned = self.is_banned; + self.is_banned = true; + f(self); + self.is_banned = old_is_banned; + } +} + +impl<'a> Visitor<'a> for ImplTraitProjectionVisitor<'a> { + fn visit_ty(&mut self, t: &'a Ty) { + match t.node { + TyKind::ImplTrait(_) => { + if self.is_banned { + struct_span_err!(self.session, t.span, E0667, + "`impl Trait` is not allowed in path parameters") + .emit(); + } + } + TyKind::Path(ref qself, ref path) => { + // We allow these: + // - `Option` + // - `option::Option` + // - `option::Option::Foo + // + // But not these: + // - `::Foo` + // - `option::Option::Foo`. + // + // To implement this, we disallow `impl Trait` from `qself` + // (for cases like `::Foo>`) + // but we allow `impl Trait` in `PathParameters` + // iff there are no more PathSegments. + if let Some(ref qself) = *qself { + // `impl Trait` in `qself` is always illegal + self.with_ban(|this| this.visit_ty(&qself.ty)); + } + + for (i, segment) in path.segments.iter().enumerate() { + // Allow `impl Trait` iff we're on the final path segment + if i == (path.segments.len() - 1) { + visit::walk_path_segment(self, path.span, segment); + } else { + self.with_ban(|this| + visit::walk_path_segment(this, path.span, segment)); + } + } + } + _ => visit::walk_ty(self, t), + } + } +} pub fn check_crate(session: &Session, krate: &Crate) { visit::walk_crate( @@ -490,5 +550,11 @@ pub fn check_crate(session: &Session, krate: &Crate) { outer_impl_trait: None, }, krate); + visit::walk_crate( + &mut ImplTraitProjectionVisitor { + session, + is_banned: false, + }, krate); + visit::walk_crate(&mut AstValidator { session: session }, krate) } diff --git a/src/librustc_passes/diagnostics.rs b/src/librustc_passes/diagnostics.rs index 6dfc52f842e16..980808a6905c1 100644 --- a/src/librustc_passes/diagnostics.rs +++ b/src/librustc_passes/diagnostics.rs @@ -321,4 +321,5 @@ register_diagnostics! { E0568, // auto traits can not have super traits E0642, // patterns aren't allowed in methods without bodies E0666, // nested `impl Trait` is illegal + E0667, // `impl Trait` in projections } diff --git a/src/test/ui/impl_trait_projections.rs b/src/test/ui/impl_trait_projections.rs new file mode 100644 index 0000000000000..e34b7799fb724 --- /dev/null +++ b/src/test/ui/impl_trait_projections.rs @@ -0,0 +1,43 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. +#![feature(conservative_impl_trait, universal_impl_trait)] + +use std::fmt::Debug; +use std::option; + +fn parametrized_type_is_allowed() -> Option { + Some(5i32) +} + +fn path_parametrized_type_is_allowed() -> option::Option { + Some(5i32) +} + +fn projection_is_disallowed(x: impl Iterator) -> ::Item { +//~^ ERROR `impl Trait` is not allowed in path parameters +//~^^ ERROR ambiguous associated type + x.next().unwrap() +} + +fn projection_with_named_trait_is_disallowed(x: impl Iterator) + -> ::Item +//~^ ERROR `impl Trait` is not allowed in path parameters +{ + x.next().unwrap() +} + +fn projection_with_named_trait_inside_path_is_disallowed() + -> <::std::ops::Range as Iterator>::Item +//~^ ERROR `impl Trait` is not allowed in path parameters +{ + (1i32..100).next().unwrap() +} + +fn main() {} diff --git a/src/test/ui/impl_trait_projections.stderr b/src/test/ui/impl_trait_projections.stderr new file mode 100644 index 0000000000000..2e8bfc931f82e --- /dev/null +++ b/src/test/ui/impl_trait_projections.stderr @@ -0,0 +1,28 @@ +error[E0667]: `impl Trait` is not allowed in path parameters + --> $DIR/impl_trait_projections.rs:23:51 + | +23 | fn projection_is_disallowed(x: impl Iterator) -> ::Item { + | ^^^^^^^^^^^^^ + +error[E0667]: `impl Trait` is not allowed in path parameters + --> $DIR/impl_trait_projections.rs:30:9 + | +30 | -> ::Item + | ^^^^^^^^^^^^^ + +error[E0667]: `impl Trait` is not allowed in path parameters + --> $DIR/impl_trait_projections.rs:37:27 + | +37 | -> <::std::ops::Range as Iterator>::Item + | ^^^^^^^^^^ + +error[E0223]: ambiguous associated type + --> $DIR/impl_trait_projections.rs:23:50 + | +23 | fn projection_is_disallowed(x: impl Iterator) -> ::Item { + | ^^^^^^^^^^^^^^^^^^^^^ ambiguous associated type + | + = note: specify the type using the syntax `::Item` + +error: aborting due to 4 previous errors + From f1fbf79223aca762c42c6674d125c4c5223f9949 Mon Sep 17 00:00:00 2001 From: Taylor Cramer Date: Tue, 13 Feb 2018 17:46:33 -0800 Subject: [PATCH 3/5] Amend nested impl Trait error message --- src/test/ui/nested_impl_trait.stderr | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/test/ui/nested_impl_trait.stderr b/src/test/ui/nested_impl_trait.stderr index 6649f9ab99cc1..094926120cdee 100644 --- a/src/test/ui/nested_impl_trait.stderr +++ b/src/test/ui/nested_impl_trait.stderr @@ -4,7 +4,7 @@ error[E0666]: nested `impl Trait` is not allowed 16 | fn bad_in_ret_position(x: impl Into) -> impl Into { x } | ----------^^^^^^^^^^- | | | - | | devilishly nested `impl Trait` here + | | nested `impl Trait` here | outer `impl Trait` error[E0666]: nested `impl Trait` is not allowed @@ -13,7 +13,7 @@ error[E0666]: nested `impl Trait` is not allowed 19 | fn bad_in_fn_syntax(x: fn() -> impl Into) {} | ----------^^^^^^^^^^- | | | - | | devilishly nested `impl Trait` here + | | nested `impl Trait` here | outer `impl Trait` error[E0666]: nested `impl Trait` is not allowed @@ -22,7 +22,7 @@ error[E0666]: nested `impl Trait` is not allowed 23 | fn bad_in_arg_position(_: impl Into) { } | ----------^^^^^^^^^^- | | | - | | devilishly nested `impl Trait` here + | | nested `impl Trait` here | outer `impl Trait` error[E0666]: nested `impl Trait` is not allowed @@ -31,7 +31,7 @@ error[E0666]: nested `impl Trait` is not allowed 28 | fn bad(x: impl Into) -> impl Into { x } | ----------^^^^^^^^^^- | | | - | | devilishly nested `impl Trait` here + | | nested `impl Trait` here | outer `impl Trait` error[E0562]: `impl Trait` not allowed outside of function and inherent method return types From dbacf0c56ba2bd5ed38fc2a2e4bc20150271e7f2 Mon Sep 17 00:00:00 2001 From: Taylor Cramer Date: Tue, 13 Feb 2018 17:52:22 -0800 Subject: [PATCH 4/5] Test err on impl Trait projection within dyn Trait --- src/test/ui/impl_trait_projections.rs | 9 ++++++++- src/test/ui/impl_trait_projections.stderr | 8 +++++++- 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/src/test/ui/impl_trait_projections.rs b/src/test/ui/impl_trait_projections.rs index e34b7799fb724..f69a78b1450f1 100644 --- a/src/test/ui/impl_trait_projections.rs +++ b/src/test/ui/impl_trait_projections.rs @@ -7,7 +7,7 @@ // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(conservative_impl_trait, universal_impl_trait)] +#![feature(dyn_trait, conservative_impl_trait, universal_impl_trait)] use std::fmt::Debug; use std::option; @@ -40,4 +40,11 @@ fn projection_with_named_trait_inside_path_is_disallowed() (1i32..100).next().unwrap() } +fn projection_from_impl_trait_inside_dyn_trait_is_disallowed() + -> as Iterator>::Item +//~^ ERROR `impl Trait` is not allowed in path parameters +{ + panic!() +} + fn main() {} diff --git a/src/test/ui/impl_trait_projections.stderr b/src/test/ui/impl_trait_projections.stderr index 2e8bfc931f82e..08de0eb99a307 100644 --- a/src/test/ui/impl_trait_projections.stderr +++ b/src/test/ui/impl_trait_projections.stderr @@ -16,6 +16,12 @@ error[E0667]: `impl Trait` is not allowed in path parameters 37 | -> <::std::ops::Range as Iterator>::Item | ^^^^^^^^^^ +error[E0667]: `impl Trait` is not allowed in path parameters + --> $DIR/impl_trait_projections.rs:44:29 + | +44 | -> as Iterator>::Item + | ^^^^^^^^^^ + error[E0223]: ambiguous associated type --> $DIR/impl_trait_projections.rs:23:50 | @@ -24,5 +30,5 @@ error[E0223]: ambiguous associated type | = note: specify the type using the syntax `::Item` -error: aborting due to 4 previous errors +error: aborting due to 5 previous errors From 9e9c55f8fd064335cadc28bd9a0152538dcc9fa0 Mon Sep 17 00:00:00 2001 From: Taylor Cramer Date: Wed, 14 Feb 2018 10:22:12 -0800 Subject: [PATCH 5/5] Update E0657 stderr to match changed test --- src/test/ui/error-codes/E0657.stderr | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/test/ui/error-codes/E0657.stderr b/src/test/ui/error-codes/E0657.stderr index d3b53d37a30a0..e039d645fa6db 100644 --- a/src/test/ui/error-codes/E0657.stderr +++ b/src/test/ui/error-codes/E0657.stderr @@ -1,14 +1,14 @@ error[E0657]: `impl Trait` can only capture lifetimes bound at the fn or impl level - --> $DIR/E0657.rs:20:32 + --> $DIR/E0657.rs:20:31 | -20 | -> impl for<'a> Id> - | ^^ +20 | -> Box Id>> + | ^^ error[E0657]: `impl Trait` can only capture lifetimes bound at the fn or impl level - --> $DIR/E0657.rs:29:36 + --> $DIR/E0657.rs:29:35 | -29 | -> impl for<'a> Id> - | ^^ +29 | -> Box Id>> + | ^^ error: aborting due to 2 previous errors