Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Syntax] Implement auto trait syntax #45247

Merged
merged 15 commits into from
Nov 4, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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) => {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd prefer to see all evidence of impl Trait for .. go away by the time HIR lowering is done. That is, I think the HIR should not include impl Trait for ..-style impls, and instead we should lower any trait that contains such an impl to have hir::IsAuto set to true.

This will presumably require one of two things:

  • A pre-pass that identifies the set of traits targeted by auto-impls, so that later, when we lower traits, we can set hir::IsAuto to true.
  • Or, alternatively, we could collect the set as we walk, and update the lowered form of traits after the fact. I suspect we still have unique access and can mutate them in place?

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