Skip to content

Commit 316c35e

Browse files
committed
Auto merge of #55101 - alexreg:trait-aliases, r=nikomatsakis
Implement trait aliases (RFC 1733) Extends groundwork done in #45047, and fully implements rust-lang/rfcs#1733. CC @durka @nikomatsakis
2 parents 8b09631 + 388f9be commit 316c35e

Some content is hidden

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

42 files changed

+633
-332
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
# `trait_alias`
2+
3+
The tracking issue for this feature is: [#41517]
4+
5+
[#41417]: https://github.com/rust-lang/rust/issues/41517
6+
7+
------------------------
8+
9+
The `trait_alias` feature adds support for trait aliases. These allow aliases
10+
to be created for one or more traits (currently just a single regular trait plus
11+
any number of auto-traits), and used wherever traits would normally be used as
12+
either bounds or trait objects.
13+
14+
```rust
15+
#![feature(trait_alias)]
16+
17+
trait Foo = std::fmt::Debug + Send;
18+
trait Bar = Foo + Sync;
19+
20+
// Use trait alias as bound on type parameter.
21+
fn foo<T: Foo>(v: &T) {
22+
println!("{:?}", v);
23+
}
24+
25+
pub fn main() {
26+
foo(&1);
27+
28+
// Use trait alias for trait objects.
29+
let a: &Bar = &123;
30+
println!("{:?}", a);
31+
let b = Box::new(456) as Box<dyn Foo>;
32+
println!("{:?}", b);
33+
}
34+
```

src/librustc/hir/lowering.rs

+17-16
Original file line numberDiff line numberDiff line change
@@ -4875,23 +4875,24 @@ impl<'a> LoweringContext<'a> {
48754875
let node = match qpath {
48764876
hir::QPath::Resolved(None, path) => {
48774877
// Turn trait object paths into `TyKind::TraitObject` instead.
4878-
if let Def::Trait(_) = path.def {
4879-
let principal = hir::PolyTraitRef {
4880-
bound_generic_params: hir::HirVec::new(),
4881-
trait_ref: hir::TraitRef {
4882-
path: path.and_then(|path| path),
4883-
ref_id: id.node_id,
4884-
hir_ref_id: id.hir_id,
4885-
},
4886-
span,
4887-
};
4878+
match path.def {
4879+
Def::Trait(_) | Def::TraitAlias(_) => {
4880+
let principal = hir::PolyTraitRef {
4881+
bound_generic_params: hir::HirVec::new(),
4882+
trait_ref: hir::TraitRef {
4883+
path: path.and_then(|path| path),
4884+
ref_id: id.node_id,
4885+
hir_ref_id: id.hir_id,
4886+
},
4887+
span,
4888+
};
48884889

4889-
// The original ID is taken by the `PolyTraitRef`,
4890-
// so the `Ty` itself needs a different one.
4891-
id = self.next_id();
4892-
hir::TyKind::TraitObject(hir_vec![principal], self.elided_dyn_bound(span))
4893-
} else {
4894-
hir::TyKind::Path(hir::QPath::Resolved(None, path))
4890+
// The original ID is taken by the `PolyTraitRef`,
4891+
// so the `Ty` itself needs a different one.
4892+
id = self.next_id();
4893+
hir::TyKind::TraitObject(hir_vec![principal], self.elided_dyn_bound(span))
4894+
}
4895+
_ => hir::TyKind::Path(hir::QPath::Resolved(None, path)),
48954896
}
48964897
}
48974898
_ => hir::TyKind::Path(qpath),

src/librustc/hir/map/mod.rs

+1-3
Original file line numberDiff line numberDiff line change
@@ -301,9 +301,7 @@ impl<'hir> Map<'hir> {
301301
ItemKind::Struct(..) => Some(Def::Struct(def_id())),
302302
ItemKind::Union(..) => Some(Def::Union(def_id())),
303303
ItemKind::Trait(..) => Some(Def::Trait(def_id())),
304-
ItemKind::TraitAlias(..) => {
305-
bug!("trait aliases are not yet implemented (see issue #41517)")
306-
},
304+
ItemKind::TraitAlias(..) => Some(Def::TraitAlias(def_id())),
307305
ItemKind::ExternCrate(_) |
308306
ItemKind::Use(..) |
309307
ItemKind::ForeignMod(..) |

src/librustc/ich/impls_ty.rs

+17
Original file line numberDiff line numberDiff line change
@@ -1119,6 +1119,7 @@ for traits::Vtable<'gcx, N> where N: HashStable<StableHashingContext<'a>> {
11191119
&VtableClosure(ref table_closure) => table_closure.hash_stable(hcx, hasher),
11201120
&VtableFnPointer(ref table_fn_pointer) => table_fn_pointer.hash_stable(hcx, hasher),
11211121
&VtableGenerator(ref table_generator) => table_generator.hash_stable(hcx, hasher),
1122+
&VtableTraitAlias(ref table_alias) => table_alias.hash_stable(hcx, hasher),
11221123
}
11231124
}
11241125
}
@@ -1227,6 +1228,22 @@ for traits::VtableGeneratorData<'gcx, N> where N: HashStable<StableHashingContex
12271228
}
12281229
}
12291230

1231+
impl<'a, 'gcx, N> HashStable<StableHashingContext<'a>>
1232+
for traits::VtableTraitAliasData<'gcx, N> where N: HashStable<StableHashingContext<'a>> {
1233+
fn hash_stable<W: StableHasherResult>(&self,
1234+
hcx: &mut StableHashingContext<'a>,
1235+
hasher: &mut StableHasher<W>) {
1236+
let traits::VtableTraitAliasData {
1237+
alias_def_id,
1238+
substs,
1239+
ref nested,
1240+
} = *self;
1241+
alias_def_id.hash_stable(hcx, hasher);
1242+
substs.hash_stable(hcx, hasher);
1243+
nested.hash_stable(hcx, hasher);
1244+
}
1245+
}
1246+
12301247
impl_stable_hash_for!(
12311248
impl<'tcx, V> for struct infer::canonical::Canonical<'tcx, V> {
12321249
max_universe, variables, value

src/librustc/middle/resolve_lifetime.rs

+15-4
Original file line numberDiff line numberDiff line change
@@ -447,6 +447,17 @@ fn krate<'tcx>(tcx: TyCtxt<'_, 'tcx, 'tcx>) -> NamedRegionMap {
447447
map
448448
}
449449

450+
/// In traits, there is an implicit `Self` type parameter which comes before the generics.
451+
/// We have to account for this when computing the index of the other generic parameters.
452+
/// This function returns whether there is such an implicit parameter defined on the given item.
453+
fn sub_items_have_self_param(node: &hir::ItemKind) -> bool {
454+
match *node {
455+
hir::ItemKind::Trait(..) |
456+
hir::ItemKind::TraitAlias(..) => true,
457+
_ => false,
458+
}
459+
}
460+
450461
impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
451462
fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
452463
NestedVisitorMap::All(&self.tcx.hir)
@@ -522,8 +533,8 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
522533
hir::ItemKind::Impl(..) => true,
523534
_ => false,
524535
};
525-
// These kinds of items have only early bound lifetime parameters.
526-
let mut index = if let hir::ItemKind::Trait(..) = item.node {
536+
// These kinds of items have only early-bound lifetime parameters.
537+
let mut index = if sub_items_have_self_param(&item.node) {
527538
1 // Self comes before lifetimes
528539
} else {
529540
0
@@ -1602,8 +1613,8 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
16021613
let mut index = 0;
16031614
if let Some(parent_id) = parent_id {
16041615
let parent = self.tcx.hir.expect_item(parent_id);
1605-
if let hir::ItemKind::Trait(..) = parent.node {
1606-
index += 1; // Self comes first.
1616+
if sub_items_have_self_param(&parent.node) {
1617+
index += 1; // Self comes before lifetimes
16071618
}
16081619
match parent.node {
16091620
hir::ItemKind::Trait(_, _, ref generics, ..)

src/librustc/traits/mod.rs

+25-9
Original file line numberDiff line numberDiff line change
@@ -534,8 +534,11 @@ pub enum Vtable<'tcx, N> {
534534
/// Same as above, but for a fn pointer type with the given signature.
535535
VtableFnPointer(VtableFnPointerData<'tcx, N>),
536536

537-
/// Vtable automatically generated for a generator
537+
/// Vtable automatically generated for a generator.
538538
VtableGenerator(VtableGeneratorData<'tcx, N>),
539+
540+
/// Vtable for a trait alias.
541+
VtableTraitAlias(VtableTraitAliasData<'tcx, N>),
539542
}
540543

541544
/// Identifies a particular impl in the source, along with a set of
@@ -605,6 +608,13 @@ pub struct VtableFnPointerData<'tcx, N> {
605608
pub nested: Vec<N>
606609
}
607610

611+
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable)]
612+
pub struct VtableTraitAliasData<'tcx, N> {
613+
pub alias_def_id: DefId,
614+
pub substs: &'tcx Substs<'tcx>,
615+
pub nested: Vec<N>,
616+
}
617+
608618
/// Creates predicate obligations from the generic bounds.
609619
pub fn predicates_for_generics<'tcx>(cause: ObligationCause<'tcx>,
610620
param_env: ty::ParamEnv<'tcx>,
@@ -1067,6 +1077,7 @@ impl<'tcx, N> Vtable<'tcx, N> {
10671077
VtableGenerator(c) => c.nested,
10681078
VtableObject(d) => d.nested,
10691079
VtableFnPointer(d) => d.nested,
1080+
VtableTraitAlias(d) => d.nested,
10701081
}
10711082
}
10721083

@@ -1090,20 +1101,25 @@ impl<'tcx, N> Vtable<'tcx, N> {
10901101
trait_def_id: d.trait_def_id,
10911102
nested: d.nested.into_iter().map(f).collect(),
10921103
}),
1093-
VtableFnPointer(p) => VtableFnPointer(VtableFnPointerData {
1094-
fn_ty: p.fn_ty,
1095-
nested: p.nested.into_iter().map(f).collect(),
1104+
VtableClosure(c) => VtableClosure(VtableClosureData {
1105+
closure_def_id: c.closure_def_id,
1106+
substs: c.substs,
1107+
nested: c.nested.into_iter().map(f).collect(),
10961108
}),
10971109
VtableGenerator(c) => VtableGenerator(VtableGeneratorData {
10981110
generator_def_id: c.generator_def_id,
10991111
substs: c.substs,
11001112
nested: c.nested.into_iter().map(f).collect(),
11011113
}),
1102-
VtableClosure(c) => VtableClosure(VtableClosureData {
1103-
closure_def_id: c.closure_def_id,
1104-
substs: c.substs,
1105-
nested: c.nested.into_iter().map(f).collect(),
1106-
})
1114+
VtableFnPointer(p) => VtableFnPointer(VtableFnPointerData {
1115+
fn_ty: p.fn_ty,
1116+
nested: p.nested.into_iter().map(f).collect(),
1117+
}),
1118+
VtableTraitAlias(d) => VtableTraitAlias(VtableTraitAliasData {
1119+
alias_def_id: d.alias_def_id,
1120+
substs: d.substs,
1121+
nested: d.nested.into_iter().map(f).collect(),
1122+
}),
11071123
}
11081124
}
11091125
}

src/librustc/traits/project.rs

+6-7
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,7 @@ use super::PredicateObligation;
1919
use super::Selection;
2020
use super::SelectionContext;
2121
use super::SelectionError;
22-
use super::VtableClosureData;
23-
use super::VtableGeneratorData;
24-
use super::VtableFnPointerData;
25-
use super::VtableImplData;
22+
use super::{VtableImplData, VtableClosureData, VtableGeneratorData, VtableFnPointerData};
2623
use super::util;
2724

2825
use hir::def_id::DefId;
@@ -1073,7 +1070,8 @@ fn assemble_candidates_from_impls<'cx, 'gcx, 'tcx>(
10731070
super::VtableClosure(_) |
10741071
super::VtableGenerator(_) |
10751072
super::VtableFnPointer(_) |
1076-
super::VtableObject(_) => {
1073+
super::VtableObject(_) |
1074+
super::VtableTraitAlias(_) => {
10771075
debug!("assemble_candidates_from_impls: vtable={:?}",
10781076
vtable);
10791077
true
@@ -1235,7 +1233,8 @@ fn confirm_select_candidate<'cx, 'gcx, 'tcx>(
12351233
confirm_object_candidate(selcx, obligation, obligation_trait_ref),
12361234
super::VtableAutoImpl(..) |
12371235
super::VtableParam(..) |
1238-
super::VtableBuiltin(..) =>
1236+
super::VtableBuiltin(..) |
1237+
super::VtableTraitAlias(..) =>
12391238
// we don't create Select candidates with this kind of resolution
12401239
span_bug!(
12411240
obligation.cause.span,
@@ -1486,7 +1485,7 @@ fn confirm_impl_candidate<'cx, 'gcx, 'tcx>(
14861485
impl_vtable: VtableImplData<'tcx, PredicateObligation<'tcx>>)
14871486
-> Progress<'tcx>
14881487
{
1489-
let VtableImplData { substs, nested, impl_def_id } = impl_vtable;
1488+
let VtableImplData { impl_def_id, substs, nested } = impl_vtable;
14901489

14911490
let tcx = selcx.tcx();
14921491
let param_env = obligation.param_env;

0 commit comments

Comments
 (0)