Skip to content

Commit 116e983

Browse files
committed
support default impl for specialization
this commit implements the first step of the `default impl` feature: all items in a `default impl` are (implicitly) `default` and hence specializable. In order to test this feature I've copied all the tests provided for the `default` method implementation (in run-pass/specialization and compile-fail/specialization directories) and moved the `default` keyword from the item to the impl. See referenced issue for further info
1 parent 15ce540 commit 116e983

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

50 files changed

+1078
-41
lines changed

rls

Submodule rls updated from 6ecff95 to 016cbc5

src/doc/reference

src/librustc/hir/lowering.rs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1326,7 +1326,13 @@ impl<'a> LoweringContext<'a> {
13261326
hir::ItemDefaultImpl(self.lower_unsafety(unsafety),
13271327
trait_ref)
13281328
}
1329-
ItemKind::Impl(unsafety, polarity, ref generics, ref ifce, ref ty, ref impl_items) => {
1329+
ItemKind::Impl(unsafety,
1330+
polarity,
1331+
defaultness,
1332+
ref generics,
1333+
ref ifce,
1334+
ref ty,
1335+
ref impl_items) => {
13301336
let new_impl_items = impl_items.iter()
13311337
.map(|item| self.lower_impl_item_ref(item))
13321338
.collect();
@@ -1340,6 +1346,7 @@ impl<'a> LoweringContext<'a> {
13401346

13411347
hir::ItemImpl(self.lower_unsafety(unsafety),
13421348
self.lower_impl_polarity(polarity),
1349+
self.lower_defaultness(defaultness),
13431350
self.lower_generics(generics),
13441351
ifce,
13451352
self.lower_ty(ty),

src/librustc/hir/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1712,6 +1712,7 @@ pub enum Item_ {
17121712
/// An implementation, eg `impl<A> Trait for Foo { .. }`
17131713
ItemImpl(Unsafety,
17141714
ImplPolarity,
1715+
Defaultness,
17151716
Generics,
17161717
Option<TraitRef>, // (optional) trait this impl implements
17171718
P<Ty>, // self

src/librustc/hir/print.rs

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -678,12 +678,14 @@ impl<'a> State<'a> {
678678
}
679679
hir::ItemImpl(unsafety,
680680
polarity,
681+
defaultness,
681682
ref generics,
682683
ref opt_trait,
683684
ref ty,
684685
ref impl_items) => {
685686
self.head("")?;
686687
self.print_visibility(&item.vis)?;
688+
self.print_defaultness(defaultness)?;
687689
self.print_unsafety(unsafety)?;
688690
self.word_nbsp("impl")?;
689691

@@ -820,6 +822,13 @@ impl<'a> State<'a> {
820822
}
821823
}
822824

825+
pub fn print_defaultness(&mut self, defaultness: hir::Defaultness) -> io::Result<()> {
826+
if let hir::Defaultness::Default = defaultness {
827+
self.word_nbsp("default")?;
828+
}
829+
Ok(())
830+
}
831+
823832
pub fn print_struct(&mut self,
824833
struct_def: &hir::VariantData,
825834
generics: &hir::Generics,
@@ -931,11 +940,7 @@ impl<'a> State<'a> {
931940
self.hardbreak_if_not_bol()?;
932941
self.maybe_print_comment(ii.span.lo)?;
933942
self.print_outer_attributes(&ii.attrs)?;
934-
935-
match ii.defaultness {
936-
hir::Defaultness::Default { .. } => self.word_nbsp("default")?,
937-
hir::Defaultness::Final => (),
938-
}
943+
self.print_defaultness(ii.defaultness)?;
939944

940945
match ii.node {
941946
hir::ImplItemKind::Const(ref ty, expr) => {

src/librustc/middle/reachable.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ fn item_might_be_inlined(item: &hir::Item) -> bool {
5050
}
5151

5252
match item.node {
53-
hir::ItemImpl(_, _, ref generics, ..) |
53+
hir::ItemImpl(_, _, _, ref generics, ..) |
5454
hir::ItemFn(.., ref generics, _) => {
5555
generics_require_inlining(generics)
5656
}
@@ -186,7 +186,7 @@ impl<'a, 'tcx> ReachableContext<'a, 'tcx> {
186186
// does too.
187187
let impl_node_id = self.tcx.hir.as_local_node_id(impl_did).unwrap();
188188
match self.tcx.hir.expect_item(impl_node_id).node {
189-
hir::ItemImpl(_, _, ref generics, ..) => {
189+
hir::ItemImpl(_, _, _, ref generics, ..) => {
190190
generics_require_inlining(generics)
191191
}
192192
_ => false

src/librustc/middle/resolve_lifetime.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -331,7 +331,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
331331
hir::ItemStruct(_, ref generics) |
332332
hir::ItemUnion(_, ref generics) |
333333
hir::ItemTrait(_, ref generics, ..) |
334-
hir::ItemImpl(_, _, ref generics, ..) => {
334+
hir::ItemImpl(_, _, _, ref generics, ..) => {
335335
// These kinds of items have only early bound lifetime parameters.
336336
let mut index = if let hir::ItemTrait(..) = item.node {
337337
1 // Self comes before lifetimes
@@ -834,7 +834,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
834834
}
835835
match parent.node {
836836
hir::ItemTrait(_, ref generics, ..) |
837-
hir::ItemImpl(_, _, ref generics, ..) => {
837+
hir::ItemImpl(_, _, _, ref generics, ..) => {
838838
index += (generics.lifetimes.len() + generics.ty_params.len()) as u32;
839839
}
840840
_ => {}

src/librustc/traits/project.rs

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ 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};
3637

3738
/// Depending on the stage of compilation, we want projection to be
3839
/// more or less conservative.
@@ -923,7 +924,28 @@ fn assemble_candidates_from_impls<'cx, 'gcx, 'tcx>(
923924
// being invoked).
924925
node_item.item.defaultness.has_value()
925926
} else {
926-
node_item.item.defaultness.is_default()
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
927949
};
928950

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

src/librustc_metadata/cstore_impl.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,7 @@ 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) }
9394
coerce_unsized_info => {
9495
cdata.get_coerce_unsized_info(def_id.index).unwrap_or_else(|| {
9596
bug!("coerce_unsized_info: `{:?}` is missing its info", def_id);

src/librustc_metadata/decoder.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -629,6 +629,10 @@ impl<'a, 'tcx> CrateMetadata {
629629
self.get_impl_data(id).polarity
630630
}
631631

632+
pub fn get_impl_defaultness(&self, id: DefIndex) -> hir::Defaultness {
633+
self.get_impl_data(id).defaultness
634+
}
635+
632636
pub fn get_coerce_unsized_info(&self,
633637
id: DefIndex)
634638
-> Option<ty::adjustment::CoerceUnsizedInfo> {

src/librustc_metadata/encoder.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -706,14 +706,15 @@ impl<'a, 'b: 'a, 'tcx: 'b> EntryBuilder<'a, 'b, 'tcx> {
706706
hir::ItemDefaultImpl(..) => {
707707
let data = ImplData {
708708
polarity: hir::ImplPolarity::Positive,
709+
defaultness: hir::Defaultness::Final,
709710
parent_impl: None,
710711
coerce_unsized_info: None,
711712
trait_ref: tcx.impl_trait_ref(def_id).map(|trait_ref| self.lazy(&trait_ref)),
712713
};
713714

714715
EntryKind::DefaultImpl(self.lazy(&data))
715716
}
716-
hir::ItemImpl(_, polarity, ..) => {
717+
hir::ItemImpl(_, polarity, defaultness, ..) => {
717718
let trait_ref = tcx.impl_trait_ref(def_id);
718719
let parent = if let Some(trait_ref) = trait_ref {
719720
let trait_def = tcx.lookup_trait_def(trait_ref.def_id);
@@ -740,6 +741,7 @@ impl<'a, 'b: 'a, 'tcx: 'b> EntryBuilder<'a, 'b, 'tcx> {
740741

741742
let data = ImplData {
742743
polarity: polarity,
744+
defaultness: defaultness,
743745
parent_impl: parent,
744746
coerce_unsized_info: coerce_unsized_info,
745747
trait_ref: trait_ref.map(|trait_ref| self.lazy(&trait_ref)),

src/librustc_metadata/schema.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -406,6 +406,7 @@ impl_stable_hash_for!(struct TraitData<'tcx> {
406406
#[derive(RustcEncodable, RustcDecodable)]
407407
pub struct ImplData<'tcx> {
408408
pub polarity: hir::ImplPolarity,
409+
pub defaultness: hir::Defaultness,
409410
pub parent_impl: Option<DefId>,
410411

411412
/// This is `Some` only for impls of `CoerceUnsized`.

src/librustc_save_analysis/dump_visitor.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -429,8 +429,8 @@ 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.hir.get_if_local(id) {
433-
if let hir::ItemImpl(_, _, _, _, ref ty, _) = item.node {
432+
if let Some(NodeItem(item)) = self.tcx.map.get_if_local(id) {
433+
if let hir::ItemImpl(_, _, _, _, _, ref ty, _) = item.node {
434434
trait_id = self.lookup_def_id(ty.id);
435435
}
436436
}

src/librustc_trans/collector.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -880,7 +880,7 @@ impl<'b, 'a, 'v> ItemLikeVisitor<'v> for RootCollector<'b, 'a, 'v> {
880880
let parent_node_id = hir_map.get_parent_node(ii.id);
881881
let is_impl_generic = match hir_map.expect_item(parent_node_id) {
882882
&hir::Item {
883-
node: hir::ItemImpl(_, _, ref generics, ..),
883+
node: hir::ItemImpl(_, _, _, ref generics, ..),
884884
..
885885
} => {
886886
generics.is_type_parameterized()
@@ -911,6 +911,7 @@ fn create_trans_items_for_default_impls<'a, 'tcx>(scx: &SharedCrateContext<'a, '
911911
let tcx = scx.tcx();
912912
match item.node {
913913
hir::ItemImpl(_,
914+
_,
914915
_,
915916
ref generics,
916917
..,

src/librustc_typeck/check/mod.rs

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1142,7 +1142,23 @@ 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-
report_forbidden_specialization(tcx, impl_item, parent.node.def_id());
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 {
1160+
report_forbidden_specialization(tcx, impl_item, parent.node.def_id());
1161+
}
11461162
}
11471163
}
11481164

src/librustc_typeck/check/wfcheck.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -105,11 +105,11 @@ impl<'a, 'gcx> CheckTypeWellFormedVisitor<'a, 'gcx> {
105105
///
106106
/// won't be allowed unless there's an *explicit* implementation of `Send`
107107
/// for `T`
108-
hir::ItemImpl(_, hir::ImplPolarity::Positive, _,
108+
hir::ItemImpl(_, hir::ImplPolarity::Positive, _, _,
109109
ref trait_ref, ref self_ty, _) => {
110110
self.check_impl(item, self_ty, trait_ref);
111111
}
112-
hir::ItemImpl(_, hir::ImplPolarity::Negative, _, Some(_), ..) => {
112+
hir::ItemImpl(_, hir::ImplPolarity::Negative, _, _, Some(_), ..) => {
113113
// FIXME(#27579) what amount of WF checking do we need for neg impls?
114114

115115
let trait_ref = tcx.impl_trait_ref(tcx.hir.local_def_id(item.id)).unwrap();

src/librustc_typeck/coherence/unsafety.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ impl<'cx, 'tcx, 'v> ItemLikeVisitor<'v> for UnsafetyChecker<'cx, 'tcx> {
8787
hir::ItemDefaultImpl(unsafety, _) => {
8888
self.check_unsafety_coherence(item, None, unsafety, hir::ImplPolarity::Positive);
8989
}
90-
hir::ItemImpl(unsafety, polarity, ref generics, Some(_), _, _) => {
90+
hir::ItemImpl(unsafety, polarity, _, ref generics, ..) => {
9191
self.check_unsafety_coherence(item, Some(generics), unsafety, polarity);
9292
}
9393
_ => {}

src/librustdoc/doctree.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -214,6 +214,7 @@ pub struct Trait {
214214
pub struct Impl {
215215
pub unsafety: hir::Unsafety,
216216
pub polarity: hir::ImplPolarity,
217+
pub defaultness: hir::Defaultness,
217218
pub generics: hir::Generics,
218219
pub trait_: Option<hir::TraitRef>,
219220
pub for_: P<hir::Ty>,

src/librustdoc/visit_ast.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -502,7 +502,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
502502
om.traits.push(t);
503503
},
504504

505-
hir::ItemImpl(unsafety, polarity, ref gen, ref tr, ref ty, ref item_ids) => {
505+
hir::ItemImpl(unsafety, polarity, defaultness, ref gen, ref tr, ref ty, ref item_ids) => {
506506
// Don't duplicate impls when inlining, we'll pick them up
507507
// regardless of where they're located.
508508
if !self.inlining {
@@ -512,6 +512,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
512512
let i = Impl {
513513
unsafety: unsafety,
514514
polarity: polarity,
515+
defaultness: defaultness,
515516
generics: gen.clone(),
516517
trait_: tr.clone(),
517518
for_: ty.clone(),

src/libsyntax/ast.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1852,6 +1852,7 @@ pub enum ItemKind {
18521852
/// E.g. `impl<A> Foo<A> { .. }` or `impl<A> Trait for Foo<A> { .. }`
18531853
Impl(Unsafety,
18541854
ImplPolarity,
1855+
Defaultness,
18551856
Generics,
18561857
Option<TraitRef>, // (optional) trait this impl implements
18571858
P<Ty>, // self

src/libsyntax/feature_gate.rs

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1215,7 +1215,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
12151215
and possibly buggy");
12161216
}
12171217

1218-
ast::ItemKind::Impl(_, polarity, _, _, _, _) => {
1218+
ast::ItemKind::Impl(_, polarity, defaultness, _, _, _, _) => {
12191219
match polarity {
12201220
ast::ImplPolarity::Negative => {
12211221
gate_feature_post!(&self, optin_builtin_traits,
@@ -1225,6 +1225,15 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
12251225
},
12261226
_ => {}
12271227
}
1228+
1229+
match defaultness {
1230+
ast::Defaultness::Default => {
1231+
gate_feature_post!(&self, specialization,
1232+
i.span,
1233+
"specialization is unstable");
1234+
}
1235+
_ => {}
1236+
}
12281237
}
12291238

12301239
_ => {}

src/libsyntax/fold.rs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -897,9 +897,16 @@ pub fn noop_fold_item_kind<T: Folder>(i: ItemKind, folder: &mut T) -> ItemKind {
897897
ItemKind::DefaultImpl(unsafety, ref trait_ref) => {
898898
ItemKind::DefaultImpl(unsafety, folder.fold_trait_ref((*trait_ref).clone()))
899899
}
900-
ItemKind::Impl(unsafety, polarity, generics, ifce, ty, impl_items) => ItemKind::Impl(
900+
ItemKind::Impl(unsafety,
901+
polarity,
902+
defaultness,
903+
generics,
904+
ifce,
905+
ty,
906+
impl_items) => ItemKind::Impl(
901907
unsafety,
902908
polarity,
909+
defaultness,
903910
folder.fold_generics(generics),
904911
ifce.map(|trait_ref| folder.fold_trait_ref(trait_ref.clone())),
905912
folder.fold_ty(ty),

0 commit comments

Comments
 (0)