Skip to content

Commit

Permalink
support default impl for specialization
Browse files Browse the repository at this point in the history
    pr review
  • Loading branch information
giannicic committed Apr 25, 2017
1 parent b0fca5f commit 715811d
Show file tree
Hide file tree
Showing 22 changed files with 202 additions and 65 deletions.
2 changes: 1 addition & 1 deletion rls
Submodule rls updated from 016cbc to 6ecff9
2 changes: 1 addition & 1 deletion src/compiler-rt
2 changes: 1 addition & 1 deletion src/doc/reference
28 changes: 17 additions & 11 deletions src/grammar/parser-lalr.y
Expand Up @@ -89,6 +89,7 @@ extern char *yytext;
%token TRAIT
%token TYPE
%token UNSAFE
%token DEFAULT
%token USE
%token WHILE
%token CONTINUE
Expand Down Expand Up @@ -534,6 +535,11 @@ maybe_unsafe
| %empty { $$ = mk_none(); }
;

maybe_default_impl
: IMPL { $$ = mk_none(); }
| DEFAULT IMPL { $$ = $1 }
;

trait_method
: type_method { $$ = mk_node("Required", 1, $1); }
| method { $$ = mk_node("Provided", 1, $1); }
Expand Down Expand Up @@ -588,27 +594,27 @@ impl_method
// they are ambiguous with traits. We do the same here, regrettably,
// by splitting ty into ty and ty_prim.
item_impl
: maybe_unsafe IMPL generic_params ty_prim_sum maybe_where_clause '{' maybe_inner_attrs maybe_impl_items '}'
: maybe_unsafe maybe_default_impl generic_params ty_prim_sum maybe_where_clause '{' maybe_inner_attrs maybe_impl_items '}'
{
$$ = mk_node("ItemImpl", 6, $1, $3, $4, $5, $7, $8);
$$ = mk_node("ItemImpl", 6, $1, $3, $4, $5, $7, $8, $2);
}
| maybe_unsafe IMPL generic_params '(' ty ')' maybe_where_clause '{' maybe_inner_attrs maybe_impl_items '}'
| maybe_unsafe maybe_default_impl generic_params '(' ty ')' maybe_where_clause '{' maybe_inner_attrs maybe_impl_items '}'
{
$$ = mk_node("ItemImpl", 6, $1, $3, 5, $6, $9, $10);
$$ = mk_node("ItemImpl", 6, $1, $3, 5, $6, $9, $10, $2);
}
| maybe_unsafe IMPL generic_params trait_ref FOR ty_sum maybe_where_clause '{' maybe_inner_attrs maybe_impl_items '}'
| maybe_unsafe maybe_default_impl generic_params trait_ref FOR ty_sum maybe_where_clause '{' maybe_inner_attrs maybe_impl_items '}'
{
$$ = mk_node("ItemImpl", 6, $3, $4, $6, $7, $9, $10);
$$ = mk_node("ItemImpl", 6, $3, $4, $6, $7, $9, $10, $2);
}
| maybe_unsafe IMPL generic_params '!' trait_ref FOR ty_sum maybe_where_clause '{' maybe_inner_attrs maybe_impl_items '}'
| maybe_unsafe maybe_default_impl generic_params '!' trait_ref FOR ty_sum maybe_where_clause '{' maybe_inner_attrs maybe_impl_items '}'
{
$$ = mk_node("ItemImplNeg", 7, $1, $3, $5, $7, $8, $10, $11);
$$ = mk_node("ItemImplNeg", 7, $1, $3, $5, $7, $8, $10, $11, $2);
}
| maybe_unsafe IMPL generic_params trait_ref FOR DOTDOT '{' '}'
| maybe_unsafe maybe_default_impl generic_params trait_ref FOR DOTDOT '{' '}'
{
$$ = mk_node("ItemImplDefault", 3, $1, $3, $4);
}
| maybe_unsafe IMPL generic_params '!' trait_ref FOR DOTDOT '{' '}'
| maybe_unsafe maybe_default_impl generic_params '!' trait_ref FOR DOTDOT '{' '}'
{
$$ = mk_node("ItemImplDefaultNeg", 3, $1, $3, $4);
}
Expand Down Expand Up @@ -1935,4 +1941,4 @@ brackets_delimited_token_trees
$2,
mk_node("TTTok", 1, mk_atom("]")));
}
;
;
3 changes: 3 additions & 0 deletions src/librustc/hir/lowering.rs
Expand Up @@ -1362,6 +1362,9 @@ impl<'a> LoweringContext<'a> {
}
ItemKind::MacroDef(..) | ItemKind::Mac(..) => panic!("Shouldn't still be around"),
}

// [1] `defaultness.has_value()` is necer called for an `impl`, always `true` in order to
// not cause an assertion failure inside the `lower_defaultness` function
}

