Unify {Trait,Impl}ItemKind::TyAlias structures.

This commit is contained in:
Mazdak Farrokhzad 2019-12-01 10:25:45 +01:00
parent c02fd31302
commit 39073767a4
16 changed files with 209 additions and 54 deletions

View File

@ -1253,6 +1253,14 @@ fn lower_path_ty(
ty
}
fn ty(&mut self, span: Span, kind: hir::TyKind) -> hir::Ty {
hir::Ty { hir_id: self.next_id(), kind, span }
}
fn ty_tup(&mut self, span: Span, tys: HirVec<hir::Ty>) -> hir::Ty {
self.ty(span, hir::TyKind::Tup(tys))
}
fn lower_ty_direct(&mut self, t: &Ty, mut itctx: ImplTraitContext<'_>) -> hir::Ty {
let kind = match t.kind {
TyKind::Infer => hir::TyKind::Infer,
@ -2084,12 +2092,9 @@ fn lower_parenthesized_parameter_data(
.iter()
.map(|ty| this.lower_ty_direct(ty, ImplTraitContext::disallowed()))
.collect();
let mk_tup = |this: &mut Self, tys, span| {
hir::Ty { kind: hir::TyKind::Tup(tys), hir_id: this.next_id(), span }
};
(
hir::GenericArgs {
args: hir_vec![GenericArg::Type(mk_tup(this, inputs, span))],
args: hir_vec![GenericArg::Type(this.ty_tup(span, inputs))],
bindings: hir_vec![
hir::TypeBinding {
hir_id: this.next_id(),
@ -2102,7 +2107,7 @@ fn lower_parenthesized_parameter_data(
ImplTraitContext::disallowed()
))
.unwrap_or_else(||
P(mk_tup(this, hir::HirVec::new(), span))
P(this.ty_tup(span, hir::HirVec::new()))
),
},
span: output.as_ref().map_or(span, |ty| ty.span),
@ -2474,17 +2479,13 @@ fn lower_async_fn_ret_ty(
})
);
// Create the `Foo<...>` refernece itself. Note that the `type
// Create the `Foo<...>` reference itself. Note that the `type
// Foo = impl Trait` is, internally, created as a child of the
// async fn, so the *type parameters* are inherited. It's
// only the lifetime parameters that we must supply.
let opaque_ty_ref = hir::TyKind::Def(hir::ItemId { id: opaque_ty_id }, generic_args.into());
hir::FunctionRetTy::Return(P(hir::Ty {
kind: opaque_ty_ref,
span: opaque_ty_span,
hir_id: self.next_id(),
}))
let opaque_ty = self.ty(opaque_ty_span, opaque_ty_ref);
hir::FunctionRetTy::Return(P(opaque_ty))
}
/// Transforms `-> T` into `Future<Output = T>`
@ -2496,16 +2497,8 @@ fn lower_async_fn_output_type_to_future_bound(
) -> hir::GenericBound {
// Compute the `T` in `Future<Output = T>` from the return type.
let output_ty = match output {
FunctionRetTy::Ty(ty) => {
self.lower_ty(ty, ImplTraitContext::OpaqueTy(Some(fn_def_id)))
}
FunctionRetTy::Default(ret_ty_span) => {
P(hir::Ty {
hir_id: self.next_id(),
kind: hir::TyKind::Tup(hir_vec![]),
span: *ret_ty_span,
})
}
FunctionRetTy::Ty(ty) => self.lower_ty(ty, ImplTraitContext::OpaqueTy(Some(fn_def_id))),
FunctionRetTy::Default(ret_ty_span) => P(self.ty_tup(*ret_ty_span, hir_vec![])),
};
// "<Output = T>"

View File

@ -932,16 +932,21 @@ fn lower_impl_item(&mut self, i: &ImplItem) -> hir::ImplItem {
(generics, hir::ImplItemKind::Method(sig, body_id))
}
ImplItemKind::TyAlias(ref ty) => {
ImplItemKind::TyAlias(_, ref ty) => {
let generics = self.lower_generics(&i.generics, ImplTraitContext::disallowed());
let kind = match ty.kind.opaque_top_hack() {
let kind = match ty {
None => {
let ty = self.lower_ty(ty, ImplTraitContext::disallowed());
hir::ImplItemKind::TyAlias(ty)
hir::ImplItemKind::TyAlias(P(self.ty(i.span, hir::TyKind::Err)))
}
Some(bs) => {
let bounds = self.lower_param_bounds(bs, ImplTraitContext::disallowed());
hir::ImplItemKind::OpaqueTy(bounds)
Some(ty) => match ty.kind.opaque_top_hack() {
None => {
let ty = self.lower_ty(ty, ImplTraitContext::disallowed());
hir::ImplItemKind::TyAlias(ty)
}
Some(bs) => {
let bs = self.lower_param_bounds(bs, ImplTraitContext::disallowed());
hir::ImplItemKind::OpaqueTy(bs)
}
}
};
(generics, kind)
@ -972,7 +977,10 @@ fn lower_impl_item_ref(&mut self, i: &ImplItem) -> hir::ImplItemRef {
defaultness: self.lower_defaultness(i.defaultness, true /* [1] */),
kind: match &i.kind {
ImplItemKind::Const(..) => hir::AssocItemKind::Const,
ImplItemKind::TyAlias(ty) => match ty.kind.opaque_top_hack() {
ImplItemKind::TyAlias(_, ty) => match ty
.as_deref()
.and_then(|ty| ty.kind.opaque_top_hack())
{
None => hir::AssocItemKind::Type,
Some(_) => hir::AssocItemKind::OpaqueTy,
},

View File

@ -697,8 +697,7 @@ fn parse_impl_item_(
let vis = self.parse_visibility(FollowedByType::No)?;
let defaultness = self.parse_defaultness();
let (name, kind, generics) = if self.eat_keyword(kw::Type) {
let (name, ty, generics) = self.parse_type_alias()?;
(name, ast::ImplItemKind::TyAlias(ty), generics)
self.parse_impl_assoc_ty()?
} else if self.is_const_item() {
self.parse_impl_const()?
} else if let Some(mac) = self.parse_assoc_macro_invoc("impl", Some(&vis), at_end)? {
@ -766,6 +765,31 @@ fn parse_impl_const(&mut self) -> PResult<'a, (Ident, ImplItemKind, Generics)> {
Ok((ident, ImplItemKind::Const(ty, expr), Generics::default()))
}
/// Parses the following grammar:
///
/// AssocTy = Ident ["<"...">"] [":" [GenericBounds]] ["where" ...] ["=" Ty]
fn parse_impl_assoc_ty(&mut self) -> PResult<'a, (Ident, ImplItemKind, Generics)> {
let ident = self.parse_ident()?;
let mut generics = self.parse_generics()?;
// Parse optional colon and param bounds.
let bounds = if self.eat(&token::Colon) {
self.parse_generic_bounds(None)?
} else {
Vec::new()
};
generics.where_clause = self.parse_where_clause()?;
let default = if self.eat(&token::Eq) {
Some(self.parse_ty()?)
} else {
None
};
self.expect_semi()?;
Ok((ident, ImplItemKind::TyAlias(bounds, default), generics))
}
/// Parses `auto? trait Foo { ... }` or `trait Foo = Bar;`.
fn parse_item_trait(&mut self, lo: Span, unsafety: Unsafety) -> PResult<'a, ItemInfo> {
// Parse optional `auto` prefix.
@ -924,7 +948,7 @@ fn parse_trait_item_const(&mut self) -> PResult<'a, (Ident, TraitItemKind, Gener
/// Parses the following grammar:
///
/// TraitItemAssocTy = Ident ["<"...">"] [":" [GenericBounds]] ["where" ...] ["=" Ty]
/// AssocTy = Ident ["<"...">"] [":" [GenericBounds]] ["where" ...] ["=" Ty]
fn parse_trait_item_assoc_ty(&mut self) -> PResult<'a, (Ident, TraitItemKind, Generics)> {
let ident = self.parse_ident()?;
let mut generics = self.parse_generics()?;

View File

@ -295,6 +295,17 @@ fn check_impl_item_provided<T>(&self, sp: Span, body: &Option<T>, ctx: &str, sug
)
.emit();
}
fn check_impl_assoc_type_no_bounds(&self, bounds: &[GenericBound]) {
let span = match bounds {
[] => return,
[b0] => b0.span(),
[b0, .., bl] => b0.span().to(bl.span()),
};
self.err_handler()
.struct_span_err(span, "bounds on associated `type`s in `impl`s have no effect")
.emit();
}
}
enum GenericPosition {
@ -770,6 +781,10 @@ fn visit_impl_item(&mut self, ii: &'a ImplItem) {
self.check_impl_item_provided(ii.span, body, "function", " { <body> }");
self.check_fn_decl(&sig.decl);
}
ImplItemKind::TyAlias(bounds, body) => {
self.check_impl_item_provided(ii.span, body, "type", " = <type>;");
self.check_impl_assoc_type_no_bounds(bounds);
}
_ => {}
}
visit::walk_impl_item(self, ii);

View File

@ -8,6 +8,7 @@
#![feature(in_band_lifetimes)]
#![feature(nll)]
#![feature(slice_patterns)]
#![recursion_limit="256"]

View File

@ -1119,7 +1119,7 @@ fn resolve_implementation(&mut self,
visit::walk_impl_item(this, impl_item);
}
ImplItemKind::TyAlias(ref ty) => {
ImplItemKind::TyAlias(_, Some(ref ty)) => {
// If this is a trait impl, ensure the type
// exists in trait
this.check_trait_item(impl_item.ident,
@ -1129,6 +1129,7 @@ fn resolve_implementation(&mut self,
this.visit_ty(ty);
}
ImplItemKind::TyAlias(_, None) => {}
ImplItemKind::Macro(_) =>
panic!("unexpanded macro in resolve!"),
}

View File

@ -1127,7 +1127,8 @@ fn process_impl_item(&mut self, impl_item: &'l ast::ImplItem, impl_id: DefId) {
impl_item.span,
);
}
ast::ImplItemKind::TyAlias(ref ty) => {
ast::ImplItemKind::TyAlias(_, None) => {}
ast::ImplItemKind::TyAlias(_, Some(ref ty)) => {
// FIXME: uses of the assoc type should ideally point to this
// 'def' and the name here should be a ref to the def in the
// trait.

View File

@ -1638,7 +1638,7 @@ pub struct ImplItem<K = ImplItemKind> {
pub enum ImplItemKind {
Const(P<Ty>, Option<P<Expr>>),
Method(FnSig, Option<P<Block>>),
TyAlias(P<Ty>),
TyAlias(GenericBounds, Option<P<Ty>>),
Macro(Mac),
}

View File

@ -612,8 +612,10 @@ fn visit_impl_item(&mut self, ii: &'a ast::ImplItem) {
"C-variadic functions are unstable");
}
}
ast::ImplItemKind::TyAlias(ref ty) => {
self.check_impl_trait(ty);
ast::ImplItemKind::TyAlias(_, ref ty) => {
if let Some(ty) = ty {
self.check_impl_trait(ty);
}
self.check_gat(&ii.generics, ii.span);
}
_ => {}

View File

@ -987,7 +987,10 @@ pub fn noop_flat_map_impl_item<T: MutVisitor>(mut item: ImplItem, visitor: &mut
visit_fn_sig(sig, visitor);
visit_opt(body, |body| visitor.visit_block(body));
}
ImplItemKind::TyAlias(ty) => visitor.visit_ty(ty),
ImplItemKind::TyAlias(bounds, ty) => {
visit_bounds(bounds, visitor);
visit_opt(ty, |ty| visitor.visit_ty(ty));
}
ImplItemKind::Macro(mac) => visitor.visit_mac(mac),
}
visitor.visit_span(span);

View File

@ -1128,16 +1128,15 @@ fn print_associated_const(&mut self,
self.s.word(";")
}
fn print_associated_type(&mut self,
ident: ast::Ident,
bounds: Option<&ast::GenericBounds>,
ty: Option<&ast::Ty>)
{
fn print_associated_type(
&mut self,
ident: ast::Ident,
bounds: &ast::GenericBounds,
ty: Option<&ast::Ty>,
) {
self.word_space("type");
self.print_ident(ident);
if let Some(bounds) = bounds {
self.print_type_bounds(":", bounds);
}
self.print_type_bounds(":", bounds);
if let Some(ty) = ty {
self.s.space();
self.word_space("=");
@ -1568,8 +1567,7 @@ fn print_poly_trait_ref(&mut self, t: &ast::PolyTraitRef) {
}
}
ast::TraitItemKind::TyAlias(ref bounds, ref default) => {
self.print_associated_type(ti.ident, Some(bounds),
default.as_ref().map(|ty| &**ty));
self.print_associated_type(ti.ident, bounds, default.as_deref());
}
ast::TraitItemKind::Macro(ref mac) => {
self.print_mac(mac);
@ -1603,8 +1601,8 @@ fn print_poly_trait_ref(&mut self, t: &ast::PolyTraitRef) {
self.s.word(";");
}
}
ast::ImplItemKind::TyAlias(ref ty) => {
self.print_associated_type(ii.ident, None, Some(ty));
ast::ImplItemKind::TyAlias(ref bounds, ref ty) => {
self.print_associated_type(ii.ident, bounds, ty.as_deref());
}
ast::ImplItemKind::Macro(ref mac) => {
self.print_mac(mac);

View File

@ -627,8 +627,9 @@ pub fn walk_impl_item<'a, V: Visitor<'a>>(visitor: &mut V, impl_item: &'a ImplIt
visitor.visit_fn(FnKind::Method(impl_item.ident, sig, &impl_item.vis, body),
&sig.decl, impl_item.span, impl_item.id);
}
ImplItemKind::TyAlias(ref ty) => {
visitor.visit_ty(ty);
ImplItemKind::TyAlias(ref bounds, ref ty) => {
walk_list!(visitor, visit_param_bound, bounds);
walk_list!(visitor, visit_ty, ty);
}
ImplItemKind::Macro(ref mac) => {
visitor.visit_mac(mac);

View File

@ -519,7 +519,9 @@ fn create_derived_impl(&self,
attrs: Vec::new(),
generics: Generics::default(),
kind: ast::ImplItemKind::TyAlias(
type_def.to_ty(cx, self.span, type_ident, generics)),
Vec::new(),
Some(type_def.to_ty(cx, self.span, type_ident, generics)),
),
tokens: None,
}
});

View File

@ -0,0 +1,11 @@
// check-pass
fn main() {}
#[cfg(FALSE)]
impl X {
type Y;
type Z: Ord;
type W: Ord where Self: Eq;
type W where Self: Eq;
}

View File

@ -0,0 +1,22 @@
#![feature(generic_associated_types)]
//~^ WARN the feature `generic_associated_types` is incomplete
fn main() {}
struct X;
impl X {
type Y;
//~^ ERROR associated type in `impl` without body
//~| ERROR associated types are not yet supported in inherent impls
type Z: Ord;
//~^ ERROR associated type in `impl` without body
//~| ERROR bounds on associated `type`s in `impl`s have no effect
//~| ERROR associated types are not yet supported in inherent impls
type W: Ord where Self: Eq;
//~^ ERROR associated type in `impl` without body
//~| ERROR bounds on associated `type`s in `impl`s have no effect
//~| ERROR associated types are not yet supported in inherent impls
type W where Self: Eq;
//~^ ERROR associated type in `impl` without body
}

View File

@ -0,0 +1,73 @@
error: associated type in `impl` without body
--> $DIR/impl-item-type-no-body-semantic-fail.rs:9:5
|
LL | type Y;
| ^^^^^^-
| |
| help: provide a definition for the type: `= <type>;`
error: associated type in `impl` without body
--> $DIR/impl-item-type-no-body-semantic-fail.rs:12:5
|
LL | type Z: Ord;
| ^^^^^^^^^^^-
| |
| help: provide a definition for the type: `= <type>;`
error: bounds on associated `type`s in `impl`s have no effect
--> $DIR/impl-item-type-no-body-semantic-fail.rs:12:13
|
LL | type Z: Ord;
| ^^^
error: associated type in `impl` without body
--> $DIR/impl-item-type-no-body-semantic-fail.rs:16:5
|
LL | type W: Ord where Self: Eq;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^-
| |
| help: provide a definition for the type: `= <type>;`
error: bounds on associated `type`s in `impl`s have no effect
--> $DIR/impl-item-type-no-body-semantic-fail.rs:16:13
|
LL | type W: Ord where Self: Eq;
| ^^^
error: associated type in `impl` without body
--> $DIR/impl-item-type-no-body-semantic-fail.rs:20:5
|
LL | type W where Self: Eq;
| ^^^^^^^^^^^^^^^^^^^^^-
| |
| help: provide a definition for the type: `= <type>;`
warning: the feature `generic_associated_types` is incomplete and may cause the compiler to crash
--> $DIR/impl-item-type-no-body-semantic-fail.rs:1:12
|
LL | #![feature(generic_associated_types)]
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: `#[warn(incomplete_features)]` on by default
error[E0202]: associated types are not yet supported in inherent impls (see #8995)
--> $DIR/impl-item-type-no-body-semantic-fail.rs:9:5
|
LL | type Y;
| ^^^^^^^
error[E0202]: associated types are not yet supported in inherent impls (see #8995)
--> $DIR/impl-item-type-no-body-semantic-fail.rs:12:5
|
LL | type Z: Ord;
| ^^^^^^^^^^^^
error[E0202]: associated types are not yet supported in inherent impls (see #8995)
--> $DIR/impl-item-type-no-body-semantic-fail.rs:16:5
|
LL | type W: Ord where Self: Eq;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: aborting due to 9 previous errors
For more information about this error, try `rustc --explain E0202`.