From d4a28268cc1c8314f0de2519c78ff97696486a36 Mon Sep 17 00:00:00 2001 From: Alex Burka Date: Mon, 2 Oct 2017 12:27:45 +0000 Subject: [PATCH 01/11] add trait aliases to AST --- src/librustc_passes/ast_validation.rs | 14 +++++++++ src/libsyntax/ast.rs | 5 ++++ src/libsyntax/fold.rs | 3 ++ src/libsyntax/parse/parser.rs | 39 ++++++++++++++++--------- src/libsyntax/print/pprust.rs | 21 ++++++++++++++ src/libsyntax/visit.rs | 4 +++ src/test/compile-fail/trait-alias.rs | 21 ++++++++++++++ src/test/run-pass/trait-alias.rs | 41 +++++++++++++++++++++++++++ 8 files changed, 134 insertions(+), 14 deletions(-) create mode 100644 src/test/compile-fail/trait-alias.rs create mode 100644 src/test/run-pass/trait-alias.rs diff --git a/src/librustc_passes/ast_validation.rs b/src/librustc_passes/ast_validation.rs index 05ad164361905..96c9323e7dc73 100644 --- a/src/librustc_passes/ast_validation.rs +++ b/src/librustc_passes/ast_validation.rs @@ -283,6 +283,20 @@ impl<'a> Visitor<'a> for AstValidator<'a> { } } } + ItemKind::TraitAlias(Generics { ref ty_params, .. }, ..) => { + for &TyParam { ref bounds, ref default, span, .. } in ty_params { + if !bounds.is_empty() { + self.err_handler().span_err(span, + "type parameters on the left side of a \ + trait alias cannot be bounded"); + } + if !default.is_none() { + self.err_handler().span_err(span, + "type parameters on the left side of a \ + trait alias cannot have defaults"); + } + } + } ItemKind::Mod(_) => { // Ensure that `path` attributes on modules are recorded as used (c.f. #35584). attr::first_attr_value_str_by_name(&item.attrs, "path"); diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index 3c1d6ea18f7c2..0d289dbd46b5b 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -1929,6 +1929,10 @@ pub enum ItemKind { /// /// E.g. `trait Foo { .. }`, `trait Foo { .. }` or `auto trait Foo {}` Trait(IsAuto, Unsafety, Generics, TyParamBounds, Vec), + /// Trait alias + /// + /// E.g. `trait Foo = Bar + Quux;` + TraitAlias(Generics, TyParamBounds), /// Auto trait implementation. /// /// E.g. `impl Trait for .. {}` or `impl Trait for .. {}` @@ -1968,6 +1972,7 @@ impl ItemKind { ItemKind::Struct(..) => "struct", ItemKind::Union(..) => "union", ItemKind::Trait(..) => "trait", + ItemKind::TraitAlias(..) => "trait alias", ItemKind::Mac(..) | ItemKind::MacroDef(..) | ItemKind::Impl(..) | diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs index 1a92f057e5e87..6f973e2bcfaef 100644 --- a/src/libsyntax/fold.rs +++ b/src/libsyntax/fold.rs @@ -921,6 +921,9 @@ pub fn noop_fold_item_kind(i: ItemKind, folder: &mut T) -> ItemKind { folder.fold_bounds(bounds), items.move_flat_map(|item| folder.fold_trait_item(item)), ), + ItemKind::TraitAlias(generics, bounds) => ItemKind::TraitAlias( + folder.fold_generics(generics), + folder.fold_bounds(bounds)), ItemKind::Mac(m) => ItemKind::Mac(folder.fold_mac(m)), ItemKind::MacroDef(def) => ItemKind::MacroDef(folder.fold_macro_def(def)), } diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index b3ef70fd18eb9..ec77d85f030eb 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -5182,7 +5182,7 @@ impl<'a> Parser<'a> { } } - /// Parse trait Foo { ... } + /// Parse `trait Foo { ... }` or `trait Foo = Bar;` fn parse_item_trait(&mut self, is_auto: IsAuto, unsafety: Unsafety) -> PResult<'a, ItemInfo> { let ident = self.parse_ident()?; let mut tps = self.parse_generics()?; @@ -5194,23 +5194,34 @@ impl<'a> Parser<'a> { Vec::new() }; - tps.where_clause = self.parse_where_clause()?; - - self.expect(&token::OpenDelim(token::Brace))?; - let mut trait_items = vec![]; - while !self.eat(&token::CloseDelim(token::Brace)) { - let mut at_end = false; - match self.parse_trait_item(&mut at_end) { - Ok(item) => trait_items.push(item), - Err(mut e) => { - e.emit(); - if !at_end { - self.recover_stmt_(SemiColonMode::Break, BlockMode::Break); + if self.eat(&token::Eq) { + // it's a trait alias + let bounds = self.parse_ty_param_bounds()?; + tps.where_clause = self.parse_where_clause()?; + self.expect(&token::Semi)?; + if unsafety != Unsafety::Normal { + self.span_err(self.prev_span, "trait aliases cannot be unsafe"); + } + Ok((ident, ItemKind::TraitAlias(tps, bounds), None)) + } else { + // it's a normal trait + tps.where_clause = self.parse_where_clause()?; + self.expect(&token::OpenDelim(token::Brace))?; + let mut trait_items = vec![]; + while !self.eat(&token::CloseDelim(token::Brace)) { + let mut at_end = false; + match self.parse_trait_item(&mut at_end) { + Ok(item) => trait_items.push(item), + Err(mut e) => { + e.emit(); + if !at_end { + self.recover_stmt_(SemiColonMode::Break, BlockMode::Break); + } } } } + Ok((ident, ItemKind::Trait(is_auto, unsafety, tps, bounds, trait_items), None)) } - Ok((ident, ItemKind::Trait(is_auto, unsafety, tps, bounds, trait_items), None)) } /// Parses items implementations variants diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index e4b7dc26d3261..e9386e5187ff0 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -1381,6 +1381,27 @@ impl<'a> State<'a> { } self.bclose(item.span)?; } + ast::ItemKind::TraitAlias(ref generics, ref bounds) => { + self.head("")?; + self.print_visibility(&item.vis)?; + self.word_nbsp("trait")?; + self.print_ident(item.ident)?; + self.print_generics(generics)?; + let mut real_bounds = Vec::with_capacity(bounds.len()); + // FIXME(durka) this seems to be some quite outdated syntax + for b in bounds.iter() { + if let TraitTyParamBound(ref ptr, ast::TraitBoundModifier::Maybe) = *b { + self.s.space()?; + self.word_space("for ?")?; + self.print_trait_ref(&ptr.trait_ref)?; + } else { + real_bounds.push(b.clone()); + } + } + self.print_bounds(" = ", &real_bounds[..])?; + self.print_where_clause(&generics.where_clause)?; + self.s.word(";")?; + } ast::ItemKind::Mac(codemap::Spanned { ref node, .. }) => { self.print_path(&node.path, false, 0, false)?; self.s.word("! ")?; diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs index 9a06ed0ba0297..9266cc280974d 100644 --- a/src/libsyntax/visit.rs +++ b/src/libsyntax/visit.rs @@ -291,6 +291,10 @@ pub fn walk_item<'a, V: Visitor<'a>>(visitor: &mut V, item: &'a Item) { walk_list!(visitor, visit_ty_param_bound, bounds); walk_list!(visitor, visit_trait_item, methods); } + ItemKind::TraitAlias(ref generics, ref bounds) => { + visitor.visit_generics(generics); + walk_list!(visitor, visit_ty_param_bound, bounds); + } ItemKind::Mac(ref mac) => visitor.visit_mac(mac), ItemKind::MacroDef(ref ts) => visitor.visit_mac_def(ts, item.id), } diff --git a/src/test/compile-fail/trait-alias.rs b/src/test/compile-fail/trait-alias.rs new file mode 100644 index 0000000000000..de87fe39395c8 --- /dev/null +++ b/src/test/compile-fail/trait-alias.rs @@ -0,0 +1,21 @@ +// 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 Alias1 = Default where T: Clone; // ok +trait Alias2 = Default; + //~^ERROR type parameters on the left side of a trait alias cannot be bounded + //~^^ERROR type parameters on the left side of a trait alias cannot have defaults + +impl Alias1 { //~ERROR expected type, found trait alias + fn foo() {} +} + +fn main() {} + diff --git a/src/test/run-pass/trait-alias.rs b/src/test/run-pass/trait-alias.rs new file mode 100644 index 0000000000000..529765320a292 --- /dev/null +++ b/src/test/run-pass/trait-alias.rs @@ -0,0 +1,41 @@ +// 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 SimpleAlias = Default; +trait GenericAlias = Iterator; +trait Partial = IntoIterator; + +trait Things {} +trait Romeo {} +struct The(T); +struct Fore(T); +impl Things for The {} +impl Romeo for Fore {} + +trait WithWhere = Romeo + Romeo where Fore<(Art, Thou)>: Romeo; +trait BareWhere = where The: Things; + +trait CD = Clone + Default; + +fn foo() -> (T, T) { + let one = T::default(); + let two = one.clone(); + (one, two) +} + +fn main() { + let both = foo(); + assert_eq!(both.0, 0); + assert_eq!(both.1, 0); + let both: (i32, i32) = foo(); + assert_eq!(both.0, 0); + assert_eq!(both.1, 0); +} + From f1c4a922fe00cd236bb4360f5fb7077d70a1e675 Mon Sep 17 00:00:00 2001 From: Alex Burka Date: Mon, 2 Oct 2017 13:48:57 +0000 Subject: [PATCH 02/11] stub out trait aliases in resolve --- src/librustc_resolve/build_reduced_graph.rs | 6 ++++++ src/librustc_resolve/lib.rs | 12 ++++++++++++ 2 files changed, 18 insertions(+) diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs index 8df6458b72e18..3b20c1e74cd39 100644 --- a/src/librustc_resolve/build_reduced_graph.rs +++ b/src/librustc_resolve/build_reduced_graph.rs @@ -344,6 +344,11 @@ impl<'a> Resolver<'a> { } } + ItemKind::TraitAlias(..) => { + let def = Def::TraitAlias(self.definitions.local_def_id(item.id)); + self.define(parent, ident, TypeNS, (def, vis, sp, expansion)); + } + // These items live in both the type and value namespaces. ItemKind::Struct(ref struct_def, _) => { // Define a name in the type namespace. @@ -411,6 +416,7 @@ impl<'a> Resolver<'a> { self.define(parent, ident, TypeNS, (module, vis, sp, expansion)); self.current_module = module; } + ItemKind::MacroDef(..) | ItemKind::Mac(_) => unreachable!(), } } diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 33e57b2d180d6..377c70f642d01 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -474,6 +474,7 @@ impl<'a> PathSource<'a> { }, PathSource::Trait => match def { Def::Trait(..) => true, + Def::TraitAlias(..) => true, _ => false, }, PathSource::Expr(..) => match def { @@ -1935,6 +1936,17 @@ impl<'a> Resolver<'a> { }); } + ItemKind::TraitAlias(ref generics, ref bounds) => { + // Create a new rib for the trait-wide type parameters. + self.with_type_parameter_rib(HasTypeParameters(generics, ItemRibKind), |this| { + let local_def_id = this.definitions.local_def_id(item.id); + this.with_self_rib(Def::SelfTy(Some(local_def_id), None), |this| { + this.visit_generics(generics); + walk_list!(this, visit_ty_param_bound, bounds); + }); + }); + } + ItemKind::Mod(_) | ItemKind::ForeignMod(_) => { self.with_scope(item.id, |this| { visit::walk_item(this, item); From 46dc7c59de28d9390ae1142ea5c15d99872e0c0a Mon Sep 17 00:00:00 2001 From: Alex Burka Date: Mon, 2 Oct 2017 13:49:11 +0000 Subject: [PATCH 03/11] stub out trait aliases in save_analysis --- src/librustc_save_analysis/dump_visitor.rs | 1 + src/librustc_save_analysis/lib.rs | 1 + src/librustc_save_analysis/sig.rs | 19 +++++++++++++++++++ 3 files changed, 21 insertions(+) diff --git a/src/librustc_save_analysis/dump_visitor.rs b/src/librustc_save_analysis/dump_visitor.rs index 7989dba11f7b8..fe6ad92ad00b2 100644 --- a/src/librustc_save_analysis/dump_visitor.rs +++ b/src/librustc_save_analysis/dump_visitor.rs @@ -285,6 +285,7 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> DumpVisitor<'l, 'tcx, 'll, O> { HirDef::Enum(..) | HirDef::TyAlias(..) | HirDef::TyForeign(..) | + HirDef::TraitAlias(..) | HirDef::Trait(_) => { let span = self.span_from_span(sub_span.expect("No span found for type ref")); self.dumper.dump_ref(Ref { diff --git a/src/librustc_save_analysis/lib.rs b/src/librustc_save_analysis/lib.rs index a815c81a6fe0b..97f77b20f8114 100644 --- a/src/librustc_save_analysis/lib.rs +++ b/src/librustc_save_analysis/lib.rs @@ -721,6 +721,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { HirDef::Enum(def_id) | HirDef::TyAlias(def_id) | HirDef::TyForeign(def_id) | + HirDef::TraitAlias(def_id) | HirDef::AssociatedTy(def_id) | HirDef::Trait(def_id) | HirDef::TyParam(def_id) => { diff --git a/src/librustc_save_analysis/sig.rs b/src/librustc_save_analysis/sig.rs index b244876226c48..11d17e0227fdf 100644 --- a/src/librustc_save_analysis/sig.rs +++ b/src/librustc_save_analysis/sig.rs @@ -487,6 +487,25 @@ impl Sig for ast::Item { Ok(sig) } + ast::ItemKind::TraitAlias(ref generics, ref bounds) => { + let mut text = String::new(); + text.push_str("trait "); + let mut sig = name_and_generics(text, + offset, + generics, + self.id, + self.ident, + scx)?; + + if !bounds.is_empty() { + sig.text.push_str(" = "); + sig.text.push_str(&pprust::bounds_to_string(bounds)); + } + // FIXME where clause + sig.text.push_str(";"); + + Ok(sig) + } ast::ItemKind::AutoImpl(unsafety, ref trait_ref) => { let mut text = String::new(); if unsafety == ast::Unsafety::Unsafe { From 1b6ad1e647c9201b9af4d7e9521b51c5d01ec8e6 Mon Sep 17 00:00:00 2001 From: Alex Burka Date: Mon, 4 Dec 2017 00:07:15 -0500 Subject: [PATCH 04/11] stub out trait aliases in librustdoc --- src/librustdoc/visit_ast.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/librustdoc/visit_ast.rs b/src/librustdoc/visit_ast.rs index fe1dac36be1f9..be78935cadfbb 100644 --- a/src/librustdoc/visit_ast.rs +++ b/src/librustdoc/visit_ast.rs @@ -512,6 +512,9 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { }; om.traits.push(t); }, + hir::ItemTraitAlias(..) => { + unimplemented!("trait objects are not yet implemented") + }, hir::ItemImpl(unsafety, polarity, From 2eefc9db15f22c993ba1103cb93d3265e528d667 Mon Sep 17 00:00:00 2001 From: Alex Burka Date: Mon, 2 Oct 2017 12:28:16 +0000 Subject: [PATCH 05/11] add trait aliases to HIR --- src/librustc/hir/def.rs | 5 ++++- src/librustc/hir/intravisit.rs | 5 +++++ src/librustc/hir/lowering.rs | 6 ++++-- src/librustc/hir/map/def_collector.rs | 3 ++- src/librustc/hir/map/mod.rs | 1 + src/librustc/hir/mod.rs | 3 +++ src/librustc/hir/print.rs | 21 +++++++++++++++++++++ src/librustc/ich/impls_hir.rs | 2 ++ src/librustc/middle/reachable.rs | 2 +- src/librustc/middle/resolve_lifetime.rs | 1 + src/librustc_metadata/encoder.rs | 4 +++- src/librustc_privacy/lib.rs | 13 +++++++++++-- src/librustc_trans_utils/collector.rs | 1 + 13 files changed, 59 insertions(+), 8 deletions(-) diff --git a/src/librustc/hir/def.rs b/src/librustc/hir/def.rs index 3ef0633e7f400..19a37b693db6f 100644 --- a/src/librustc/hir/def.rs +++ b/src/librustc/hir/def.rs @@ -37,6 +37,7 @@ pub enum Def { Trait(DefId), TyAlias(DefId), TyForeign(DefId), + TraitAlias(DefId), AssociatedTy(DefId), PrimTy(hir::PrimTy), TyParam(DefId), @@ -155,7 +156,8 @@ impl Def { pub fn def_id(&self) -> DefId { match *self { Def::Fn(id) | Def::Mod(id) | Def::Static(id, _) | - Def::Variant(id) | Def::VariantCtor(id, ..) | Def::Enum(id) | Def::TyAlias(id) | + Def::Variant(id) | Def::VariantCtor(id, ..) | Def::Enum(id) | + Def::TyAlias(id) | Def::TraitAlias(id) | Def::AssociatedTy(id) | Def::TyParam(id) | Def::Struct(id) | Def::StructCtor(id, ..) | Def::Union(id) | Def::Trait(id) | Def::Method(id) | Def::Const(id) | Def::AssociatedConst(id) | Def::Macro(id, ..) | @@ -186,6 +188,7 @@ impl Def { Def::VariantCtor(.., CtorKind::Fictive) => "struct variant", Def::Enum(..) => "enum", Def::TyAlias(..) => "type alias", + Def::TraitAlias(..) => "trait alias", Def::AssociatedTy(..) => "associated type", Def::Struct(..) => "struct", Def::StructCtor(.., CtorKind::Fn) => "tuple struct", diff --git a/src/librustc/hir/intravisit.rs b/src/librustc/hir/intravisit.rs index c9d35158ed002..eacad100f10be 100644 --- a/src/librustc/hir/intravisit.rs +++ b/src/librustc/hir/intravisit.rs @@ -526,6 +526,11 @@ pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item) { walk_list!(visitor, visit_ty_param_bound, bounds); walk_list!(visitor, visit_trait_item_ref, trait_item_refs); } + ItemTraitAlias(ref generics, ref bounds) => { + visitor.visit_id(item.id); + visitor.visit_generics(generics); + walk_list!(visitor, visit_ty_param_bound, bounds); + } } walk_list!(visitor, visit_attribute, &item.attrs); } diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index e3a5e835bb9f6..b544ea820c0f7 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -1924,9 +1924,11 @@ impl<'a> LoweringContext<'a> { bounds, items) } - ItemKind::MacroDef(..) | ItemKind::Mac(..) => { - panic!("Shouldn't still be around") + ItemKind::TraitAlias(ref generics, ref bounds) => { + hir::ItemTraitAlias(self.lower_generics(generics), + self.lower_bounds(bounds, ImplTraitContext::Disallowed)) } + ItemKind::MacroDef(..) | ItemKind::Mac(..) => panic!("Shouldn't still be around"), } // [1] `defaultness.has_value()` is never called for an `impl`, always `true` in order to diff --git a/src/librustc/hir/map/def_collector.rs b/src/librustc/hir/map/def_collector.rs index 17a4c66edb9c9..2978f1eb409d8 100644 --- a/src/librustc/hir/map/def_collector.rs +++ b/src/librustc/hir/map/def_collector.rs @@ -106,7 +106,8 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> { let def_data = match i.node { ItemKind::AutoImpl(..) | ItemKind::Impl(..) => DefPathData::Impl, - ItemKind::Enum(..) | ItemKind::Struct(..) | ItemKind::Union(..) | ItemKind::Trait(..) | + ItemKind::Enum(..) | ItemKind::Struct(..) | ItemKind::Union(..) | + ItemKind::Trait(..) | ItemKind::TraitAlias(..) | ItemKind::ExternCrate(..) | ItemKind::ForeignMod(..) | ItemKind::Ty(..) => DefPathData::TypeNs(i.ident.name.as_str()), ItemKind::Mod(..) if i.ident == keywords::Invalid.ident() => { diff --git a/src/librustc/hir/map/mod.rs b/src/librustc/hir/map/mod.rs index 8969528dd1949..014e57716562c 100644 --- a/src/librustc/hir/map/mod.rs +++ b/src/librustc/hir/map/mod.rs @@ -1185,6 +1185,7 @@ fn node_id_to_string(map: &Map, id: NodeId, include_id: bool) -> String { ItemStruct(..) => "struct", ItemUnion(..) => "union", ItemTrait(..) => "trait", + ItemTraitAlias(..) => "trait alias", ItemImpl(..) => "impl", ItemAutoImpl(..) => "default impl", }; diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs index d6107a8f55197..dc44a943e4cf8 100644 --- a/src/librustc/hir/mod.rs +++ b/src/librustc/hir/mod.rs @@ -1888,6 +1888,8 @@ pub enum Item_ { ItemUnion(VariantData, Generics), /// Represents a Trait Declaration ItemTrait(IsAuto, Unsafety, Generics, TyParamBounds, HirVec), + /// Represents a Trait Alias Declaration + ItemTraitAlias(Generics, TyParamBounds), /// Auto trait implementations /// @@ -1919,6 +1921,7 @@ impl Item_ { ItemStruct(..) => "struct", ItemUnion(..) => "union", ItemTrait(..) => "trait", + ItemTraitAlias(..) => "trait alias", ItemImpl(..) | ItemAutoImpl(..) => "item", } diff --git a/src/librustc/hir/print.rs b/src/librustc/hir/print.rs index fb502ecb996ae..c7bb121e90105 100644 --- a/src/librustc/hir/print.rs +++ b/src/librustc/hir/print.rs @@ -747,6 +747,27 @@ impl<'a> State<'a> { } self.bclose(item.span)?; } + hir::ItemTraitAlias(ref generics, ref bounds) => { + self.head("")?; + self.print_visibility(&item.vis)?; + self.word_nbsp("trait")?; + self.print_name(item.name)?; + self.print_generics(generics)?; + let mut real_bounds = Vec::with_capacity(bounds.len()); + // FIXME(durka) this seems to be some quite outdated syntax + for b in bounds.iter() { + if let TraitTyParamBound(ref ptr, hir::TraitBoundModifier::Maybe) = *b { + self.s.space()?; + self.word_space("for ?")?; + self.print_trait_ref(&ptr.trait_ref)?; + } else { + real_bounds.push(b.clone()); + } + } + self.print_bounds(" = ", &real_bounds[..])?; + self.print_where_clause(&generics.where_clause)?; + self.s.word(";")?; + } } self.ann.post(self, NodeItem(item)) } diff --git a/src/librustc/ich/impls_hir.rs b/src/librustc/ich/impls_hir.rs index 6fc49e5189d55..ff5327ced8b79 100644 --- a/src/librustc/ich/impls_hir.rs +++ b/src/librustc/ich/impls_hir.rs @@ -848,6 +848,7 @@ impl_stable_hash_for!(enum hir::Item_ { ItemStruct(variant_data, generics), ItemUnion(variant_data, generics), ItemTrait(is_auto, unsafety, generics, bounds, item_refs), + ItemTraitAlias(generics, bounds), ItemAutoImpl(unsafety, trait_ref), ItemImpl(unsafety, impl_polarity, impl_defaultness, generics, trait_ref, ty, impl_item_refs) }); @@ -1004,6 +1005,7 @@ impl_stable_hash_for!(enum hir::def::Def { Variant(def_id), Trait(def_id), TyAlias(def_id), + TraitAlias(def_id), AssociatedTy(def_id), PrimTy(prim_ty), TyParam(def_id), diff --git a/src/librustc/middle/reachable.rs b/src/librustc/middle/reachable.rs index d5f26d1117c5b..27f12c2c1587e 100644 --- a/src/librustc/middle/reachable.rs +++ b/src/librustc/middle/reachable.rs @@ -268,7 +268,7 @@ impl<'a, 'tcx> ReachableContext<'a, 'tcx> { hir::ItemExternCrate(_) | hir::ItemUse(..) | hir::ItemTy(..) | hir::ItemStatic(..) | hir::ItemMod(..) | hir::ItemForeignMod(..) | - hir::ItemImpl(..) | hir::ItemTrait(..) | + hir::ItemImpl(..) | hir::ItemTrait(..) | hir::ItemTraitAlias(..) | hir::ItemStruct(..) | hir::ItemEnum(..) | hir::ItemUnion(..) | hir::ItemAutoImpl(..) | hir::ItemGlobalAsm(..) => {} diff --git a/src/librustc/middle/resolve_lifetime.rs b/src/librustc/middle/resolve_lifetime.rs index d9b2bf62841f1..e75762cbacb42 100644 --- a/src/librustc/middle/resolve_lifetime.rs +++ b/src/librustc/middle/resolve_lifetime.rs @@ -469,6 +469,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { | hir::ItemStruct(_, ref generics) | hir::ItemUnion(_, ref generics) | hir::ItemTrait(_, _, ref generics, ..) + | hir::ItemTraitAlias(ref generics, ..) | hir::ItemImpl(_, _, _, ref generics, ..) => { // These kinds of items have only early bound lifetime parameters. let mut index = if let hir::ItemTrait(..) = item.node { diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs index caeee989283fc..5e8bbabee4a9a 100644 --- a/src/librustc_metadata/encoder.rs +++ b/src/librustc_metadata/encoder.rs @@ -979,6 +979,7 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> { EntryKind::Trait(self.lazy(&data)) } hir::ItemExternCrate(_) | + hir::ItemTraitAlias(..) | hir::ItemUse(..) => bug!("cannot encode info for item {:?}", item), }; @@ -1526,7 +1527,8 @@ impl<'a, 'b, 'tcx> IndexBuilder<'a, 'b, 'tcx> { hir::ItemExternCrate(..) | hir::ItemUse(..) | hir::ItemAutoImpl(..) | - hir::ItemTy(..) => { + hir::ItemTy(..) | + hir::ItemTraitAlias(..) => { // no sub-item recording needed in these cases } hir::ItemEnum(..) => { diff --git a/src/librustc_privacy/lib.rs b/src/librustc_privacy/lib.rs index 27898b5dd64bc..d41881218129f 100644 --- a/src/librustc_privacy/lib.rs +++ b/src/librustc_privacy/lib.rs @@ -158,7 +158,8 @@ impl<'a, 'tcx> Visitor<'tcx> for EmbargoVisitor<'a, 'tcx> { // Other `pub` items inherit levels from parents hir::ItemConst(..) | hir::ItemEnum(..) | hir::ItemExternCrate(..) | hir::ItemGlobalAsm(..) | hir::ItemFn(..) | hir::ItemMod(..) | - hir::ItemStatic(..) | hir::ItemStruct(..) | hir::ItemTrait(..) | + hir::ItemStatic(..) | hir::ItemStruct(..) | + hir::ItemTrait(..) | hir::ItemTraitAlias(..) | hir::ItemTy(..) | hir::ItemUnion(..) | hir::ItemUse(..) => { if item.vis == hir::Public { self.prev_level } else { None } } @@ -212,7 +213,7 @@ impl<'a, 'tcx> Visitor<'tcx> for EmbargoVisitor<'a, 'tcx> { } } hir::ItemUse(..) | hir::ItemStatic(..) | hir::ItemConst(..) | - hir::ItemGlobalAsm(..) | hir::ItemTy(..) | hir::ItemMod(..) | + hir::ItemGlobalAsm(..) | hir::ItemTy(..) | hir::ItemMod(..) | hir::ItemTraitAlias(..) | hir::ItemFn(..) | hir::ItemExternCrate(..) | hir::ItemAutoImpl(..) => {} } @@ -252,6 +253,11 @@ impl<'a, 'tcx> Visitor<'tcx> for EmbargoVisitor<'a, 'tcx> { } } } + hir::ItemTraitAlias(..) => { + if item_level.is_some() { + self.reach(item.id).generics().predicates(); + } + } // Visit everything except for private impl items hir::ItemImpl(.., ref trait_ref, _, ref impl_item_refs) => { if item_level.is_some() { @@ -1498,6 +1504,9 @@ impl<'a, 'tcx> Visitor<'tcx> for PrivateItemsInPublicInterfacesVisitor<'a, 'tcx> } } } + hir::ItemTraitAlias(..) => { + self.check(item.id, item_visibility).generics().predicates(); + } hir::ItemEnum(ref def, _) => { self.check(item.id, item_visibility).generics().predicates(); diff --git a/src/librustc_trans_utils/collector.rs b/src/librustc_trans_utils/collector.rs index e5a97966723d2..56b1a0238a1a6 100644 --- a/src/librustc_trans_utils/collector.rs +++ b/src/librustc_trans_utils/collector.rs @@ -894,6 +894,7 @@ impl<'b, 'a, 'v> ItemLikeVisitor<'v> for RootCollector<'b, 'a, 'v> { hir::ItemTy(..) | hir::ItemAutoImpl(..) | hir::ItemTrait(..) | + hir::ItemTraitAlias(..) | hir::ItemMod(..) => { // Nothing to do, just keep recursing... } From 63f1c24d8ac1f920da7564aa59027b2bd5c7d1bd Mon Sep 17 00:00:00 2001 From: Alex Burka Date: Mon, 9 Oct 2017 17:49:53 +0200 Subject: [PATCH 06/11] add trait aliases to typeck --- src/librustc/ty/mod.rs | 1 + src/librustc_typeck/astconv.rs | 1 + src/librustc_typeck/collect.rs | 11 +++++++++-- 3 files changed, 11 insertions(+), 2 deletions(-) diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index 93ef29855ce1d..4e1a79d4613e7 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -2577,6 +2577,7 @@ fn associated_item_def_ids<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, .map(|id| tcx.hir.local_def_id(id.node_id)) .collect() } + hir::ItemTraitAlias(..) => vec![], _ => span_bug!(item.span, "associated_item_def_ids: not impl or trait") }; Rc::new(vec) diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index 83aec27c15315..6b37a30cb82d8 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -336,6 +336,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { let path = &trait_ref.path; match path.def { Def::Trait(trait_def_id) => trait_def_id, + Def::TraitAlias(alias_def_id) => alias_def_id, Def::Err => { self.tcx().sess.fatal("cannot continue compilation due to previous error"); } diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index 85b926a707db3..918146605fd4d 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -441,6 +441,11 @@ fn convert_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, item_id: ast::NodeId) { tcx.at(it.span).super_predicates_of(def_id); tcx.predicates_of(def_id); }, + hir::ItemTraitAlias(..) => { + tcx.generics_of(def_id); + tcx.trait_def(def_id); + tcx.predicates_of(def_id); + }, hir::ItemStruct(ref struct_def, _) | hir::ItemUnion(ref struct_def, _) => { tcx.generics_of(def_id); @@ -672,6 +677,7 @@ fn super_predicates_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, let (generics, bounds) = match item.node { hir::ItemTrait(.., ref generics, ref supertraits, _) => (generics, supertraits), + hir::ItemTraitAlias(ref generics, ref supertraits) => (generics, supertraits), _ => span_bug!(item.span, "super_predicates invoked on non-trait"), }; @@ -715,6 +721,7 @@ fn trait_def<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, let unsafety = match item.node { hir::ItemTrait(_, unsafety, ..) => unsafety, + hir::ItemTraitAlias(..) => hir::Unsafety::Normal, _ => span_bug!(item.span, "trait_def_of_item invoked on non-trait"), }; @@ -902,7 +909,7 @@ fn generics_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, (generics, None) } - ItemTrait(_, _, ref generics, ..) => { + ItemTrait(_, _, ref generics, ..) | ItemTraitAlias(ref generics, ..) => { // Add in the self type parameter. // // Something of a hack: use the node id for the trait, also as @@ -1132,7 +1139,7 @@ fn type_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, tcx.mk_adt(def, substs) } ItemAutoImpl(..) | - ItemTrait(..) | + ItemTrait(..) | ItemTraitAlias(..) | ItemMod(..) | ItemForeignMod(..) | ItemGlobalAsm(..) | From 4029a0198433a4b03dc4b4529164ee4872fc2834 Mon Sep 17 00:00:00 2001 From: Alex Burka Date: Sun, 3 Dec 2017 12:57:54 -0500 Subject: [PATCH 07/11] error on any use of trait alias --- src/librustc_typeck/collect.rs | 5 ++-- src/librustc_typeck/diagnostics.rs | 1 + src/test/compile-fail/trait-alias.rs | 2 ++ src/test/{run-pass => ui}/trait-alias.rs | 12 ++++---- src/test/ui/trait-alias.stderr | 38 ++++++++++++++++++++++++ 5 files changed, 49 insertions(+), 9 deletions(-) rename src/test/{run-pass => ui}/trait-alias.rs (76%) create mode 100644 src/test/ui/trait-alias.stderr diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index 918146605fd4d..3d4d8e65f699d 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -442,9 +442,8 @@ fn convert_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, item_id: ast::NodeId) { tcx.predicates_of(def_id); }, hir::ItemTraitAlias(..) => { - tcx.generics_of(def_id); - tcx.trait_def(def_id); - tcx.predicates_of(def_id); + span_err!(tcx.sess, it.span, E0645, + "trait aliases are not yet implemented (see issue #41517)"); }, hir::ItemStruct(ref struct_def, _) | hir::ItemUnion(ref struct_def, _) => { diff --git a/src/librustc_typeck/diagnostics.rs b/src/librustc_typeck/diagnostics.rs index 328b7f9fdefca..770d0cd4f1fc4 100644 --- a/src/librustc_typeck/diagnostics.rs +++ b/src/librustc_typeck/diagnostics.rs @@ -4721,4 +4721,5 @@ register_diagnostics! { E0632, // cannot provide explicit type parameters when `impl Trait` is used in // argument position. E0641, // cannot cast to/from a pointer with an unknown kind + E0645, // trait aliases not finished } diff --git a/src/test/compile-fail/trait-alias.rs b/src/test/compile-fail/trait-alias.rs index de87fe39395c8..5d4112e4a5e4d 100644 --- a/src/test/compile-fail/trait-alias.rs +++ b/src/test/compile-fail/trait-alias.rs @@ -9,9 +9,11 @@ // except according to those terms. trait Alias1 = Default where T: Clone; // ok + //~^ERROR trait aliases are not yet implemented trait Alias2 = Default; //~^ERROR type parameters on the left side of a trait alias cannot be bounded //~^^ERROR type parameters on the left side of a trait alias cannot have defaults + //~^^^ERROR trait aliases are not yet implemented impl Alias1 { //~ERROR expected type, found trait alias fn foo() {} diff --git a/src/test/run-pass/trait-alias.rs b/src/test/ui/trait-alias.rs similarity index 76% rename from src/test/run-pass/trait-alias.rs rename to src/test/ui/trait-alias.rs index 529765320a292..b794bab847044 100644 --- a/src/test/run-pass/trait-alias.rs +++ b/src/test/ui/trait-alias.rs @@ -8,9 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -trait SimpleAlias = Default; -trait GenericAlias = Iterator; -trait Partial = IntoIterator; +trait SimpleAlias = Default; //~ERROR E0645 +trait GenericAlias = Iterator; //~ERROR E0645 +trait Partial = IntoIterator; //~ERROR E0645 trait Things {} trait Romeo {} @@ -19,10 +19,10 @@ struct Fore(T); impl Things for The {} impl Romeo for Fore {} -trait WithWhere = Romeo + Romeo where Fore<(Art, Thou)>: Romeo; -trait BareWhere = where The: Things; +trait WithWhere = Romeo + Romeo where Fore<(Art, Thou)>: Romeo; //~ERROR E0645 +trait BareWhere = where The: Things; //~ERROR E0645 -trait CD = Clone + Default; +trait CD = Clone + Default; //~ERROR E0645 fn foo() -> (T, T) { let one = T::default(); diff --git a/src/test/ui/trait-alias.stderr b/src/test/ui/trait-alias.stderr new file mode 100644 index 0000000000000..4a8de37a39357 --- /dev/null +++ b/src/test/ui/trait-alias.stderr @@ -0,0 +1,38 @@ +error[E0645]: trait aliases are not yet implemented (see issue #41517) + --> $DIR/trait-alias.rs:11:1 + | +11 | trait SimpleAlias = Default; //~ERROR E0645 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0645]: trait aliases are not yet implemented (see issue #41517) + --> $DIR/trait-alias.rs:12:1 + | +12 | trait GenericAlias = Iterator; //~ERROR E0645 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0645]: trait aliases are not yet implemented (see issue #41517) + --> $DIR/trait-alias.rs:13:1 + | +13 | trait Partial = IntoIterator; //~ERROR E0645 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0645]: trait aliases are not yet implemented (see issue #41517) + --> $DIR/trait-alias.rs:22:1 + | +22 | trait WithWhere = Romeo + Romeo where Fore<(Art, Thou)>: Romeo; //~ERROR E0645 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0645]: trait aliases are not yet implemented (see issue #41517) + --> $DIR/trait-alias.rs:23:1 + | +23 | trait BareWhere = where The: Things; //~ERROR E0645 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0645]: trait aliases are not yet implemented (see issue #41517) + --> $DIR/trait-alias.rs:25:1 + | +25 | trait CD = Clone + Default; //~ERROR E0645 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 6 previous errors + From 4f0b4f267f98e9ec719ee5ac1aaa2a39467ffc98 Mon Sep 17 00:00:00 2001 From: Alex Burka Date: Sun, 3 Dec 2017 12:55:22 -0500 Subject: [PATCH 08/11] feature gate trait aliases --- src/libsyntax/feature_gate.rs | 8 ++++++++ src/test/compile-fail/trait-alias.rs | 6 ++++-- src/test/ui/trait-alias.rs | 2 ++ src/test/ui/trait-alias.stderr | 24 ++++++++++++------------ 4 files changed, 26 insertions(+), 14 deletions(-) diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index c7bfb121f801e..ba534676324a9 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -368,6 +368,8 @@ declare_features! ( // Generators (active, generators, "1.21.0", None), + // Trait aliases + (active, trait_alias, "1.24.0", Some(41517)), // global allocators and their internals (active, global_allocator, "1.20.0", None), @@ -1406,6 +1408,12 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { } } + ast::ItemKind::TraitAlias(..) => { + gate_feature_post!(&self, trait_alias, + i.span, + "trait aliases are not yet fully implemented"); + } + ast::ItemKind::AutoImpl(..) => { gate_feature_post!(&self, optin_builtin_traits, i.span, diff --git a/src/test/compile-fail/trait-alias.rs b/src/test/compile-fail/trait-alias.rs index 5d4112e4a5e4d..12cfd4ce0e5b9 100644 --- a/src/test/compile-fail/trait-alias.rs +++ b/src/test/compile-fail/trait-alias.rs @@ -8,12 +8,14 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// gate-test-trait_alias + trait Alias1 = Default where T: Clone; // ok - //~^ERROR trait aliases are not yet implemented + //~^ERROR trait aliases are not yet fully implemented trait Alias2 = Default; //~^ERROR type parameters on the left side of a trait alias cannot be bounded //~^^ERROR type parameters on the left side of a trait alias cannot have defaults - //~^^^ERROR trait aliases are not yet implemented + //~^^^ERROR trait aliases are not yet fully implemented impl Alias1 { //~ERROR expected type, found trait alias fn foo() {} diff --git a/src/test/ui/trait-alias.rs b/src/test/ui/trait-alias.rs index b794bab847044..9ea211b4d7d69 100644 --- a/src/test/ui/trait-alias.rs +++ b/src/test/ui/trait-alias.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![feature(trait_alias)] + trait SimpleAlias = Default; //~ERROR E0645 trait GenericAlias = Iterator; //~ERROR E0645 trait Partial = IntoIterator; //~ERROR E0645 diff --git a/src/test/ui/trait-alias.stderr b/src/test/ui/trait-alias.stderr index 4a8de37a39357..ad299dc84145c 100644 --- a/src/test/ui/trait-alias.stderr +++ b/src/test/ui/trait-alias.stderr @@ -1,37 +1,37 @@ error[E0645]: trait aliases are not yet implemented (see issue #41517) - --> $DIR/trait-alias.rs:11:1 + --> $DIR/trait-alias.rs:13:1 | -11 | trait SimpleAlias = Default; //~ERROR E0645 +13 | trait SimpleAlias = Default; //~ERROR E0645 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0645]: trait aliases are not yet implemented (see issue #41517) - --> $DIR/trait-alias.rs:12:1 + --> $DIR/trait-alias.rs:14:1 | -12 | trait GenericAlias = Iterator; //~ERROR E0645 +14 | trait GenericAlias = Iterator; //~ERROR E0645 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0645]: trait aliases are not yet implemented (see issue #41517) - --> $DIR/trait-alias.rs:13:1 + --> $DIR/trait-alias.rs:15:1 | -13 | trait Partial = IntoIterator; //~ERROR E0645 +15 | trait Partial = IntoIterator; //~ERROR E0645 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0645]: trait aliases are not yet implemented (see issue #41517) - --> $DIR/trait-alias.rs:22:1 + --> $DIR/trait-alias.rs:24:1 | -22 | trait WithWhere = Romeo + Romeo where Fore<(Art, Thou)>: Romeo; //~ERROR E0645 +24 | trait WithWhere = Romeo + Romeo where Fore<(Art, Thou)>: Romeo; //~ERROR E0645 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0645]: trait aliases are not yet implemented (see issue #41517) - --> $DIR/trait-alias.rs:23:1 + --> $DIR/trait-alias.rs:25:1 | -23 | trait BareWhere = where The: Things; //~ERROR E0645 +25 | trait BareWhere = where The: Things; //~ERROR E0645 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0645]: trait aliases are not yet implemented (see issue #41517) - --> $DIR/trait-alias.rs:25:1 + --> $DIR/trait-alias.rs:27:1 | -25 | trait CD = Clone + Default; //~ERROR E0645 +27 | trait CD = Clone + Default; //~ERROR E0645 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 6 previous errors From 435fe5b7946d99a4da0008938dee33d81329cef9 Mon Sep 17 00:00:00 2001 From: Alex Burka Date: Mon, 4 Dec 2017 14:47:49 -0500 Subject: [PATCH 09/11] trait alias fallout --- src/librustc_driver/test.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/librustc_driver/test.rs b/src/librustc_driver/test.rs index f04e01f3f961d..ded2fa01e5977 100644 --- a/src/librustc_driver/test.rs +++ b/src/librustc_driver/test.rs @@ -248,6 +248,7 @@ impl<'a, 'gcx, 'tcx> Env<'a, 'gcx, 'tcx> { hir::ItemStruct(..) | hir::ItemUnion(..) | hir::ItemTrait(..) | + hir::ItemTraitAlias(..) | hir::ItemImpl(..) | hir::ItemAutoImpl(..) => None, From aaeae4c72e645af5435cc03d981c3e12dcb76658 Mon Sep 17 00:00:00 2001 From: Alex Burka Date: Wed, 13 Dec 2017 01:56:22 -0500 Subject: [PATCH 10/11] error for impl trait alias --- src/librustc_resolve/lib.rs | 32 ++++++++++++++++++---------- src/test/compile-fail/trait-alias.rs | 4 +++- 2 files changed, 24 insertions(+), 12 deletions(-) diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 377c70f642d01..c42ac7aaa937c 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -390,12 +390,18 @@ impl PatternSource { } } +#[derive(Copy, Clone, PartialEq, Eq, Debug)] +enum AliasPossibility { + No, + Maybe, +} + #[derive(Copy, Clone, PartialEq, Eq, Debug)] enum PathSource<'a> { // Type paths `Path`. Type, // Trait paths in bounds or impls. - Trait, + Trait(AliasPossibility), // Expression paths `path`, with optional parent context. Expr(Option<&'a Expr>), // Paths in path patterns `Path`. @@ -415,7 +421,7 @@ enum PathSource<'a> { impl<'a> PathSource<'a> { fn namespace(self) -> Namespace { match self { - PathSource::Type | PathSource::Trait | PathSource::Struct | + PathSource::Type | PathSource::Trait(_) | PathSource::Struct | PathSource::Visibility | PathSource::ImportPrefix => TypeNS, PathSource::Expr(..) | PathSource::Pat | PathSource::TupleStruct => ValueNS, PathSource::TraitItem(ns) => ns, @@ -427,7 +433,7 @@ impl<'a> PathSource<'a> { PathSource::Visibility | PathSource::ImportPrefix => true, PathSource::Type | PathSource::Expr(..) | PathSource::Pat | PathSource::Struct | PathSource::TupleStruct | - PathSource::Trait | PathSource::TraitItem(..) => false, + PathSource::Trait(_) | PathSource::TraitItem(..) => false, } } @@ -435,7 +441,7 @@ impl<'a> PathSource<'a> { match self { PathSource::Type | PathSource::Expr(..) | PathSource::Pat | PathSource::Struct | PathSource::TupleStruct => true, - PathSource::Trait | PathSource::TraitItem(..) | + PathSource::Trait(_) | PathSource::TraitItem(..) | PathSource::Visibility | PathSource::ImportPrefix => false, } } @@ -443,7 +449,7 @@ impl<'a> PathSource<'a> { fn descr_expected(self) -> &'static str { match self { PathSource::Type => "type", - PathSource::Trait => "trait", + PathSource::Trait(_) => "trait", PathSource::Pat => "unit struct/variant or constant", PathSource::Struct => "struct, variant or union type", PathSource::TupleStruct => "tuple struct/variant", @@ -472,7 +478,11 @@ impl<'a> PathSource<'a> { Def::TyForeign(..) => true, _ => false, }, - PathSource::Trait => match def { + PathSource::Trait(AliasPossibility::No) => match def { + Def::Trait(..) => true, + _ => false, + }, + PathSource::Trait(AliasPossibility::Maybe) => match def { Def::Trait(..) => true, Def::TraitAlias(..) => true, _ => false, @@ -531,8 +541,8 @@ impl<'a> PathSource<'a> { __diagnostic_used!(E0577); __diagnostic_used!(E0578); match (self, has_unexpected_resolution) { - (PathSource::Trait, true) => "E0404", - (PathSource::Trait, false) => "E0405", + (PathSource::Trait(_), true) => "E0404", + (PathSource::Trait(_), false) => "E0405", (PathSource::Type, true) => "E0573", (PathSource::Type, false) => "E0412", (PathSource::Struct, true) => "E0574", @@ -694,7 +704,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Resolver<'a> { tref: &'tcx ast::PolyTraitRef, m: &'tcx ast::TraitBoundModifier) { self.smart_resolve_path(tref.trait_ref.ref_id, None, - &tref.trait_ref.path, PathSource::Trait); + &tref.trait_ref.path, PathSource::Trait(AliasPossibility::Maybe)); visit::walk_poly_trait_ref(self, tref, m); } fn visit_variant(&mut self, @@ -2095,7 +2105,7 @@ impl<'a> Resolver<'a> { &path, trait_ref.path.span, trait_ref.path.segments.last().unwrap().span, - PathSource::Trait) + PathSource::Trait(AliasPossibility::No)) .base_def(); if def != Def::Err { new_id = Some(def.def_id()); @@ -2647,7 +2657,7 @@ impl<'a> Resolver<'a> { err.span_label(span, format!("did you mean `{}!(...)`?", path_str)); return (err, candidates); } - (Def::TyAlias(..), PathSource::Trait) => { + (Def::TyAlias(..), PathSource::Trait(_)) => { err.span_label(span, "type aliases cannot be used for traits"); return (err, candidates); } diff --git a/src/test/compile-fail/trait-alias.rs b/src/test/compile-fail/trait-alias.rs index 12cfd4ce0e5b9..7aca227a76c48 100644 --- a/src/test/compile-fail/trait-alias.rs +++ b/src/test/compile-fail/trait-alias.rs @@ -18,7 +18,9 @@ trait Alias2 = Default; //~^^^ERROR trait aliases are not yet fully implemented impl Alias1 { //~ERROR expected type, found trait alias - fn foo() {} +} + +impl Alias1 for () { //~ERROR expected trait, found trait alias } fn main() {} From 834674fa1d97f0e83baf99e1da5e24b82d41f63c Mon Sep 17 00:00:00 2001 From: Alex Burka Date: Thu, 14 Dec 2017 12:55:20 -0500 Subject: [PATCH 11/11] rls depends on rustfmt --- src/tools/toolstate.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/src/tools/toolstate.toml b/src/tools/toolstate.toml index 3f0d13b585c40..b29e505c3b09e 100644 --- a/src/tools/toolstate.toml +++ b/src/tools/toolstate.toml @@ -32,4 +32,5 @@ clippy = "Testing" rls = "Broken" # ping @nrc +# when breaking rustfmt, always break rls as well rustfmt = "Broken"