fn lower_trait_item(&mut self, i: &TraitItem) -> hir::TraitItem {
Expand Down
2 changes: 1 addition & 1 deletion src/librustc/ich/impls_hir.rs
Expand Up @@ -933,7 +933,7 @@ impl_stable_hash_for!(enum hir::Item_ {
ItemUnion(variant_data, generics),
ItemTrait(unsafety, generics, bounds, item_refs),
ItemDefaultImpl(unsafety, trait_ref),
ItemImpl(unsafety, impl_polarity, generics, trait_ref, ty, impl_item_refs)
ItemImpl(unsafety, impl_polarity, impl_defaultness, generics, trait_ref, ty, impl_item_refs)
});

impl_stable_hash_for!(struct hir::TraitItemRef {
Expand Down
2 changes: 2 additions & 0 deletions src/librustc/middle/cstore.rs
Expand Up @@ -195,6 +195,7 @@ pub trait CrateStore {
fn implementations_of_trait(&self, filter: Option<DefId>) -> Vec<DefId>;

// impl info
fn impl_defaultness(&self, def: DefId) -> hir::Defaultness;
fn impl_parent(&self, impl_def_id: DefId) -> Option<DefId>;

// trait/impl-item info
Expand Down Expand Up @@ -329,6 +330,7 @@ impl CrateStore for DummyCrateStore {
fn implementations_of_trait(&self, filter: Option<DefId>) -> Vec<DefId> { vec![] }

// impl info
fn impl_defaultness(&self, def: DefId) -> hir::Defaultness { bug!("impl_defaultness") }
fn impl_parent(&self, def: DefId) -> Option<DefId> { bug!("impl_parent") }

// trait/impl-item info
Expand Down
25 changes: 2 additions & 23 deletions src/librustc/traits/project.rs
Expand Up @@ -33,7 +33,6 @@ use ty::subst::Subst;
use ty::{self, ToPredicate, ToPolyTraitRef, Ty, TyCtxt};
use ty::fold::{TypeFoldable, TypeFolder};
use util::common::FN_OUTPUT_NAME;
use hir::{self};

/// Depending on the stage of compilation, we want projection to be
/// more or less conservative.
Expand Down Expand Up @@ -924,28 +923,8 @@ fn assemble_candidates_from_impls<'cx, 'gcx, 'tcx>(
// being invoked).
node_item.item.defaultness.has_value()
} else {
let is_default = match selcx.tcx()
.map
.as_local_node_id(node_item.node.def_id()) {
Some(node_id) => {
let item = selcx.tcx().map.expect_item(node_id);
if let hir::ItemImpl(_, _, defaultness, ..) = item.node {
defaultness.is_default()
} else {
false
}
}
None => {
selcx.tcx()
.global_tcx()
.sess
.cstore
.impl_defaultness(node_item.node.def_id())
.is_default()
}
};

node_item.item.defaultness.is_default() || is_default
node_item.item.defaultness.is_default() ||
selcx.tcx().impl_is_default(node_item.node.def_id())
};

// Only reveal a specializable default if we're past type-checking
Expand Down
21 changes: 21 additions & 0 deletions src/librustc/traits/util.rs
Expand Up @@ -13,6 +13,7 @@ use ty::subst::{Subst, Substs};
use ty::{self, Ty, TyCtxt, ToPredicate, ToPolyTraitRef};
use ty::outlives::Component;
use util::nodemap::FxHashSet;
use hir::{self};

use super::{Obligation, ObligationCause, PredicateObligation, SelectionContext, Normalized};

Expand Down Expand Up @@ -504,6 +505,26 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
};
ty::Binder((trait_ref, sig.skip_binder().output()))
}

pub fn impl_is_default(self, node_item_def_id: DefId) -> bool {
match self.hir.as_local_node_id(node_item_def_id) {
Some(node_id) => {
let item = self.hir.expect_item(node_id);
if let hir::ItemImpl(_, _, defaultness, ..) = item.node {
defaultness.is_default()
} else {
false
}
}
None => {
self.global_tcx()
.sess
.cstore
.impl_defaultness(node_item_def_id)
.is_default()
}
}
}
}

pub enum TupleArgumentsFlag { Yes, No }
7 changes: 6 additions & 1 deletion src/librustc_metadata/cstore_impl.rs
Expand Up @@ -90,7 +90,6 @@ provide! { <'tcx> tcx, def_id, cdata
associated_item => { cdata.get_associated_item(def_id.index) }
impl_trait_ref => { cdata.get_impl_trait(def_id.index, tcx) }
impl_polarity => { cdata.get_impl_polarity(def_id.index) }
impl_defaultness => { cdata.get_impl_defaultness(def_id.index) }
coerce_unsized_info => {
cdata.get_coerce_unsized_info(def_id.index).unwrap_or_else(|| {
bug!("coerce_unsized_info: `{:?}` is missing its info", def_id);
Expand Down Expand Up @@ -179,6 +178,12 @@ impl CrateStore for cstore::CStore {
result
}

fn impl_defaultness(&self, def: DefId) -> hir::Defaultness
{
self.dep_graph.read(DepNode::MetaData(def));
self.get_crate_data(def.krate).get_impl_defaultness(def.index)
}

fn impl_parent(&self, impl_def: DefId) -> Option<DefId> {
self.dep_graph.read(DepNode::MetaData(impl_def));
self.get_crate_data(impl_def.krate).get_parent_impl(impl_def.index)
Expand Down
1 change: 1 addition & 0 deletions src/librustc_metadata/schema.rs
Expand Up @@ -416,6 +416,7 @@ pub struct ImplData<'tcx> {

impl_stable_hash_for!(struct ImplData<'tcx> {
polarity,
defaultness,
parent_impl,
coerce_unsized_info,
trait_ref
Expand Down
2 changes: 1 addition & 1 deletion src/librustc_save_analysis/dump_visitor.rs
Expand Up @@ -429,7 +429,7 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> {
}
}
None => {
if let Some(NodeItem(item)) = self.tcx.map.get_if_local(id) {
if let Some(NodeItem(item)) = self.tcx.hir.get_if_local(id) {
if let hir::ItemImpl(_, _, _, _, _, ref ty, _) = item.node {
trait_id = self.lookup_def_id(ty.id);
}
Expand Down
16 changes: 1 addition & 15 deletions src/librustc_typeck/check/mod.rs
Expand Up @@ -1142,21 +1142,7 @@ fn check_specialization_validity<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,

if let Some(parent) = parent {
if parent.item.is_final() {
let is_final = match tcx.map.as_local_node_id(parent.node.def_id()) {
Some(node_id) => {
let item = tcx.map.expect_item(node_id);
if let hir::ItemImpl(_, _, defaultness, ..) = item.node {
defaultness.is_final()
} else {
true
}
}
None => {
tcx.global_tcx().sess.cstore.impl_defaultness(parent.node.def_id()).is_final()
}
};

if is_final {
if !tcx.impl_is_default(parent.node.def_id()) {
report_forbidden_specialization(tcx, impl_item, parent.node.def_id());
}
}
Expand Down
6 changes: 3 additions & 3 deletions src/librustc_typeck/collect.rs
Expand Up @@ -309,7 +309,7 @@ fn type_param_predicates<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
NodeItem(item) => {
match item.node {
ItemFn(.., ref generics, _) |
ItemImpl(_, _, ref generics, ..) |
ItemImpl(_, _, _, ref generics, ..) |
ItemTy(_, ref generics) |
ItemEnum(_, ref generics) |
ItemStruct(_, ref generics) |
Expand Down Expand Up @@ -825,7 +825,7 @@ fn generics<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
NodeItem(item) => {
match item.node {
ItemFn(.., ref generics, _) |
ItemImpl(_, _, ref generics, ..) => generics,
ItemImpl(_, _, _, ref generics, ..) => generics,

ItemTy(_, ref generics) |
ItemEnum(_, ref generics) |
Expand Down Expand Up @@ -1236,7 +1236,7 @@ fn predicates<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
NodeItem(item) => {
match item.node {
ItemFn(.., ref generics, _) |
ItemImpl(_, _, ref generics, ..) |
ItemImpl(_, _, _, ref generics, ..) |
ItemTy(_, ref generics) |
ItemEnum(_, ref generics) |
ItemStruct(_, ref generics) |
Expand Down
14 changes: 11 additions & 3 deletions src/libsyntax/parse/parser.rs
Expand Up @@ -4918,6 +4918,14 @@ impl<'a> Parser<'a> {
allowed to have generics");
}

match defaultness {
ast::Defaultness::Default => {
self.span_err(impl_span, "`default impl` is not allowed for \
default trait implementations");
}
_ => {}
}

self.expect(&token::OpenDelim(token::Brace))?;
self.expect(&token::CloseDelim(token::Brace))?;
Ok((keywords::Invalid.ident(),
Expand Down Expand Up @@ -5760,13 +5768,13 @@ impl<'a> Parser<'a> {
}
if (self.check_keyword(keywords::Unsafe) &&
self.look_ahead(1, |t| t.is_keyword(keywords::Impl))) ||
(self.check_keyword(keywords::Default) &&
self.look_ahead(1, |t| t.is_keyword(keywords::Unsafe)) &&
(self.check_keyword(keywords::Unsafe) &&
self.look_ahead(1, |t| t.is_keyword(keywords::Default)) &&
self.look_ahead(2, |t| t.is_keyword(keywords::Impl)))
{
// IMPL ITEM
let defaultness = self.parse_defaultness()?;
self.expect_keyword(keywords::Unsafe)?;
let defaultness = self.parse_defaultness()?;
self.expect_keyword(keywords::Impl)?;
let (ident,
item_,
Expand Down
1 change: 1 addition & 0 deletions src/rt/hoedown
Submodule hoedown added at da282f
@@ -0,0 +1,19 @@
// Copyright 2015 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 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#![feature(specialization)]
#![feature(optin_builtin_traits)]

trait Foo {}

default impl Foo for .. {}
//~^ ERROR `default impl` is not allowed for default trait implementations

fn main() {}

0 comments on commit 715811d

Please sign in to comment.