Skip to content

Commit 715811d

Browse files
committed
support default impl for specialization
pr review
1 parent b0fca5f commit 715811d

File tree

22 files changed

+202
-65
lines changed

22 files changed

+202
-65
lines changed

rls

Submodule rls updated from 016cbc5 to 6ecff95

src/doc/reference

src/grammar/parser-lalr.y

+17-11
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,7 @@ extern char *yytext;
8989
%token TRAIT
9090
%token TYPE
9191
%token UNSAFE
92+
%token DEFAULT
9293
%token USE
9394
%token WHILE
9495
%token CONTINUE
@@ -534,6 +535,11 @@ maybe_unsafe
534535
| %empty { $$ = mk_none(); }
535536
;
536537

538+
maybe_default_impl
539+
: IMPL { $$ = mk_none(); }
540+
| DEFAULT IMPL { $$ = $1 }
541+
;
542+
537543
trait_method
538544
: type_method { $$ = mk_node("Required", 1, $1); }
539545
| method { $$ = mk_node("Provided", 1, $1); }
@@ -588,27 +594,27 @@ impl_method
588594
// they are ambiguous with traits. We do the same here, regrettably,
589595
// by splitting ty into ty and ty_prim.
590596
item_impl
591-
: maybe_unsafe IMPL generic_params ty_prim_sum maybe_where_clause '{' maybe_inner_attrs maybe_impl_items '}'
597+
: maybe_unsafe maybe_default_impl generic_params ty_prim_sum maybe_where_clause '{' maybe_inner_attrs maybe_impl_items '}'
592598
{
593-
$$ = mk_node("ItemImpl", 6, $1, $3, $4, $5, $7, $8);
599+
$$ = mk_node("ItemImpl", 6, $1, $3, $4, $5, $7, $8, $2);
594600
}
595-
| maybe_unsafe IMPL generic_params '(' ty ')' maybe_where_clause '{' maybe_inner_attrs maybe_impl_items '}'
601+
| maybe_unsafe maybe_default_impl generic_params '(' ty ')' maybe_where_clause '{' maybe_inner_attrs maybe_impl_items '}'
596602
{
597-
$$ = mk_node("ItemImpl", 6, $1, $3, 5, $6, $9, $10);
603+
$$ = mk_node("ItemImpl", 6, $1, $3, 5, $6, $9, $10, $2);
598604
}
599-
| maybe_unsafe IMPL generic_params trait_ref FOR ty_sum maybe_where_clause '{' maybe_inner_attrs maybe_impl_items '}'
605+
| maybe_unsafe maybe_default_impl generic_params trait_ref FOR ty_sum maybe_where_clause '{' maybe_inner_attrs maybe_impl_items '}'
600606
{
601-
$$ = mk_node("ItemImpl", 6, $3, $4, $6, $7, $9, $10);
607+
$$ = mk_node("ItemImpl", 6, $3, $4, $6, $7, $9, $10, $2);
602608
}
603-
| maybe_unsafe IMPL generic_params '!' trait_ref FOR ty_sum maybe_where_clause '{' maybe_inner_attrs maybe_impl_items '}'
609+
| maybe_unsafe maybe_default_impl generic_params '!' trait_ref FOR ty_sum maybe_where_clause '{' maybe_inner_attrs maybe_impl_items '}'
604610
{
605-
$$ = mk_node("ItemImplNeg", 7, $1, $3, $5, $7, $8, $10, $11);
611+
$$ = mk_node("ItemImplNeg", 7, $1, $3, $5, $7, $8, $10, $11, $2);
606612
}
607-
| maybe_unsafe IMPL generic_params trait_ref FOR DOTDOT '{' '}'
613+
| maybe_unsafe maybe_default_impl generic_params trait_ref FOR DOTDOT '{' '}'
608614
{
609615
$$ = mk_node("ItemImplDefault", 3, $1, $3, $4);
610616
}
611-
| maybe_unsafe IMPL generic_params '!' trait_ref FOR DOTDOT '{' '}'
617+
| maybe_unsafe maybe_default_impl generic_params '!' trait_ref FOR DOTDOT '{' '}'
612618
{
613619
$$ = mk_node("ItemImplDefaultNeg", 3, $1, $3, $4);
614620
}
@@ -1935,4 +1941,4 @@ brackets_delimited_token_trees
19351941
$2,
19361942
mk_node("TTTok", 1, mk_atom("]")));
19371943
}
1938-
;
1944+
;

src/librustc/hir/lowering.rs

+3
Original file line numberDiff line numberDiff line change
@@ -1362,6 +1362,9 @@ impl<'a> LoweringContext<'a> {
13621362
}
13631363
ItemKind::MacroDef(..) | ItemKind::Mac(..) => panic!("Shouldn't still be around"),
13641364
}
1365+
1366+
// [1] `defaultness.has_value()` is necer called for an `impl`, always `true` in order to
1367+
// not cause an assertion failure inside the `lower_defaultness` function
13651368
}
13661369

