Skip to content

Commit

Permalink
Auto merge of #45247 - leodasvacas:implement-auto-trait-syntax, r=nik…
Browse files Browse the repository at this point in the history
…omatsakis

[Syntax] Implement auto trait syntax

Implements `auto trait Send {}` as a substitute for `trait Send {} impl Send for .. {}`.

See the [internals thread](https://internals.rust-lang.org/t/pre-rfc-renaming-oibits-and-changing-their-declaration-syntax/3086) for motivation. Part of #13231.

The first commit is just a rename moving from "default trait" to "auto trait". The rest is parser->AST->HIR work and making it the same as the current syntax for everything below HIR. It's under the `optin_builtin_traits` feature gate.

When can we remove the old syntax? Do we need to wait for a new `stage0`? We also need to formally decide for the new form (even if the keyword is not settled yet).

Observations:
- If you `auto trait Auto {}` and then `impl Auto for .. {}` that's accepted even if it's redundant.
- The new syntax is simpler internally which will allow for a net removal of code, for example well-formedness checks are effectively moved to the parser.
- Rustfmt and clippy are broken, need to fix those.
- Rustdoc just ignores it for now.

ping @petrochenkov @nikomatsakis
  • Loading branch information
bors committed Nov 3, 2017
2 parents 59d4845 + 5190abb commit 2278506
Show file tree
Hide file tree
Showing 97 changed files with 494 additions and 216 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,7 @@ Example:
```rust
#![feature(optin_builtin_traits)]

trait Valid {}

impl Valid for .. {}
auto trait Valid {}

struct True;
struct False;
Expand Down
6 changes: 6 additions & 0 deletions src/libcore/marker.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@ pub unsafe trait Send {
}

#[stable(feature = "rust1", since = "1.0.0")]
#[allow(unknown_lints)]
#[allow(auto_impl)]
unsafe impl Send for .. { }

#[stable(feature = "rust1", since = "1.0.0")]
Expand Down Expand Up @@ -349,6 +351,8 @@ pub unsafe trait Sync {
}

#[stable(feature = "rust1", since = "1.0.0")]
#[allow(unknown_lints)]
#[allow(auto_impl)]
unsafe impl Sync for .. { }

#[stable(feature = "rust1", since = "1.0.0")]
Expand Down Expand Up @@ -562,6 +566,8 @@ mod impls {
#[lang = "freeze"]
unsafe trait Freeze {}

#[allow(unknown_lints)]
#[allow(auto_impl)]
unsafe impl Freeze for .. {}

impl<T: ?Sized> !Freeze for UnsafeCell<T> {}
Expand Down
2 changes: 1 addition & 1 deletion src/librustc/dep_graph/dep_node.rs
Original file line number Diff line number Diff line change
Expand Up @@ -498,7 +498,7 @@ define_dep_nodes!( <'tcx>
[] SuperPredicatesOfItem(DefId),
[] TraitDefOfItem(DefId),
[] AdtDefOfItem(DefId),
[] IsDefaultImpl(DefId),
[] IsAutoImpl(DefId),
[] ImplTraitRef(DefId),
[] ImplPolarity(DefId),
[] ClosureKind(DefId),
Expand Down
4 changes: 2 additions & 2 deletions src/librustc/hir/intravisit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -503,7 +503,7 @@ pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item) {
// visit_enum_def() takes care of visiting the Item's NodeId
visitor.visit_enum_def(enum_definition, type_parameters, item.id, item.span)
}
ItemDefaultImpl(_, ref trait_ref) => {
ItemAutoImpl(_, ref trait_ref) => {
visitor.visit_id(item.id);
visitor.visit_trait_ref(trait_ref)
}
Expand All @@ -520,7 +520,7 @@ pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item) {
visitor.visit_id(item.id);
visitor.visit_variant_data(struct_definition, item.name, generics, item.id, item.span);
}
ItemTrait(_, ref generics, ref bounds, ref trait_item_refs) => {
ItemTrait(.., ref generics, ref bounds, ref trait_item_refs) => {
visitor.visit_id(item.id);
visitor.visit_generics(generics);
walk_list!(visitor, visit_ty_param_bound, bounds);
Expand Down
26 changes: 17 additions & 9 deletions src/librustc/hir/lowering.rs
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ pub struct LoweringContext<'a> {
exported_macros: Vec<hir::MacroDef>,

trait_impls: BTreeMap<DefId, Vec<NodeId>>,
trait_default_impl: BTreeMap<DefId, NodeId>,
trait_auto_impl: BTreeMap<DefId, NodeId>,

is_generator: bool,

Expand Down Expand Up @@ -146,7 +146,7 @@ pub fn lower_crate(sess: &Session,
impl_items: BTreeMap::new(),
bodies: BTreeMap::new(),
trait_impls: BTreeMap::new(),
trait_default_impl: BTreeMap::new(),
trait_auto_impl: BTreeMap::new(),
exported_macros: Vec::new(),
catch_scopes: Vec::new(),
loop_scopes: Vec::new(),
Expand Down Expand Up @@ -198,7 +198,7 @@ impl<'a> LoweringContext<'a> {
ItemKind::Union(_, ref generics) |
ItemKind::Enum(_, ref generics) |
ItemKind::Ty(_, ref generics) |
ItemKind::Trait(_, ref generics, ..) => {
ItemKind::Trait(_, _, ref generics, ..) => {
let def_id = self.lctx.resolver.definitions().local_def_id(item.id);
let count = generics.lifetimes.len();
self.lctx.type_def_lifetime_params.insert(def_id, count);
Expand Down Expand Up @@ -284,7 +284,7 @@ impl<'a> LoweringContext<'a> {
bodies: self.bodies,
body_ids,
trait_impls: self.trait_impls,
trait_default_impl: self.trait_default_impl,
trait_auto_impl: self.trait_auto_impl,
}
}

Expand Down Expand Up @@ -1479,14 +1479,14 @@ impl<'a> LoweringContext<'a> {
let vdata = self.lower_variant_data(vdata);
hir::ItemUnion(vdata, self.lower_generics(generics))
}
ItemKind::DefaultImpl(unsafety, ref trait_ref) => {
ItemKind::AutoImpl(unsafety, ref trait_ref) => {
let trait_ref = self.lower_trait_ref(trait_ref);

if let Def::Trait(def_id) = trait_ref.path.def {
self.trait_default_impl.insert(def_id, id);
self.trait_auto_impl.insert(def_id, id);
}

hir::ItemDefaultImpl(self.lower_unsafety(unsafety),
hir::ItemAutoImpl(self.lower_unsafety(unsafety),
trait_ref)
}
ItemKind::Impl(unsafety,
Expand Down Expand Up @@ -1515,10 +1515,11 @@ impl<'a> LoweringContext<'a> {
self.lower_ty(ty),
new_impl_items)
}
ItemKind::Trait(unsafety, ref generics, ref bounds, ref items) => {
ItemKind::Trait(is_auto, unsafety, ref generics, ref bounds, ref items) => {
let bounds = self.lower_bounds(bounds);
let items = items.iter().map(|item| self.lower_trait_item_ref(item)).collect();
hir::ItemTrait(self.lower_unsafety(unsafety),
hir::ItemTrait(self.lower_is_auto(is_auto),
self.lower_unsafety(unsafety),
self.lower_generics(generics),
bounds,
items)
Expand Down Expand Up @@ -1741,6 +1742,13 @@ impl<'a> LoweringContext<'a> {
}
}

fn lower_is_auto(&mut self, a: IsAuto) -> hir::IsAuto {
match a {
IsAuto::Yes => hir::IsAuto::Yes,
IsAuto::No => hir::IsAuto::No,
}
}

fn lower_unsafety(&mut self, u: Unsafety) -> hir::Unsafety {
match u {
Unsafety::Unsafe => hir::Unsafety::Unsafe,
Expand Down
2 changes: 1 addition & 1 deletion src/librustc/hir/map/collector.rs
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ impl<'a, 'hir> NodeCollector<'a, 'hir> {
impl_items: _,
bodies: _,
trait_impls: _,
trait_default_impl: _,
trait_auto_impl: _,
body_ids: _,
} = *krate;

Expand Down
2 changes: 1 addition & 1 deletion src/librustc/hir/map/def_collector.rs
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> {
// Pick the def data. This need not be unique, but the more
// information we encapsulate into
let def_data = match i.node {
ItemKind::DefaultImpl(..) | ItemKind::Impl(..) =>
ItemKind::AutoImpl(..) | ItemKind::Impl(..) =>
DefPathData::Impl,
ItemKind::Enum(..) | ItemKind::Struct(..) | ItemKind::Union(..) | ItemKind::Trait(..) |
ItemKind::ExternCrate(..) | ItemKind::ForeignMod(..) | ItemKind::Ty(..) =>
Expand Down
8 changes: 4 additions & 4 deletions src/librustc/hir/map/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -474,16 +474,16 @@ impl<'hir> Map<'hir> {
self.forest.krate.trait_impls.get(&trait_did).map_or(&[], |xs| &xs[..])
}

pub fn trait_default_impl(&self, trait_did: DefId) -> Option<NodeId> {
pub fn trait_auto_impl(&self, trait_did: DefId) -> Option<NodeId> {
self.dep_graph.read(DepNode::new_no_params(DepKind::AllLocalTraitImpls));

// NB: intentionally bypass `self.forest.krate()` so that we
// do not trigger a read of the whole krate here
self.forest.krate.trait_default_impl.get(&trait_did).cloned()
self.forest.krate.trait_auto_impl.get(&trait_did).cloned()
}

pub fn trait_is_auto(&self, trait_did: DefId) -> bool {
self.trait_default_impl(trait_did).is_some()
self.trait_auto_impl(trait_did).is_some()
}

/// Get the attributes on the krate. This is preferable to
Expand Down Expand Up @@ -1140,7 +1140,7 @@ fn node_id_to_string(map: &Map, id: NodeId, include_id: bool) -> String {
ItemUnion(..) => "union",
ItemTrait(..) => "trait",
ItemImpl(..) => "impl",
ItemDefaultImpl(..) => "default impl",
ItemAutoImpl(..) => "default impl",
};
format!("{} {}{}", item_str, path_str(), id_str)
}
Expand Down
19 changes: 13 additions & 6 deletions src/librustc/hir/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -499,7 +499,7 @@ pub struct Crate {
pub impl_items: BTreeMap<ImplItemId, ImplItem>,
pub bodies: BTreeMap<BodyId, Body>,
pub trait_impls: BTreeMap<DefId, Vec<NodeId>>,
pub trait_default_impl: BTreeMap<DefId, NodeId>,
pub trait_auto_impl: BTreeMap<DefId, NodeId>,

/// A list of the body ids written out in the order in which they
/// appear in the crate. If you're going to process all the bodies
Expand Down Expand Up @@ -1500,6 +1500,13 @@ pub struct FnDecl {
pub has_implicit_self: bool,
}

/// Is the trait definition an auto trait?
#[derive(Copy, Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
pub enum IsAuto {
Yes,
No
}

#[derive(Copy, Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
pub enum Unsafety {
Unsafe,
Expand Down Expand Up @@ -1811,12 +1818,12 @@ pub enum Item_ {
/// A union definition, e.g. `union Foo<A, B> {x: A, y: B}`
ItemUnion(VariantData, Generics),
/// Represents a Trait Declaration
ItemTrait(Unsafety, Generics, TyParamBounds, HirVec<TraitItemRef>),
ItemTrait(IsAuto, Unsafety, Generics, TyParamBounds, HirVec<TraitItemRef>),

// Default trait implementations
/// Auto trait implementations
///
/// `impl Trait for .. {}`
ItemDefaultImpl(Unsafety, TraitRef),
ItemAutoImpl(Unsafety, TraitRef),
/// An implementation, eg `impl<A> Trait for Foo { .. }`
ItemImpl(Unsafety,
ImplPolarity,
Expand Down Expand Up @@ -1844,7 +1851,7 @@ impl Item_ {
ItemUnion(..) => "union",
ItemTrait(..) => "trait",
ItemImpl(..) |
ItemDefaultImpl(..) => "item",
ItemAutoImpl(..) => "item",
}
}

Expand All @@ -1864,7 +1871,7 @@ impl Item_ {
ItemEnum(_, ref generics) |
ItemStruct(_, ref generics) |
ItemUnion(_, ref generics) |
ItemTrait(_, ref generics, _, _) |
ItemTrait(_, _, ref generics, _, _) |
ItemImpl(_, _, _, ref generics, _, _, _)=> generics,
_ => return None
})
Expand Down
12 changes: 10 additions & 2 deletions src/librustc/hir/print.rs
Original file line number Diff line number Diff line change
Expand Up @@ -660,7 +660,7 @@ impl<'a> State<'a> {
self.head(&visibility_qualified(&item.vis, "union"))?;
self.print_struct(struct_def, generics, item.name, item.span, true)?;
}
hir::ItemDefaultImpl(unsafety, ref trait_ref) => {
hir::ItemAutoImpl(unsafety, ref trait_ref) => {
self.head("")?;
self.print_visibility(&item.vis)?;
self.print_unsafety(unsafety)?;
Expand Down Expand Up @@ -717,9 +717,10 @@ impl<'a> State<'a> {
}
self.bclose(item.span)?;
}
hir::ItemTrait(unsafety, ref generics, ref bounds, ref trait_items) => {
hir::ItemTrait(is_auto, unsafety, ref generics, ref bounds, ref trait_items) => {
self.head("")?;
self.print_visibility(&item.vis)?;
self.print_is_auto(is_auto)?;
self.print_unsafety(unsafety)?;
self.word_nbsp("trait")?;
self.print_name(item.name)?;
Expand Down Expand Up @@ -2274,6 +2275,13 @@ impl<'a> State<'a> {
hir::Unsafety::Unsafe => self.word_nbsp("unsafe"),
}
}

pub fn print_is_auto(&mut self, s: hir::IsAuto) -> io::Result<()> {
match s {
hir::IsAuto::Yes => self.word_nbsp("auto"),
hir::IsAuto::No => Ok(()),
}
}
}

// Dup'ed from parse::classify, but adapted for the HIR.
Expand Down
10 changes: 7 additions & 3 deletions src/librustc/ich/impls_hir.rs
Original file line number Diff line number Diff line change
Expand Up @@ -898,7 +898,7 @@ impl<'gcx> HashStable<StableHashingContext<'gcx>> for hir::Item {
hir::ItemForeignMod(..) |
hir::ItemGlobalAsm(..) |
hir::ItemMod(..) |
hir::ItemDefaultImpl(..) |
hir::ItemAutoImpl(..) |
hir::ItemTrait(..) |
hir::ItemImpl(..) |
hir::ItemTy(..) |
Expand Down Expand Up @@ -944,8 +944,8 @@ impl_stable_hash_for!(enum hir::Item_ {
ItemEnum(enum_def, generics),
ItemStruct(variant_data, generics),
ItemUnion(variant_data, generics),
ItemTrait(unsafety, generics, bounds, item_refs),
ItemDefaultImpl(unsafety, trait_ref),
ItemTrait(is_auto, unsafety, generics, bounds, item_refs),
ItemAutoImpl(unsafety, trait_ref),
ItemImpl(unsafety, impl_polarity, impl_defaultness, generics, trait_ref, ty, impl_item_refs)
});

Expand Down Expand Up @@ -1126,6 +1126,10 @@ impl_stable_hash_for!(enum hir::Mutability {
MutImmutable
});

impl_stable_hash_for!(enum hir::IsAuto {
Yes,
No
});

impl_stable_hash_for!(enum hir::Unsafety {
Unsafe,
Expand Down
10 changes: 5 additions & 5 deletions src/librustc/ich/impls_ty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -731,13 +731,13 @@ impl<'gcx> HashStable<StableHashingContext<'gcx>> for ty::TraitDef {
def_id: _,
unsafety,
paren_sugar,
has_default_impl,
has_auto_impl,
def_path_hash,
} = *self;

unsafety.hash_stable(hcx, hasher);
paren_sugar.hash_stable(hcx, hasher);
has_default_impl.hash_stable(hcx, hasher);
has_auto_impl.hash_stable(hcx, hasher);
def_path_hash.hash_stable(hcx, hasher);
}
}
Expand Down Expand Up @@ -856,7 +856,7 @@ for traits::Vtable<'gcx, N> where N: HashStable<StableHashingContext<'gcx>> {

match self {
&VtableImpl(ref table_impl) => table_impl.hash_stable(hcx, hasher),
&VtableDefaultImpl(ref table_def_impl) => table_def_impl.hash_stable(hcx, hasher),
&VtableAutoImpl(ref table_def_impl) => table_def_impl.hash_stable(hcx, hasher),
&VtableParam(ref table_param) => table_param.hash_stable(hcx, hasher),
&VtableObject(ref table_obj) => table_obj.hash_stable(hcx, hasher),
&VtableBuiltin(ref table_builtin) => table_builtin.hash_stable(hcx, hasher),
Expand Down Expand Up @@ -884,11 +884,11 @@ for traits::VtableImplData<'gcx, N> where N: HashStable<StableHashingContext<'gc
}

impl<'gcx, N> HashStable<StableHashingContext<'gcx>>
for traits::VtableDefaultImplData<N> where N: HashStable<StableHashingContext<'gcx>> {
for traits::VtableAutoImplData<N> where N: HashStable<StableHashingContext<'gcx>> {
fn hash_stable<W: StableHasherResult>(&self,
hcx: &mut StableHashingContext<'gcx>,
hasher: &mut StableHasher<W>) {
let traits::VtableDefaultImplData {
let traits::VtableAutoImplData {
trait_def_id,
ref nested,
} = *self;
Expand Down
2 changes: 1 addition & 1 deletion src/librustc/middle/dead.rs
Original file line number Diff line number Diff line change
Expand Up @@ -562,7 +562,7 @@ impl<'a, 'tcx> Visitor<'tcx> for DeadVisitor<'a, 'tcx> {
hir::ItemStruct(..) |
hir::ItemUnion(..) |
hir::ItemTrait(..) |
hir::ItemDefaultImpl(..) |
hir::ItemAutoImpl(..) |
hir::ItemImpl(..) => self.tcx.sess.codemap().def_span(item.span),
_ => item.span,
};
Expand Down
2 changes: 1 addition & 1 deletion src/librustc/middle/reachable.rs
Original file line number Diff line number Diff line change
Expand Up @@ -270,7 +270,7 @@ impl<'a, 'tcx> ReachableContext<'a, 'tcx> {
hir::ItemMod(..) | hir::ItemForeignMod(..) |
hir::ItemImpl(..) | hir::ItemTrait(..) |
hir::ItemStruct(..) | hir::ItemEnum(..) |
hir::ItemUnion(..) | hir::ItemDefaultImpl(..) |
hir::ItemUnion(..) | hir::ItemAutoImpl(..) |
hir::ItemGlobalAsm(..) => {}
}
}
Expand Down
Loading

0 comments on commit 2278506

Please sign in to comment.