From f93183adb43cff4cc0972ce133ce077f8cae1656 Mon Sep 17 00:00:00 2001 From: "leonardo.yvens" Date: Fri, 1 Dec 2017 10:01:23 -0200 Subject: Remove `impl Foo for ..` in favor of `auto trait Foo` No longer parse it. Remove AutoTrait variant from AST and HIR. Remove backwards compatibility lint. Remove coherence checks, they make no sense for the new syntax. Remove from rustdoc. --- src/libsyntax/parse/parser.rs | 57 +++++++++++++++---------------------------- 1 file changed, 19 insertions(+), 38 deletions(-) (limited to 'src/libsyntax/parse') diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 489e5e78cce..b2d66386582 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -5374,11 +5374,9 @@ impl<'a> Parser<'a> { /// Parses items implementations variants /// impl Foo { ... } /// impl ToString for &'static T { ... } - /// impl Send for .. {} fn parse_item_impl(&mut self, unsafety: ast::Unsafety, defaultness: Defaultness) -> PResult<'a, ItemInfo> { - let impl_span = self.span; // First, parse type parameters if necessary. let mut generics = self.parse_generics()?; @@ -5421,48 +5419,31 @@ impl<'a> Parser<'a> { None }; - if opt_trait.is_some() && self.eat(&token::DotDot) { - if generics.is_parameterized() { - self.span_err(impl_span, "auto trait implementations are not \ - allowed to have generics"); - } - - if let ast::Defaultness::Default = defaultness { - self.span_err(impl_span, "`default impl` is not allowed for \ - auto trait implementations"); - } - - self.expect(&token::OpenDelim(token::Brace))?; - self.expect(&token::CloseDelim(token::Brace))?; - Ok((keywords::Invalid.ident(), - ItemKind::AutoImpl(unsafety, opt_trait.unwrap()), None)) - } else { - if opt_trait.is_some() { - ty = self.parse_ty()?; - } - generics.where_clause = self.parse_where_clause()?; + if opt_trait.is_some() { + ty = self.parse_ty()?; + } + generics.where_clause = self.parse_where_clause()?; - self.expect(&token::OpenDelim(token::Brace))?; - let attrs = self.parse_inner_attributes()?; + self.expect(&token::OpenDelim(token::Brace))?; + let attrs = self.parse_inner_attributes()?; - let mut impl_items = vec![]; - while !self.eat(&token::CloseDelim(token::Brace)) { - let mut at_end = false; - match self.parse_impl_item(&mut at_end) { - Ok(item) => impl_items.push(item), - Err(mut e) => { - e.emit(); - if !at_end { - self.recover_stmt_(SemiColonMode::Break, BlockMode::Break); - } + let mut impl_items = vec![]; + while !self.eat(&token::CloseDelim(token::Brace)) { + let mut at_end = false; + match self.parse_impl_item(&mut at_end) { + Ok(item) => impl_items.push(item), + Err(mut e) => { + e.emit(); + if !at_end { + self.recover_stmt_(SemiColonMode::Break, BlockMode::Break); } } } - - Ok((keywords::Invalid.ident(), - ItemKind::Impl(unsafety, polarity, defaultness, generics, opt_trait, ty, impl_items), - Some(attrs))) } + + Ok((keywords::Invalid.ident(), + ItemKind::Impl(unsafety, polarity, defaultness, generics, opt_trait, ty, impl_items), + Some(attrs))) } fn parse_late_bound_lifetime_defs(&mut self) -> PResult<'a, Vec> { -- cgit 1.4.1-3-g733a5 From 4e3953bbdd58892844a1bd2b7f4a2336a8acea5e Mon Sep 17 00:00:00 2001 From: "leonardo.yvens" Date: Mon, 4 Dec 2017 16:26:20 -0200 Subject: Parse `auto trait` inside fns. Also refactored parsing auto traits. --- src/libsyntax/parse/parser.rs | 28 ++++++++++++++++------------ src/test/run-pass/auto-traits.rs | 5 ++++- 2 files changed, 20 insertions(+), 13 deletions(-) (limited to 'src/libsyntax/parse') diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index b2d66386582..884e7d1f6ad 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -4084,14 +4084,14 @@ impl<'a> Parser<'a> { self.token.is_keyword(keywords::Extern) && self.look_ahead(1, |t| t != &token::ModSep) } - fn eat_auto_trait(&mut self) -> bool { - if self.token.is_keyword(keywords::Auto) - && self.look_ahead(1, |t| t.is_keyword(keywords::Trait)) - { - self.eat_keyword(keywords::Auto) && self.eat_keyword(keywords::Trait) - } else { - false - } + fn is_auto_trait_item(&mut self) -> bool { + // auto trait + (self.token.is_keyword(keywords::Auto) + && self.look_ahead(1, |t| t.is_keyword(keywords::Trait))) + || // unsafe auto trait + (self.token.is_keyword(keywords::Unsafe) && + self.look_ahead(1, |t| t.is_keyword(keywords::Auto)) && + self.look_ahead(2, |t| t.is_keyword(keywords::Trait))) } fn is_defaultness(&self) -> bool { @@ -4194,7 +4194,8 @@ impl<'a> Parser<'a> { node: StmtKind::Item(macro_def), span: lo.to(self.prev_span), } - // Starts like a simple path, but not a union item or item with `crate` visibility. + // Starts like a simple path, being careful to avoid contextual keywords + // such as a union items, item with `crate` visibility or auto trait items. // Our goal here is to parse an arbitrary path `a::b::c` but not something that starts // like a path (1 token), but it fact not a path. // `union::b::c` - path, `union U { ... }` - not a path. @@ -4204,7 +4205,8 @@ impl<'a> Parser<'a> { !self.token.is_qpath_start() && !self.is_union_item() && !self.is_crate_vis() && - !self.is_extern_non_path() { + !self.is_extern_non_path() && + !self.is_auto_trait_item() { let pth = self.parse_path(PathStyle::Expr)?; if !self.eat(&token::Not) { @@ -6368,7 +6370,8 @@ impl<'a> Parser<'a> { let is_auto = if self.eat_keyword(keywords::Trait) { IsAuto::No } else { - self.eat_auto_trait(); + self.eat_keyword(keywords::Auto); + self.eat_keyword(keywords::Trait); IsAuto::Yes }; let (ident, item_, extra_attrs) = @@ -6482,7 +6485,8 @@ impl<'a> Parser<'a> { let is_auto = if self.eat_keyword(keywords::Trait) { IsAuto::No } else { - self.eat_auto_trait(); + self.eat_keyword(keywords::Auto); + self.eat_keyword(keywords::Trait); IsAuto::Yes }; // TRAIT ITEM diff --git a/src/test/run-pass/auto-traits.rs b/src/test/run-pass/auto-traits.rs index 2511488c94e..2a18b402bc6 100644 --- a/src/test/run-pass/auto-traits.rs +++ b/src/test/run-pass/auto-traits.rs @@ -11,7 +11,6 @@ #![feature(optin_builtin_traits)] auto trait Auto {} - unsafe auto trait AutoUnsafe {} impl !Auto for bool {} @@ -26,6 +25,10 @@ fn take_auto(_: T) {} fn take_auto_unsafe(_: T) {} fn main() { + // Parse inside functions. + auto trait AutoInner {} + unsafe auto trait AutoUnsafeInner {} + take_auto(0); take_auto(AutoBool(true)); take_auto_unsafe(0); -- cgit 1.4.1-3-g733a5 From 8b4d852f32b6bf3fdec2cce6c0d2804b27d02a20 Mon Sep 17 00:00:00 2001 From: "leonardo.yvens" Date: Mon, 4 Dec 2017 20:55:14 -0200 Subject: Address review. --- src/librustc_passes/ast_validation.rs | 6 +-- src/librustc_passes/diagnostics.rs | 4 +- src/librustc_typeck/collect.rs | 53 +--------------------- src/libsyntax/parse/parser.rs | 8 ++-- src/test/compile-fail/auto-trait-validation.rs | 6 +-- .../ui/feature-gate-optin-builtin-traits.stderr | 14 ++---- 6 files changed, 16 insertions(+), 75 deletions(-) (limited to 'src/libsyntax/parse') diff --git a/src/librustc_passes/ast_validation.rs b/src/librustc_passes/ast_validation.rs index ba819cbf538..8342af6011d 100644 --- a/src/librustc_passes/ast_validation.rs +++ b/src/librustc_passes/ast_validation.rs @@ -248,15 +248,15 @@ impl<'a> Visitor<'a> for AstValidator<'a> { // Auto traits cannot have generics, super traits nor contain items. if generics.is_parameterized() { struct_span_err!(self.session, item.span, E0567, - "Auto traits cannot have generic parameters").emit(); + "auto traits cannot have generic parameters").emit(); } if !bounds.is_empty() { struct_span_err!(self.session, item.span, E0568, - "Auto traits cannot have predicates").emit(); + "auto traits cannot have super traits").emit(); } if !trait_items.is_empty() { struct_span_err!(self.session, item.span, E0380, - "Auto traits cannot have methods or associated items").emit(); + "auto traits cannot have methods or associated items").emit(); } } self.no_questions_in_bounds(bounds, "supertraits", true); diff --git a/src/librustc_passes/diagnostics.rs b/src/librustc_passes/diagnostics.rs index 2244463518e..cbfdace7e0f 100644 --- a/src/librustc_passes/diagnostics.rs +++ b/src/librustc_passes/diagnostics.rs @@ -271,7 +271,7 @@ register_diagnostics! { E0226, // only a single explicit lifetime bound is permitted E0472, // asm! is unsupported on this target E0561, // patterns aren't allowed in function pointer types - E0567, // auto traits can not have type parameters - E0568, // auto traits can not have predicates + 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 } diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index 4754aaceff4..5485045b704 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -714,7 +714,7 @@ fn trait_def<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, let (is_auto, unsafety) = match item.node { hir::ItemTrait(is_auto, unsafety, ..) => (is_auto == hir::IsAuto::Yes, unsafety), - hir::ItemTraitAlias(..) => (hir::IsAuto::No, hir::Unsafety::Normal), + hir::ItemTraitAlias(..) => (false, hir::Unsafety::Normal), _ => span_bug!(item.span, "trait_def_of_item invoked on non-trait"), }; @@ -1714,54 +1714,3 @@ fn is_foreign_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, _ => bug!("is_foreign_item applied to non-local def-id {:?}", def_id) } } - -struct ImplTraitUniversalInfo<'hir> { - id: ast::NodeId, - def_id: DefId, - span: Span, - bounds: &'hir [hir::TyParamBound], -} - -/// Take some possible list of arguments and return the DefIds of the ImplTraitUniversal -/// arguments -fn extract_universal_impl_trait_info<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, - opt_inputs: Option<&'tcx [P]>) - -> Vec> -{ - // A visitor for simply collecting Universally quantified impl Trait arguments - struct ImplTraitUniversalVisitor<'tcx> { - items: Vec<&'tcx hir::Ty> - } - - impl<'tcx> Visitor<'tcx> for ImplTraitUniversalVisitor<'tcx> { - fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> { - NestedVisitorMap::None - } - - fn visit_ty(&mut self, ty: &'tcx hir::Ty) { - if let hir::TyImplTraitUniversal(..) = ty.node { - self.items.push(ty); - } - intravisit::walk_ty(self, ty); - } - } - - let mut visitor = ImplTraitUniversalVisitor { items: Vec::new() }; - - if let Some(inputs) = opt_inputs { - for t in inputs.iter() { - visitor.visit_ty(t); - } - } - - visitor.items.into_iter().map(|ty| if let hir::TyImplTraitUniversal(_, ref bounds) = ty.node { - ImplTraitUniversalInfo { - id: ty.id, - def_id: tcx.hir.local_def_id(ty.id), - span: ty.span, - bounds: bounds - } - } else { - span_bug!(ty.span, "this type should be a universally quantified impl trait. this is a bug") - }).collect() -} diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 884e7d1f6ad..ce42b05b8bb 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -6370,8 +6370,8 @@ impl<'a> Parser<'a> { let is_auto = if self.eat_keyword(keywords::Trait) { IsAuto::No } else { - self.eat_keyword(keywords::Auto); - self.eat_keyword(keywords::Trait); + self.expect_keyword(keywords::Auto)?; + self.expect_keyword(keywords::Trait)?; IsAuto::Yes }; let (ident, item_, extra_attrs) = @@ -6485,8 +6485,8 @@ impl<'a> Parser<'a> { let is_auto = if self.eat_keyword(keywords::Trait) { IsAuto::No } else { - self.eat_keyword(keywords::Auto); - self.eat_keyword(keywords::Trait); + self.expect_keyword(keywords::Auto)?; + self.expect_keyword(keywords::Trait)?; IsAuto::Yes }; // TRAIT ITEM diff --git a/src/test/compile-fail/auto-trait-validation.rs b/src/test/compile-fail/auto-trait-validation.rs index 782e352c471..92b222e1322 100644 --- a/src/test/compile-fail/auto-trait-validation.rs +++ b/src/test/compile-fail/auto-trait-validation.rs @@ -11,9 +11,9 @@ #![feature(optin_builtin_traits)] auto trait Generic {} -//~^ Auto traits cannot have type parameters [E0567] +//~^ auto traits cannot have generic parameters [E0567] auto trait Bound : Copy {} -//~^ Auto traits cannot have predicates [E0568] +//~^ auto traits cannot have super traits [E0568] auto trait MyTrait { fn foo() {} } -//~^ Auto traits cannot have methods or associated items [E0380] +//~^ auto traits cannot have methods or associated items [E0380] fn main() {} diff --git a/src/test/ui/feature-gate-optin-builtin-traits.stderr b/src/test/ui/feature-gate-optin-builtin-traits.stderr index c5e9614c29a..d66da1224f8 100644 --- a/src/test/ui/feature-gate-optin-builtin-traits.stderr +++ b/src/test/ui/feature-gate-optin-builtin-traits.stderr @@ -6,21 +6,13 @@ error: auto traits are experimental and possibly buggy (see issue #13231) | = help: add #![feature(optin_builtin_traits)] to the crate attributes to enable -error: auto trait implementations are experimental and possibly buggy (see issue #13231) - --> $DIR/feature-gate-optin-builtin-traits.rs:24:1 - | -24 | impl DummyTrait for .. {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = help: add #![feature(optin_builtin_traits)] to the crate attributes to enable - error: negative trait bounds are not yet fully implemented; use marker types for now (see issue #13231) - --> $DIR/feature-gate-optin-builtin-traits.rs:27:1 + --> $DIR/feature-gate-optin-builtin-traits.rs:23:1 | -27 | impl !DummyTrait for DummyStruct {} +23 | impl !DummyTrait for DummyStruct {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = help: add #![feature(optin_builtin_traits)] to the crate attributes to enable -error: aborting due to 3 previous errors +error: aborting due to 2 previous errors -- cgit 1.4.1-3-g733a5 From 22598776b04cc947f001191b47c18d981b46eec7 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Sat, 13 Jan 2018 19:26:49 +0300 Subject: Re-add support for `impl Trait for ..` to the parser --- src/librustc_passes/ast_validation.rs | 7 ++++++- src/libsyntax/parse/parser.rs | 6 +++++- src/test/ui/obsolete-syntax-impl-for-dotdot.rs | 19 +++++++++++++++++++ src/test/ui/obsolete-syntax-impl-for-dotdot.stderr | 10 ++++++++++ 4 files changed, 40 insertions(+), 2 deletions(-) create mode 100644 src/test/ui/obsolete-syntax-impl-for-dotdot.rs create mode 100644 src/test/ui/obsolete-syntax-impl-for-dotdot.stderr (limited to 'src/libsyntax/parse') diff --git a/src/librustc_passes/ast_validation.rs b/src/librustc_passes/ast_validation.rs index 8342af6011d..c41591bbc37 100644 --- a/src/librustc_passes/ast_validation.rs +++ b/src/librustc_passes/ast_validation.rs @@ -215,8 +215,13 @@ impl<'a> Visitor<'a> for AstValidator<'a> { fn visit_item(&mut self, item: &'a Item) { match item.node { - ItemKind::Impl(.., Some(..), _, ref impl_items) => { + ItemKind::Impl(.., Some(..), ref ty, ref impl_items) => { self.invalid_visibility(&item.vis, item.span, None); + if ty.node == TyKind::Err { + self.err_handler() + .struct_span_err(item.span, "`impl Trait for .. {}` is an obsolete syntax") + .help("use `auto trait Trait {}` instead").emit(); + } for impl_item in impl_items { self.invalid_visibility(&impl_item.vis, impl_item.span, None); if let ImplItemKind::Method(ref sig, _) = impl_item.node { diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index ce42b05b8bb..ad9c802ac85 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -5422,7 +5422,11 @@ impl<'a> Parser<'a> { }; if opt_trait.is_some() { - ty = self.parse_ty()?; + ty = if self.eat(&token::DotDot) { + P(Ty { node: TyKind::Err, span: self.prev_span, id: ast::DUMMY_NODE_ID }) + } else { + self.parse_ty()? + } } generics.where_clause = self.parse_where_clause()?; diff --git a/src/test/ui/obsolete-syntax-impl-for-dotdot.rs b/src/test/ui/obsolete-syntax-impl-for-dotdot.rs new file mode 100644 index 00000000000..914621a117d --- /dev/null +++ b/src/test/ui/obsolete-syntax-impl-for-dotdot.rs @@ -0,0 +1,19 @@ +// Copyright 2017 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. + +trait Trait1 {} +trait Trait2 {} + +#[cfg(not_enabled)] +impl Trait1 for .. {} + +impl Trait2 for .. {} //~ ERROR `impl Trait for .. {}` is an obsolete syntax + +fn main() {} diff --git a/src/test/ui/obsolete-syntax-impl-for-dotdot.stderr b/src/test/ui/obsolete-syntax-impl-for-dotdot.stderr new file mode 100644 index 00000000000..aa0af840d1a --- /dev/null +++ b/src/test/ui/obsolete-syntax-impl-for-dotdot.stderr @@ -0,0 +1,10 @@ +error: `impl Trait for .. {}` is an obsolete syntax + --> $DIR/obsolete-syntax-impl-for-dotdot.rs:17:1 + | +17 | impl Trait2 for .. {} //~ ERROR `impl Trait for .. {}` is an obsolete syntax + | ^^^^^^^^^^^^^^^^^^^^^ + | + = help: use `auto trait Trait {}` instead + +error: aborting due to previous error + -- cgit 1.4.1-3-g733a5