Skip to content

Commit 0077d12

Browse files
committed
Auto merge of #45047 - durka:trait-alias, r=petrochenkov
trait alias infrastructure This will be an implementation of trait aliases (RFC 1733, #41517). Progress so far: - [x] Feature gate - [x] Add to parser - [x] `where` clauses - [x] prohibit LHS type parameter bounds via AST validation #45047 (comment) - [x] Add to AST and HIR - [x] make a separate PathSource for trait alias contexts #45047 (comment) - [x] Stub out enough of typeck and resolve to just barely not ICE Postponed: - [ ] Actually implement the alias part - [ ] #21903 - [ ] #24010 I need some pointers on where to start with that last one. The test currently does this: ``` error[E0283]: type annotations required: cannot resolve `_: CD` --> src/test/run-pass/trait-alias.rs:34:16 | 34 | let both = foo(); | ^^^ | = note: required by `foo` ```
2 parents 3fc7f85 + 834674f commit 0077d12

File tree

35 files changed

+323
-35
lines changed

35 files changed

+323
-35
lines changed

Diff for: src/librustc/hir/def.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ pub enum Def {
3737
Trait(DefId),
3838
TyAlias(DefId),
3939
TyForeign(DefId),
40+
TraitAlias(DefId),
4041
AssociatedTy(DefId),
4142
PrimTy(hir::PrimTy),
4243
TyParam(DefId),
@@ -155,7 +156,8 @@ impl Def {
155156
pub fn def_id(&self) -> DefId {
156157
match *self {
157158
Def::Fn(id) | Def::Mod(id) | Def::Static(id, _) |
158-
Def::Variant(id) | Def::VariantCtor(id, ..) | Def::Enum(id) | Def::TyAlias(id) |
159+
Def::Variant(id) | Def::VariantCtor(id, ..) | Def::Enum(id) |
160+
Def::TyAlias(id) | Def::TraitAlias(id) |
159161
Def::AssociatedTy(id) | Def::TyParam(id) | Def::Struct(id) | Def::StructCtor(id, ..) |
160162
Def::Union(id) | Def::Trait(id) | Def::Method(id) | Def::Const(id) |
161163
Def::AssociatedConst(id) | Def::Macro(id, ..) |
@@ -186,6 +188,7 @@ impl Def {
186188
Def::VariantCtor(.., CtorKind::Fictive) => "struct variant",
187189
Def::Enum(..) => "enum",
188190
Def::TyAlias(..) => "type alias",
191+
Def::TraitAlias(..) => "trait alias",
189192
Def::AssociatedTy(..) => "associated type",
190193
Def::Struct(..) => "struct",
191194
Def::StructCtor(.., CtorKind::Fn) => "tuple struct",

Diff for: src/librustc/hir/intravisit.rs

+5
Original file line numberDiff line numberDiff line change
@@ -526,6 +526,11 @@ pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item) {
526526
walk_list!(visitor, visit_ty_param_bound, bounds);
527527
walk_list!(visitor, visit_trait_item_ref, trait_item_refs);
528528
}
529+
ItemTraitAlias(ref generics, ref bounds) => {
530+
visitor.visit_id(item.id);
531+
visitor.visit_generics(generics);
532+
walk_list!(visitor, visit_ty_param_bound, bounds);
533+
}
529534
}
530535
walk_list!(visitor, visit_attribute, &item.attrs);
531536
}

Diff for: src/librustc/hir/lowering.rs

+4-2
Original file line numberDiff line numberDiff line change
@@ -1924,9 +1924,11 @@ impl<'a> LoweringContext<'a> {
19241924
bounds,
19251925
items)
19261926
}
1927-
ItemKind::MacroDef(..) | ItemKind::Mac(..) => {
1928-
panic!("Shouldn't still be around")
1927+
ItemKind::TraitAlias(ref generics, ref bounds) => {
1928+
hir::ItemTraitAlias(self.lower_generics(generics),
1929+
self.lower_bounds(bounds, ImplTraitContext::Disallowed))
19291930
}
1931+
ItemKind::MacroDef(..) | ItemKind::Mac(..) => panic!("Shouldn't still be around"),
19301932
}
19311933

19321934
// [1] `defaultness.has_value()` is never called for an `impl`, always `true` in order to

Diff for: src/librustc/hir/map/def_collector.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,8 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> {
106106
let def_data = match i.node {
107107
ItemKind::AutoImpl(..) | ItemKind::Impl(..) =>
108108
DefPathData::Impl,
109-
ItemKind::Enum(..) | ItemKind::Struct(..) | ItemKind::Union(..) | ItemKind::Trait(..) |
109+
ItemKind::Enum(..) | ItemKind::Struct(..) | ItemKind::Union(..) |
110+
ItemKind::Trait(..) | ItemKind::TraitAlias(..) |
110111
ItemKind::ExternCrate(..) | ItemKind::ForeignMod(..) | ItemKind::Ty(..) =>
111112
DefPathData::TypeNs(i.ident.name.as_str()),
112113
ItemKind::Mod(..) if i.ident == keywords::Invalid.ident() => {

Diff for: src/librustc/hir/map/mod.rs

+1
Original file line numberDiff line numberDiff line change
@@ -1185,6 +1185,7 @@ fn node_id_to_string(map: &Map, id: NodeId, include_id: bool) -> String {
11851185
ItemStruct(..) => "struct",
11861186
ItemUnion(..) => "union",
11871187
ItemTrait(..) => "trait",
1188+
ItemTraitAlias(..) => "trait alias",
11881189
ItemImpl(..) => "impl",
11891190
ItemAutoImpl(..) => "default impl",
11901191
};

Diff for: src/librustc/hir/mod.rs

+3
Original file line numberDiff line numberDiff line change
@@ -1888,6 +1888,8 @@ pub enum Item_ {
18881888
ItemUnion(VariantData, Generics),
18891889
/// Represents a Trait Declaration
18901890
ItemTrait(IsAuto, Unsafety, Generics, TyParamBounds, HirVec<TraitItemRef>),
1891+
/// Represents a Trait Alias Declaration
1892+
ItemTraitAlias(Generics, TyParamBounds),
18911893

18921894
/// Auto trait implementations
18931895
///
@@ -1919,6 +1921,7 @@ impl Item_ {
19191921
ItemStruct(..) => "struct",
19201922
ItemUnion(..) => "union",
19211923
ItemTrait(..) => "trait",
1924+
ItemTraitAlias(..) => "trait alias",
19221925
ItemImpl(..) |
19231926
ItemAutoImpl(..) => "item",
19241927
}

Diff for: src/librustc/hir/print.rs

+21
Original file line numberDiff line numberDiff line change
@@ -747,6 +747,27 @@ impl<'a> State<'a> {
747747
}
748748
self.bclose(item.span)?;
749749
}
750+
hir::ItemTraitAlias(ref generics, ref bounds) => {
751+
self.head("")?;
752+
self.print_visibility(&item.vis)?;
753+
self.word_nbsp("trait")?;
754+
self.print_name(item.name)?;
755+
self.print_generics(generics)?;
756+
let mut real_bounds = Vec::with_capacity(bounds.len());
757+
// FIXME(durka) this seems to be some quite outdated syntax
758+
for b in bounds.iter() {
759+
if let TraitTyParamBound(ref ptr, hir::TraitBoundModifier::Maybe) = *b {
760+
self.s.space()?;
761+
self.word_space("for ?")?;
762+
self.print_trait_ref(&ptr.trait_ref)?;
763+
} else {
764+
real_bounds.push(b.clone());
765+
}
766+
}
767+
self.print_bounds(" = ", &real_bounds[..])?;
768+
self.print_where_clause(&generics.where_clause)?;
769+
self.s.word(";")?;
770+
}
750771
}
751772
self.ann.post(self, NodeItem(item))
752773
}

Diff for: src/librustc/ich/impls_hir.rs

+2
Original file line numberDiff line numberDiff line change
@@ -848,6 +848,7 @@ impl_stable_hash_for!(enum hir::Item_ {
848848
ItemStruct(variant_data, generics),
849849
ItemUnion(variant_data, generics),
850850
ItemTrait(is_auto, unsafety, generics, bounds, item_refs),
851+
ItemTraitAlias(generics, bounds),
851852
ItemAutoImpl(unsafety, trait_ref),
852853
ItemImpl(unsafety, impl_polarity, impl_defaultness, generics, trait_ref, ty, impl_item_refs)
853854
});
@@ -1004,6 +1005,7 @@ impl_stable_hash_for!(enum hir::def::Def {
10041005
Variant(def_id),
10051006
Trait(def_id),
10061007
TyAlias(def_id),
1008+
TraitAlias(def_id),
10071009
AssociatedTy(def_id),
10081010
PrimTy(prim_ty),
10091011
TyParam(def_id),

Diff for: src/librustc/middle/reachable.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -268,7 +268,7 @@ impl<'a, 'tcx> ReachableContext<'a, 'tcx> {
268268
hir::ItemExternCrate(_) | hir::ItemUse(..) |
269269
hir::ItemTy(..) | hir::ItemStatic(..) |
270270
hir::ItemMod(..) | hir::ItemForeignMod(..) |
271-
hir::ItemImpl(..) | hir::ItemTrait(..) |
271+
hir::ItemImpl(..) | hir::ItemTrait(..) | hir::ItemTraitAlias(..) |
272272
hir::ItemStruct(..) | hir::ItemEnum(..) |
273273
hir::ItemUnion(..) | hir::ItemAutoImpl(..) |
274274
hir::ItemGlobalAsm(..) => {}

Diff for: src/librustc/middle/resolve_lifetime.rs

+1
Original file line numberDiff line numberDiff line change
@@ -469,6 +469,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
469469
| hir::ItemStruct(_, ref generics)
470470
| hir::ItemUnion(_, ref generics)
471471
| hir::ItemTrait(_, _, ref generics, ..)
472+
| hir::ItemTraitAlias(ref generics, ..)
472473
| hir::ItemImpl(_, _, _, ref generics, ..) => {
473474
// These kinds of items have only early bound lifetime parameters.
474475
let mut index = if let hir::ItemTrait(..) = item.node {

Diff for: src/librustc/ty/mod.rs

+1
Original file line numberDiff line numberDiff line change
@@ -2577,6 +2577,7 @@ fn associated_item_def_ids<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
25772577
.map(|id| tcx.hir.local_def_id(id.node_id))
25782578
.collect()
25792579
}
2580+
hir::ItemTraitAlias(..) => vec![],
25802581
_ => span_bug!(item.span, "associated_item_def_ids: not impl or trait")
25812582
};
25822583
Rc::new(vec)

Diff for: src/librustc_driver/test.rs

+1
Original file line numberDiff line numberDiff line change
@@ -248,6 +248,7 @@ impl<'a, 'gcx, 'tcx> Env<'a, 'gcx, 'tcx> {
248248
hir::ItemStruct(..) |
249249
hir::ItemUnion(..) |
250250
hir::ItemTrait(..) |
251+
hir::ItemTraitAlias(..) |
251252
hir::ItemImpl(..) |
252253
hir::ItemAutoImpl(..) => None,
253254

Diff for: src/librustc_metadata/encoder.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -979,6 +979,7 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> {
979979
EntryKind::Trait(self.lazy(&data))
980980
}
981981
hir::ItemExternCrate(_) |
982+
hir::ItemTraitAlias(..) |
982983
hir::ItemUse(..) => bug!("cannot encode info for item {:?}", item),
983984
};
984985

@@ -1526,7 +1527,8 @@ impl<'a, 'b, 'tcx> IndexBuilder<'a, 'b, 'tcx> {
15261527
hir::ItemExternCrate(..) |
15271528
hir::ItemUse(..) |
15281529
hir::ItemAutoImpl(..) |
1529-
hir::ItemTy(..) => {
1530+
hir::ItemTy(..) |
1531+
hir::ItemTraitAlias(..) => {
15301532
// no sub-item recording needed in these cases
15311533
}
15321534
hir::ItemEnum(..) => {

Diff for: src/librustc_passes/ast_validation.rs

+14
Original file line numberDiff line numberDiff line change
@@ -283,6 +283,20 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
283283
}
284284
}
285285
}
286+
ItemKind::TraitAlias(Generics { ref ty_params, .. }, ..) => {
287+
for &TyParam { ref bounds, ref default, span, .. } in ty_params {
288+
if !bounds.is_empty() {
289+
self.err_handler().span_err(span,
290+
"type parameters on the left side of a \
291+
trait alias cannot be bounded");
292+
}
293+
if !default.is_none() {
294+
self.err_handler().span_err(span,
295+
"type parameters on the left side of a \
296+
trait alias cannot have defaults");
297+
}
298+
}
299+
}
286300
ItemKind::Mod(_) => {
287301
// Ensure that `path` attributes on modules are recorded as used (c.f. #35584).
288302
attr::first_attr_value_str_by_name(&item.attrs, "path");

Diff for: src/librustc_privacy/lib.rs

+11-2
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,8 @@ impl<'a, 'tcx> Visitor<'tcx> for EmbargoVisitor<'a, 'tcx> {
158158
// Other `pub` items inherit levels from parents
159159
hir::ItemConst(..) | hir::ItemEnum(..) | hir::ItemExternCrate(..) |
160160
hir::ItemGlobalAsm(..) | hir::ItemFn(..) | hir::ItemMod(..) |
161-
hir::ItemStatic(..) | hir::ItemStruct(..) | hir::ItemTrait(..) |
161+
hir::ItemStatic(..) | hir::ItemStruct(..) |
162+
hir::ItemTrait(..) | hir::ItemTraitAlias(..) |
162163
hir::ItemTy(..) | hir::ItemUnion(..) | hir::ItemUse(..) => {
163164
if item.vis == hir::Public { self.prev_level } else { None }
164165
}
@@ -212,7 +213,7 @@ impl<'a, 'tcx> Visitor<'tcx> for EmbargoVisitor<'a, 'tcx> {
212213
}
213214
}
214215
hir::ItemUse(..) | hir::ItemStatic(..) | hir::ItemConst(..) |
215-
hir::ItemGlobalAsm(..) | hir::ItemTy(..) | hir::ItemMod(..) |
216+
hir::ItemGlobalAsm(..) | hir::ItemTy(..) | hir::ItemMod(..) | hir::ItemTraitAlias(..) |
216217
hir::ItemFn(..) | hir::ItemExternCrate(..) | hir::ItemAutoImpl(..) => {}
217218
}
218219

@@ -252,6 +253,11 @@ impl<'a, 'tcx> Visitor<'tcx> for EmbargoVisitor<'a, 'tcx> {
252253
}
253254
}
254255
}
256+
hir::ItemTraitAlias(..) => {
257+
if item_level.is_some() {
258+
self.reach(item.id).generics().predicates();
259+
}
260+
}
255261
// Visit everything except for private impl items
256262
hir::ItemImpl(.., ref trait_ref, _, ref impl_item_refs) => {
257263
if item_level.is_some() {
@@ -1498,6 +1504,9 @@ impl<'a, 'tcx> Visitor<'tcx> for PrivateItemsInPublicInterfacesVisitor<'a, 'tcx>
14981504
}
14991505
}
15001506
}
1507+
hir::ItemTraitAlias(..) => {
1508+
self.check(item.id, item_visibility).generics().predicates();
1509+
}
15011510
hir::ItemEnum(ref def, _) => {
15021511
self.check(item.id, item_visibility).generics().predicates();
15031512

Diff for: src/librustc_resolve/build_reduced_graph.rs

+6
Original file line numberDiff line numberDiff line change
@@ -344,6 +344,11 @@ impl<'a> Resolver<'a> {
344344
}
345345
}
346346

347+
ItemKind::TraitAlias(..) => {
348+
let def = Def::TraitAlias(self.definitions.local_def_id(item.id));
349+
self.define(parent, ident, TypeNS, (def, vis, sp, expansion));
350+
}
351+
347352
// These items live in both the type and value namespaces.
348353
ItemKind::Struct(ref struct_def, _) => {
349354
// Define a name in the type namespace.
@@ -411,6 +416,7 @@ impl<'a> Resolver<'a> {
411416
self.define(parent, ident, TypeNS, (module, vis, sp, expansion));
412417
self.current_module = module;
413418
}
419+
414420
ItemKind::MacroDef(..) | ItemKind::Mac(_) => unreachable!(),
415421
}
416422
}

Diff for: src/librustc_resolve/lib.rs

+33-11
Original file line numberDiff line numberDiff line change
@@ -390,12 +390,18 @@ impl PatternSource {
390390
}
391391
}
392392

