Unify {Trait,Impl}ItemKind::TyAlias
structures.
This commit is contained in:
parent
c02fd31302
commit
39073767a4
@ -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>"
|
||||
|
@ -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,
|
||||
},
|
||||
|
@ -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()?;
|
||||
|
@ -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);
|
||||
|
@ -8,6 +8,7 @@
|
||||
|
||||
#![feature(in_band_lifetimes)]
|
||||
#![feature(nll)]
|
||||
#![feature(slice_patterns)]
|
||||
|
||||
#![recursion_limit="256"]
|
||||
|
||||
|
@ -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!"),
|
||||
}
|
||||
|
@ -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.
|
||||
|
@ -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),
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
_ => {}
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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,
|
||||
}
|
||||
});
|
||||
|
11
src/test/ui/parser/impl-item-type-no-body-pass.rs
Normal file
11
src/test/ui/parser/impl-item-type-no-body-pass.rs
Normal 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;
|
||||
}
|
22
src/test/ui/parser/impl-item-type-no-body-semantic-fail.rs
Normal file
22
src/test/ui/parser/impl-item-type-no-body-semantic-fail.rs
Normal 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
|
||||
}
|
@ -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`.
|
Loading…
Reference in New Issue
Block a user