13671370
fn lower_trait_item(&mut self, i: &TraitItem) -> hir::TraitItem {

src/librustc/ich/impls_hir.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -933,7 +933,7 @@ impl_stable_hash_for!(enum hir::Item_ {
933933
ItemUnion(variant_data, generics),
934934
ItemTrait(unsafety, generics, bounds, item_refs),
935935
ItemDefaultImpl(unsafety, trait_ref),
936-
ItemImpl(unsafety, impl_polarity, generics, trait_ref, ty, impl_item_refs)
936+
ItemImpl(unsafety, impl_polarity, impl_defaultness, generics, trait_ref, ty, impl_item_refs)
937937
});
938938

939939
impl_stable_hash_for!(struct hir::TraitItemRef {

src/librustc/middle/cstore.rs

+2
Original file line numberDiff line numberDiff line change
@@ -195,6 +195,7 @@ pub trait CrateStore {
195195
fn implementations_of_trait(&self, filter: Option<DefId>) -> Vec<DefId>;
196196

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

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

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

334336
// trait/impl-item info

src/librustc/traits/project.rs

+2-23
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,6 @@ use ty::subst::Subst;
3333
use ty::{self, ToPredicate, ToPolyTraitRef, Ty, TyCtxt};
3434
use ty::fold::{TypeFoldable, TypeFolder};
3535
use util::common::FN_OUTPUT_NAME;
36-
use hir::{self};
3736

3837
/// Depending on the stage of compilation, we want projection to be
3938
/// more or less conservative.
@@ -924,28 +923,8 @@ fn assemble_candidates_from_impls<'cx, 'gcx, 'tcx>(
924923
// being invoked).
925924
node_item.item.defaultness.has_value()
926925
} else {
927-
let is_default = match selcx.tcx()
928-
.map
929-
.as_local_node_id(node_item.node.def_id()) {
930-
Some(node_id) => {
931-
let item = selcx.tcx().map.expect_item(node_id);
932-
if let hir::ItemImpl(_, _, defaultness, ..) = item.node {
933-
defaultness.is_default()
934-
} else {
935-
false
936-
}
937-
}
938-
None => {
939-
selcx.tcx()
940-
.global_tcx()
941-
.sess
942-
.cstore
943-
.impl_defaultness(node_item.node.def_id())
944-
.is_default()
945-
}
946-
};
947-
948-
node_item.item.defaultness.is_default() || is_default
926+
node_item.item.defaultness.is_default() ||
927+
selcx.tcx().impl_is_default(node_item.node.def_id())
949928
};
950929

951930
// Only reveal a specializable default if we're past type-checking

src/librustc/traits/util.rs

+21
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ use ty::subst::{Subst, Substs};
1313
use ty::{self, Ty, TyCtxt, ToPredicate, ToPolyTraitRef};
1414
use ty::outlives::Component;
1515
use util::nodemap::FxHashSet;
16+
use hir::{self};
1617

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

@@ -504,6 +505,26 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
504505
};
505506
ty::Binder((trait_ref, sig.skip_binder().output()))
506507
}
508+
509+
pub fn impl_is_default(self, node_item_def_id: DefId) -> bool {
510+
match self.hir.as_local_node_id(node_item_def_id) {
511+
Some(node_id) => {
512+
let item = self.hir.expect_item(node_id);
513+
if let hir::ItemImpl(_, _, defaultness, ..) = item.node {
514+
defaultness.is_default()
515+
} else {
516+
false
517+
}
518+
}
519+
None => {
520+
self.global_tcx()
521+
.sess
522+
.cstore
523+
.impl_defaultness(node_item_def_id)
524+
.is_default()
525+
}
526+
}
527+
}
507528
}
508529

509530
pub enum TupleArgumentsFlag { Yes, No }

src/librustc_metadata/cstore_impl.rs

