Skip to content

Commit b48eb5e

Browse files
committed
support default impl for specialization
`[default] [unsafe] impl` and typecheck
1 parent 715811d commit b48eb5e

File tree

7 files changed

+44
-46
lines changed

7 files changed

+44
-46
lines changed

src/grammar/parser-lalr.y

+15-14
Original file line numberDiff line numberDiff line change
@@ -535,10 +535,11 @@ maybe_unsafe
535535
| %empty { $$ = mk_none(); }
536536
;
537537

538-
maybe_default_impl
539-
: IMPL { $$ = mk_none(); }
540-
| DEFAULT IMPL { $$ = $1 }
541-
;
538+
maybe_default_maybe_unsafe
539+
: DEFAULT UNSAFE { $$ = mk_atom("DefaultUnsafe"); }
540+
| DEFAULT { $$ = mk_atom("Default"); }
541+
| UNSAFE { $$ = mk_atom("Unsafe"); }
542+
| %empty { $$ = mk_none(); }
542543

543544
trait_method
544545
: type_method { $$ = mk_node("Required", 1, $1); }
@@ -594,27 +595,27 @@ impl_method
594595
// they are ambiguous with traits. We do the same here, regrettably,
595596
// by splitting ty into ty and ty_prim.
596597
item_impl
597-
: maybe_unsafe maybe_default_impl generic_params ty_prim_sum maybe_where_clause '{' maybe_inner_attrs maybe_impl_items '}'
598+
: maybe_default_maybe_unsafe IMPL generic_params ty_prim_sum maybe_where_clause '{' maybe_inner_attrs maybe_impl_items '}'
598599
{
599-
$$ = mk_node("ItemImpl", 6, $1, $3, $4, $5, $7, $8, $2);
600+
$$ = mk_node("ItemImpl", 6, $1, $3, $4, $5, $7, $8);
600601
}
601-
| maybe_unsafe maybe_default_impl generic_params '(' ty ')' maybe_where_clause '{' maybe_inner_attrs maybe_impl_items '}'
602+
| maybe_default_maybe_unsafe IMPL generic_params '(' ty ')' maybe_where_clause '{' maybe_inner_attrs maybe_impl_items '}'
602603
{
603-
$$ = mk_node("ItemImpl", 6, $1, $3, 5, $6, $9, $10, $2);
604+
$$ = mk_node("ItemImpl", 6, $1, $3, 5, $6, $9, $10);
604605
}
605-
| maybe_unsafe maybe_default_impl generic_params trait_ref FOR ty_sum maybe_where_clause '{' maybe_inner_attrs maybe_impl_items '}'
606+
| maybe_default_maybe_unsafe IMPL generic_params trait_ref FOR ty_sum maybe_where_clause '{' maybe_inner_attrs maybe_impl_items '}'
606607
{
607-
$$ = mk_node("ItemImpl", 6, $3, $4, $6, $7, $9, $10, $2);
608+
$$ = mk_node("ItemImpl", 6, $3, $4, $6, $7, $9, $10);
608609
}
609-
| maybe_unsafe maybe_default_impl generic_params '!' trait_ref FOR ty_sum maybe_where_clause '{' maybe_inner_attrs maybe_impl_items '}'
610+
| maybe_default_maybe_unsafe IMPL generic_params '!' trait_ref FOR ty_sum maybe_where_clause '{' maybe_inner_attrs maybe_impl_items '}'
610611
{
611-
$$ = mk_node("ItemImplNeg", 7, $1, $3, $5, $7, $8, $10, $11, $2);
612+
$$ = mk_node("ItemImplNeg", 7, $1, $3, $5, $7, $8, $10, $11);
612613
}
613-
| maybe_unsafe maybe_default_impl generic_params trait_ref FOR DOTDOT '{' '}'
614+
| maybe_default_maybe_unsafe IMPL generic_params trait_ref FOR DOTDOT '{' '}'
614615
{
615616
$$ = mk_node("ItemImplDefault", 3, $1, $3, $4);
616617
}
617-
| maybe_unsafe maybe_default_impl generic_params '!' trait_ref FOR DOTDOT '{' '}'
618+
| maybe_default_maybe_unsafe IMPL generic_params '!' trait_ref FOR DOTDOT '{' '}'
618619
{
619620
$$ = mk_node("ItemImplDefaultNeg", 3, $1, $3, $4);
620621
}

src/librustc/hir/lowering.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1363,7 +1363,7 @@ impl<'a> LoweringContext<'a> {
13631363
ItemKind::MacroDef(..) | ItemKind::Mac(..) => panic!("Shouldn't still be around"),
13641364
}
13651365

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

src/librustc/traits/util.rs

+5
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ use ty::{self, Ty, TyCtxt, ToPredicate, ToPolyTraitRef};
1414
use ty::outlives::Component;
1515
use util::nodemap::FxHashSet;
1616
use hir::{self};
17+
use traits::specialize::specialization_graph::NodeItem;
1718

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

@@ -525,6 +526,10 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
525526
}
526527
}
527528
}
529+
530+
pub fn impl_item_is_final(self, node_item: &NodeItem<hir::Defaultness>) -> bool {
531+
node_item.item.is_final() && !self.impl_is_default(node_item.node.def_id())
532+
}
528533
}
529534

530535
pub enum TupleArgumentsFlag { Yes, No }

src/librustc_typeck/check/mod.rs

+2-4
Original file line numberDiff line numberDiff line change
@@ -1141,10 +1141,8 @@ fn check_specialization_validity<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
11411141
.map(|node_item| node_item.map(|parent| parent.defaultness));
11421142