393+
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
394+
enum AliasPossibility {
395+
No,
396+
Maybe,
397+
}
398+
393399
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
394400
enum PathSource<'a> {
395401
// Type paths `Path`.
396402
Type,
397403
// Trait paths in bounds or impls.
398-
Trait,
404+
Trait(AliasPossibility),
399405
// Expression paths `path`, with optional parent context.
400406
Expr(Option<&'a Expr>),
401407
// Paths in path patterns `Path`.
@@ -415,7 +421,7 @@ enum PathSource<'a> {
415421
impl<'a> PathSource<'a> {
416422
fn namespace(self) -> Namespace {
417423
match self {
418-
PathSource::Type | PathSource::Trait | PathSource::Struct |
424+
PathSource::Type | PathSource::Trait(_) | PathSource::Struct |
419425
PathSource::Visibility | PathSource::ImportPrefix => TypeNS,
420426
PathSource::Expr(..) | PathSource::Pat | PathSource::TupleStruct => ValueNS,
421427
PathSource::TraitItem(ns) => ns,
@@ -427,23 +433,23 @@ impl<'a> PathSource<'a> {
427433
PathSource::Visibility | PathSource::ImportPrefix => true,
428434
PathSource::Type | PathSource::Expr(..) | PathSource::Pat |
429435
PathSource::Struct | PathSource::TupleStruct |
430-
PathSource::Trait | PathSource::TraitItem(..) => false,
436+
PathSource::Trait(_) | PathSource::TraitItem(..) => false,
431437
}
432438
}
433439

434440
fn defer_to_typeck(self) -> bool {
435441
match self {
436442
PathSource::Type | PathSource::Expr(..) | PathSource::Pat |
437443
PathSource::Struct | PathSource::TupleStruct => true,
438-
PathSource::Trait | PathSource::TraitItem(..) |
444+
PathSource::Trait(_) | PathSource::TraitItem(..) |
439445
PathSource::Visibility | PathSource::ImportPrefix => false,
440446
}
441447
}
442448

443449
fn descr_expected(self) -> &'static str {
444450
match self {
445451
PathSource::Type => "type",
446-
PathSource::Trait => "trait",
452+
PathSource::Trait(_) => "trait",
447453
PathSource::Pat => "unit struct/variant or constant",
448454
PathSource::Struct => "struct, variant or union type",
449455
PathSource::TupleStruct => "tuple struct/variant",
@@ -472,10 +478,15 @@ impl<'a> PathSource<'a> {
472478
Def::TyForeign(..) => true,
473479
_ => false,
474480
},
475-
PathSource::Trait => match def {
481+
PathSource::Trait(AliasPossibility::No) => match def {
476482
Def::Trait(..) => true,
477483
_ => false,
478484
},
485+
PathSource::Trait(AliasPossibility::Maybe) => match def {
486+
Def::Trait(..) => true,
487+
Def::TraitAlias(..) => true,
488+
_ => false,
489+
},
479490
PathSource::Expr(..) => match def {
480491
Def::StructCtor(_, CtorKind::Const) | Def::StructCtor(_, CtorKind::Fn) |
481492
Def::VariantCtor(_, CtorKind::Const) | Def::VariantCtor(_, CtorKind::Fn) |
@@ -530,8 +541,8 @@ impl<'a> PathSource<'a> {
530541
__diagnostic_used!(E0577);
531542
__diagnostic_used!(E0578);
532543
match (self, has_unexpected_resolution) {
533-
(PathSource::Trait, true) => "E0404",
534-
(PathSource::Trait, false) => "E0405",
544+
(PathSource::Trait(_), true) => "E0404",
545+
(PathSource::Trait(_), false) => "E0405",
535546
(PathSource::Type, true) => "E0573",
536547
(PathSource::Type, false) => "E0412",
537548
(PathSource::Struct, true) => "E0574",
@@ -693,7 +704,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Resolver<'a> {
693704
tref: &'tcx ast::PolyTraitRef,
694705
m: &'tcx ast::TraitBoundModifier) {
695706
self.smart_resolve_path(tref.trait_ref.ref_id, None,
696-
&tref.trait_ref.path, PathSource::Trait);
707+
&tref.trait_ref.path, PathSource::Trait(AliasPossibility::Maybe));
697708
visit::walk_poly_trait_ref(self, tref, m);
698709
}
699710
fn visit_variant(&mut self,
@@ -1935,6 +1946,17 @@ impl<'a> Resolver<'a> {
19351946
});
19361947
}
19371948

1949+
ItemKind::TraitAlias(ref generics, ref bounds) => {
1950+
// Create a new rib for the trait-wide type parameters.
1951+
self.with_type_parameter_rib(HasTypeParameters(generics, ItemRibKind), |this| {
1952+
let local_def_id = this.definitions.local_def_id(item.id);
1953+
this.with_self_rib(Def::SelfTy(Some(local_def_id), None), |this| {
1954+
this.visit_generics(generics);
1955+
walk_list!(this, visit_ty_param_bound, bounds);
1956+
});
1957+
});
1958+
}
1959+
19381960
ItemKind::Mod(_) | ItemKind::ForeignMod(_) => {
19391961
self.with_scope(item.id, |this| {
19401962
visit::walk_item(this, item);
@@ -2083,7 +2105,7 @@ impl<'a> Resolver<'a> {
20832105
&path,
20842106
trait_ref.path.span,
20852107
trait_ref.path.segments.last().unwrap().span,
2086-
PathSource::Trait)
2108+
PathSource::Trait(AliasPossibility::No))
20872109
.base_def();
20882110
if def != Def::Err {
20892111
new_id = Some(def.def_id());
@@ -2635,7 +2657,7 @@ impl<'a> Resolver<'a> {
26352657
err.span_label(span, format!("did you mean `{}!(...)`?", path_str));
26362658
return (err, candidates);
26372659
}
2638-
(Def::TyAlias(..), PathSource::Trait) => {
2660+
(Def::TyAlias(..), PathSource::Trait(_)) => {
26392661
err.span_label(span, "type aliases cannot be used for traits");
26402662
return (err, candidates);
26412663
}

0 commit comments

Comments
 (0)