+6-1
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,6 @@ provide! { <'tcx> tcx, def_id, cdata
9090
associated_item => { cdata.get_associated_item(def_id.index) }
9191
impl_trait_ref => { cdata.get_impl_trait(def_id.index, tcx) }
9292
impl_polarity => { cdata.get_impl_polarity(def_id.index) }
93-
impl_defaultness => { cdata.get_impl_defaultness(def_id.index) }
9493
coerce_unsized_info => {
9594
cdata.get_coerce_unsized_info(def_id.index).unwrap_or_else(|| {
9695
bug!("coerce_unsized_info: `{:?}` is missing its info", def_id);
@@ -179,6 +178,12 @@ impl CrateStore for cstore::CStore {
179178
result
180179
}
181180

181+
fn impl_defaultness(&self, def: DefId) -> hir::Defaultness
182+
{
183+
self.dep_graph.read(DepNode::MetaData(def));
184+
self.get_crate_data(def.krate).get_impl_defaultness(def.index)
185+
}
186+
182187
fn impl_parent(&self, impl_def: DefId) -> Option<DefId> {
183188
self.dep_graph.read(DepNode::MetaData(impl_def));
184189
self.get_crate_data(impl_def.krate).get_parent_impl(impl_def.index)

src/librustc_metadata/schema.rs

+1
Original file line numberDiff line numberDiff line change
@@ -416,6 +416,7 @@ pub struct ImplData<'tcx> {
416416

417417
impl_stable_hash_for!(struct ImplData<'tcx> {
418418
polarity,
419+
defaultness,
419420
parent_impl,
420421
coerce_unsized_info,
421422
trait_ref

src/librustc_save_analysis/dump_visitor.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -429,7 +429,7 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> {
429429
}
430430
}
431431
None => {
432-
if let Some(NodeItem(item)) = self.tcx.map.get_if_local(id) {
432+
if let Some(NodeItem(item)) = self.tcx.hir.get_if_local(id) {
433433
if let hir::ItemImpl(_, _, _, _, _, ref ty, _) = item.node {
434434
trait_id = self.lookup_def_id(ty.id);
435435
}

src/librustc_typeck/check/mod.rs

+1-15
Original file line numberDiff line numberDiff line change
@@ -1142,21 +1142,7 @@ fn check_specialization_validity<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
11421142

11431143
if let Some(parent) = parent {
11441144
if parent.item.is_final() {
1145-
let is_final = match tcx.map.as_local_node_id(parent.node.def_id()) {
1146-
Some(node_id) => {
1147-
let item = tcx.map.expect_item(node_id);
1148-
if let hir::ItemImpl(_, _, defaultness, ..) = item.node {
1149-
defaultness.is_final()
1150-
} else {
1151-
true
1152-
}
1153-
}
1154-
None => {
1155-
tcx.global_tcx().sess.cstore.impl_defaultness(parent.node.def_id()).is_final()
1156-
}
1157-
};
1158-
1159-
if is_final {
1145+
if !tcx.impl_is_default(parent.node.def_id()) {
11601146
report_forbidden_specialization(tcx, impl_item, parent.node.def_id());
11611147
}
11621148
}

src/librustc_typeck/collect.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -309,7 +309,7 @@ fn type_param_predicates<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
309309
NodeItem(item) => {
310310
match item.node {
311311
ItemFn(.., ref generics, _) |
312-
ItemImpl(_, _, ref generics, ..) |
312+
ItemImpl(_, _, _, ref generics, ..) |
313313
ItemTy(_, ref generics) |
314314
ItemEnum(_, ref generics) |
315315
ItemStruct(_, ref generics) |
@@ -825,7 +825,7 @@ fn generics<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
825825
NodeItem(item) => {
826826
match item.node {
827827
ItemFn(.., ref generics, _) |
828-
ItemImpl(_, _, ref generics, ..) => generics,
828+
ItemImpl(_, _, _, ref generics, ..) => generics,
829829

830830
ItemTy(_, ref generics) |
831831
ItemEnum(_, ref generics) |
@@ -1236,7 +1236,7 @@ fn predicates<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
12361236
NodeItem(item) => {
12371237
match item.node {
12381238
ItemFn(.., ref generics, _) |
1239-
ItemImpl(_, _, ref generics, ..) |
1239+
ItemImpl(_, _, _, ref generics, ..) |
12401240
ItemTy(_, ref generics) |
12411241
ItemEnum(_, ref generics) |
12421242
ItemStruct(_, ref generics) |

src/libsyntax/parse/parser.rs

+11-3
Original file line numberDiff line numberDiff line change
@@ -4918,6 +4918,14 @@ impl<'a> Parser<'a> {
49184918
allowed to have generics");
49194919
}
49204920

4921+
match defaultness {
4922+
ast::Defaultness::Default => {
4923+
self.span_err(impl_span, "`default impl` is not allowed for \
4924+
default trait implementations");
4925+
}
4926+
_ => {}
4927+
}
4928+
49214929
self.expect(&token::OpenDelim(token::Brace))?;
49224930
self.expect(&token::CloseDelim(token::Brace))?;
49234931
Ok((keywords::Invalid.ident(),
@@ -5760,13 +5768,13 @@ impl<'a> Parser<'a> {
57605768
}
57615769
if (self.check_keyword(keywords::Unsafe) &&
57625770
self.look_ahead(1, |t| t.is_keyword(keywords::Impl))) ||
5763-
(self.check_keyword(keywords::Default) &&
5764-
self.look_ahead(1, |t| t.is_keyword(keywords::Unsafe)) &&
5771+
(self.check_keyword(keywords::Unsafe) &&
5772+
self.look_ahead(1, |t| t.is_keyword(keywords::Default)) &&
57655773
self.look_ahead(2, |t| t.is_keyword(keywords::Impl)))
57665774
{
57675775
// IMPL ITEM
5768-
let defaultness = self.parse_defaultness()?;
57695776
self.expect_keyword(keywords::Unsafe)?;
5777+
let defaultness = self.parse_defaultness()?;
57705778
self.expect_keyword(keywords::Impl)?;
57715779
let (ident,
57725780
item_,

src/rt/hoedown

Submodule hoedown added at da282f1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
#![feature(specialization)]
12+
#![feature(optin_builtin_traits)]
13+
14+
trait Foo {}
15+
16+
default impl Foo for .. {}
17+
//~^ ERROR `default impl` is not allowed for default trait implementations
18+
19+
fn main() {}

0 commit comments

Comments
 (0)