11431143
if let Some(parent) = parent {
1144-
if parent.item.is_final() {
1145-
if !tcx.impl_is_default(parent.node.def_id()) {
1146-
report_forbidden_specialization(tcx, impl_item, parent.node.def_id());
1147-
}
1144+
if tcx.impl_item_is_final(&parent) {
1145+
report_forbidden_specialization(tcx, impl_item, parent.node.def_id());
11481146
}
11491147
}
11501148

src/libsyntax/feature_gate.rs

+4-7
Original file line numberDiff line numberDiff line change
@@ -1226,13 +1226,10 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
12261226
_ => {}
12271227
}
12281228

1229-
match defaultness {
1230-
ast::Defaultness::Default => {
1231-
gate_feature_post!(&self, specialization,
1232-
i.span,
1233-
"specialization is unstable");
1234-
}
1235-
_ => {}
1229+
if let ast::Defaultness::Default = defaultness {
1230+
gate_feature_post!(&self, specialization,
1231+
i.span,
1232+
"specialization is unstable");
12361233
}
12371234
}
12381235

src/libsyntax/parse/parser.rs

+6-9
Original file line numberDiff line numberDiff line change
@@ -4918,12 +4918,9 @@ 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-
_ => {}
4921+
if let ast::Defaultness::Default = defaultness {
4922+
self.span_err(impl_span, "`default impl` is not allowed for \
4923+
default trait implementations");
49274924
}
49284925

49294926
self.expect(&token::OpenDelim(token::Brace))?;
@@ -5768,13 +5765,13 @@ impl<'a> Parser<'a> {
57685765
}
57695766
if (self.check_keyword(keywords::Unsafe) &&
57705767
self.look_ahead(1, |t| t.is_keyword(keywords::Impl))) ||
5771-
(self.check_keyword(keywords::Unsafe) &&
5772-
self.look_ahead(1, |t| t.is_keyword(keywords::Default)) &&
5768+
(self.check_keyword(keywords::Default) &&
5769+
self.look_ahead(1, |t| t.is_keyword(keywords::Unsafe)) &&
57735770
self.look_ahead(2, |t| t.is_keyword(keywords::Impl)))
57745771
{
57755772
// IMPL ITEM
5776-
self.expect_keyword(keywords::Unsafe)?;
57775773
let defaultness = self.parse_defaultness()?;
5774+
self.expect_keyword(keywords::Unsafe)?;
57785775
self.expect_keyword(keywords::Impl)?;
57795776
let (ident,
57805777
item_,

src/test/run-pass/specialization/defaultimpl/specialization-basics-unsafe.rs

+11-11
Original file line numberDiff line numberDiff line change
@@ -17,61 +17,61 @@ unsafe trait Foo {
1717
fn foo(&self) -> &'static str;
1818
}
1919

20-
unsafe default impl<T> Foo for T {
20+
default unsafe impl<T> Foo for T {
2121
fn foo(&self) -> &'static str {
2222
"generic"
2323
}
2424
}
2525

26-
unsafe default impl<T: Clone> Foo for T {
26+
default unsafe impl<T: Clone> Foo for T {
2727
fn foo(&self) -> &'static str {
2828
"generic Clone"
2929
}
3030
}
3131

32-
unsafe default impl<T, U> Foo for (T, U) where T: Clone, U: Clone {
32+
default unsafe impl<T, U> Foo for (T, U) where T: Clone, U: Clone {
3333
fn foo(&self) -> &'static str {
3434
"generic pair"
3535
}
3636
}
3737

38-
unsafe default impl<T: Clone> Foo for (T, T) {
38+
default unsafe impl<T: Clone> Foo for (T, T) {
3939
fn foo(&self) -> &'static str {
4040
"generic uniform pair"
4141
}
4242
}
4343

44-
unsafe default impl Foo for (u8, u32) {
44+
default unsafe impl Foo for (u8, u32) {
4545
fn foo(&self) -> &'static str {
4646
"(u8, u32)"
4747
}
4848
}
4949

50-
unsafe default impl Foo for (u8, u8) {
50+
default unsafe impl Foo for (u8, u8) {
5151
fn foo(&self) -> &'static str {
5252
"(u8, u8)"
5353
}
5454
}
5555

56-
unsafe default impl<T: Clone> Foo for Vec<T> {
56+
default unsafe impl<T: Clone> Foo for Vec<T> {
5757
fn foo(&self) -> &'static str {
5858
"generic Vec"
5959
}
6060
}
6161

62-
unsafe impl Foo for Vec<i32> {
62+
default unsafe impl Foo for Vec<i32> {
6363
fn foo(&self) -> &'static str {
6464
"Vec<i32>"
6565
}
6666
}
6767

68-
unsafe impl Foo for String {
68+
default unsafe impl Foo for String {
6969
fn foo(&self) -> &'static str {
7070
"String"
7171
}
7272
}
7373

74-
unsafe impl Foo for i32 {
74+
default unsafe impl Foo for i32 {
7575
fn foo(&self) -> &'static str {
7676
"i32"
7777
}
@@ -80,7 +80,7 @@ unsafe impl Foo for i32 {
8080
struct NotClone;
8181

8282
unsafe trait MyMarker {}
83-
unsafe default impl<T: Clone + MyMarker> Foo for T {
83+
default unsafe impl<T: Clone + MyMarker> Foo for T {
8484
fn foo(&self) -> &'static str {
8585
"generic Clone + MyMarker"
8686
}

0 commit comments

Comments
 (0)