ast: normalize ForeignItemKind::Ty & AssocItemKind::TyAlias.

This commit is contained in:
Mazdak Farrokhzad 2020-02-14 12:55:42 +01:00
parent e2ae717265
commit 95dc9b9a73
18 changed files with 192 additions and 37 deletions

View File

@ -682,7 +682,7 @@ fn lower_foreign_item(&mut self, i: &ForeignItem) -> hir::ForeignItem<'hir> {
let ty = self.lower_ty(t, ImplTraitContext::disallowed());
hir::ForeignItemKind::Static(ty, m)
}
ForeignItemKind::Ty => hir::ForeignItemKind::Type,
ForeignItemKind::TyAlias(..) => hir::ForeignItemKind::Type,
ForeignItemKind::Macro(_) => panic!("macro shouldn't exist here"),
},
vis: self.lower_visibility(&i.vis, None),

View File

@ -22,6 +22,9 @@
use syntax::visit::{self, AssocCtxt, FnCtxt, FnKind, Visitor};
use syntax::walk_list;
const MORE_EXTERN: &str =
"for more information, visit https://doc.rust-lang.org/std/keyword.extern.html";
/// Is `self` allowed semantically as the first parameter in an `FnDecl`?
enum SelfSemantic {
Yes,
@ -423,14 +426,59 @@ fn check_impl_item_provided<T>(&self, sp: Span, body: &Option<T>, ctx: &str, sug
}
}
fn check_impl_assoc_type_no_bounds(&self, bounds: &[GenericBound]) {
fn check_type_no_bounds(&self, bounds: &[GenericBound], ctx: &str) {
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")
.struct_span_err(span, &format!("bounds on `type`s in {} have no effect", ctx))
.emit();
}
fn check_foreign_ty_genericless(&self, generics: &Generics) {
let cannot_have = |span, descr, remove_descr| {
self.err_handler()
.struct_span_err(
span,
&format!("`type`s inside `extern` blocks cannot have {}", descr),
)
.span_suggestion(
span,
&format!("remove the {}", remove_descr),
String::new(),
Applicability::MaybeIncorrect,
)
.span_label(self.current_extern_span(), "`extern` block begins here")
.note(MORE_EXTERN)
.emit();
};
if !generics.params.is_empty() {
cannot_have(generics.span, "generic parameters", "generic parameters");
}
if !generics.where_clause.predicates.is_empty() {
cannot_have(generics.where_clause.span, "`where` clauses", "`where` clause");
}
}
fn check_foreign_ty_bodyless(&self, ident: Ident, body: Option<&Ty>) {
let body = match body {
None => return,
Some(body) => body,
};
self.err_handler()
.struct_span_err(ident.span, "incorrect `type` inside `extern` block")
.span_label(ident.span, "cannot have a body")
.span_label(body.span, "the invalid body")
.span_label(
self.current_extern_span(),
"`extern` blocks define existing foreign types and types \
inside of them cannot have a body",
)
.note(MORE_EXTERN)
.emit();
}
@ -458,7 +506,7 @@ fn check_foreign_fn_bodyless(&self, ident: Ident, body: Option<&Block>) {
"`extern` blocks define existing foreign functions and functions \
inside of them cannot have a body",
)
.note("for more information, visit https://doc.rust-lang.org/std/keyword.extern.html")
.note(MORE_EXTERN)
.emit();
}
@ -912,7 +960,12 @@ fn visit_foreign_item(&mut self, fi: &'a ForeignItem) {
self.check_foreign_fn_bodyless(fi.ident, body.as_deref());
self.check_foreign_fn_headerless(fi.ident, fi.span, sig.header);
}
ForeignItemKind::Static(..) | ForeignItemKind::Ty | ForeignItemKind::Macro(..) => {}
ForeignItemKind::TyAlias(generics, bounds, body) => {
self.check_foreign_ty_bodyless(fi.ident, body.as_deref());
self.check_type_no_bounds(bounds, "`extern` blocks");
self.check_foreign_ty_genericless(generics);
}
ForeignItemKind::Static(..) | ForeignItemKind::Macro(..) => {}
}
visit::walk_foreign_item(self, fi)
@ -1159,7 +1212,7 @@ fn visit_assoc_item(&mut self, item: &'a AssocItem, ctxt: AssocCtxt) {
}
AssocItemKind::TyAlias(_, bounds, body) => {
self.check_impl_item_provided(item.span, body, "type", " = <type>;");
self.check_impl_assoc_type_no_bounds(bounds);
self.check_type_no_bounds(bounds, "`impl`s");
}
_ => {}
}

View File

@ -397,7 +397,7 @@ fn visit_foreign_item(&mut self, i: &'a ast::ForeignItem) {
);
}
}
ast::ForeignItemKind::Ty => {
ast::ForeignItemKind::TyAlias(..) => {
gate_feature_post!(&self, extern_types, i.span, "extern types are experimental");
}
ast::ForeignItemKind::Macro(..) => {}

View File

@ -1019,13 +1019,13 @@ pub fn print_type(&mut self, ty: &ast::Ty) {
self.hardbreak_if_not_bol();
self.maybe_print_comment(item.span.lo());
self.print_outer_attributes(&item.attrs);
match item.kind {
ast::ForeignItemKind::Fn(ref sig, ref gen, ref body) => {
match &item.kind {
ast::ForeignItemKind::Fn(sig, gen, body) => {
self.print_fn_full(sig, item.ident, gen, &item.vis, body.as_deref(), &item.attrs);
}
ast::ForeignItemKind::Static(ref t, m) => {
ast::ForeignItemKind::Static(t, m) => {
self.head(visibility_qualified(&item.vis, "static"));
if m == ast::Mutability::Mut {
if *m == ast::Mutability::Mut {
self.word_space("mut");
}
self.print_ident(item.ident);
@ -1035,14 +1035,10 @@ pub fn print_type(&mut self, ty: &ast::Ty) {
self.end(); // end the head-ibox
self.end(); // end the outer cbox
}
ast::ForeignItemKind::Ty => {
self.head(visibility_qualified(&item.vis, "type"));
self.print_ident(item.ident);
self.s.word(";");
self.end(); // end the head-ibox
self.end(); // end the outer cbox
ast::ForeignItemKind::TyAlias(generics, bounds, ty) => {
self.print_associated_type(item.ident, generics, bounds, ty.as_deref());
}
ast::ForeignItemKind::Macro(ref m) => {
ast::ForeignItemKind::Macro(m) => {
self.print_mac(m);
if m.args.need_semicolon() {
self.s.word(";");

View File

@ -876,7 +876,7 @@ pub fn parse_foreign_item(&mut self, at_end: &mut bool) -> PResult<'a, P<Foreign
let lo = self.token.span;
let vis = self.parse_visibility(FollowedByType::No)?;
let (ident, kind) = if self.check_keyword(kw::Type) {
let (ident, kind) = if self.eat_keyword(kw::Type) {
// FOREIGN TYPE ITEM
self.parse_item_foreign_type()?
} else if self.check_fn_front_matter() {
@ -925,10 +925,12 @@ fn parse_item_foreign_static(&mut self) -> PResult<'a, (Ident, ForeignItemKind)>
/// Parses a type from a foreign module.
fn parse_item_foreign_type(&mut self) -> PResult<'a, (Ident, ForeignItemKind)> {
self.expect_keyword(kw::Type)?;
let ident = self.parse_ident()?;
self.expect_semi()?;
Ok((ident, ForeignItemKind::Ty))
let (ident, kind) = self.parse_assoc_ty()?;
let kind = match kind {
AssocItemKind::TyAlias(g, b, d) => ForeignItemKind::TyAlias(g, b, d),
_ => unreachable!(),
};
Ok((ident, kind))
}
fn is_static_global(&mut self) -> bool {

View File

@ -829,7 +829,7 @@ fn build_reduced_graph_for_foreign_item(&mut self, item: &ForeignItem) {
ForeignItemKind::Static(..) => {
(Res::Def(DefKind::Static, self.r.definitions.local_def_id(item.id)), ValueNS)
}
ForeignItemKind::Ty => {
ForeignItemKind::TyAlias(..) => {
(Res::Def(DefKind::ForeignTy, self.r.definitions.local_def_id(item.id)), TypeNS)
}
ForeignItemKind::Macro(_) => unreachable!(),

View File

@ -437,7 +437,8 @@ fn visit_poly_trait_ref(&mut self, tref: &'ast PolyTraitRef, m: &'ast TraitBound
}
fn visit_foreign_item(&mut self, foreign_item: &'ast ForeignItem) {
match foreign_item.kind {
ForeignItemKind::Fn(_, ref generics, _) => {
ForeignItemKind::Fn(_, ref generics, _)
| ForeignItemKind::TyAlias(ref generics, ..) => {
self.with_generic_param_rib(generics, ItemRibKind(HasGenericParams::Yes), |this| {
visit::walk_foreign_item(this, foreign_item);
});
@ -447,7 +448,7 @@ fn visit_foreign_item(&mut self, foreign_item: &'ast ForeignItem) {
visit::walk_foreign_item(this, foreign_item);
});
}
ForeignItemKind::Ty | ForeignItemKind::Macro(..) => {
ForeignItemKind::Macro(..) => {
visit::walk_foreign_item(self, foreign_item);
}
}

View File

@ -1540,7 +1540,7 @@ fn visit_foreign_item(&mut self, item: &'l ast::ForeignItem) {
self.visit_ty(ty);
}
ast::ForeignItemKind::Ty => {
ast::ForeignItemKind::TyAlias(..) => {
if let Some(var_data) = self.save_ctxt.get_extern_item_data(item) {
down_cast_data!(var_data, DefData, item.span);
self.dumper.dump_def(&access, var_data);

View File

@ -173,7 +173,7 @@ pub fn get_extern_item_data(&self, item: &ast::ForeignItem) -> Option<Data> {
}))
}
// FIXME(plietar): needs a new DefKind in rls-data
ast::ForeignItemKind::Ty => None,
ast::ForeignItemKind::TyAlias(..) => None,
ast::ForeignItemKind::Macro(..) => None,
}
}

View File

@ -773,7 +773,7 @@ fn make(&self, offset: usize, _parent_id: Option<NodeId>, scx: &SaveContext<'_,
Ok(extend_sig(ty_sig, text, defs, vec![]))
}
ast::ForeignItemKind::Ty => {
ast::ForeignItemKind::TyAlias(..) => {
let mut text = "type ".to_owned();
let name = self.ident.to_string();
let defs = vec![SigElement {

View File

@ -2610,7 +2610,7 @@ pub enum ForeignItemKind {
/// A function.
Fn(FnSig, Generics, Option<P<Block>>),
/// A type.
Ty,
TyAlias(Generics, GenericBounds, Option<P<Ty>>),
/// A macro expanding to an item.
Macro(Mac),
}
@ -2620,7 +2620,7 @@ pub fn descriptive_variant(&self) -> &str {
match *self {
ForeignItemKind::Fn(..) => "foreign function",
ForeignItemKind::Static(..) => "foreign static item",
ForeignItemKind::Ty => "foreign type",
ForeignItemKind::TyAlias(..) => "foreign type",
ForeignItemKind::Macro(..) => "macro in foreign module",
}
}

View File

@ -1051,7 +1051,11 @@ pub fn noop_flat_map_foreign_item<T: MutVisitor>(
visit_opt(body, |body| visitor.visit_block(body));
}
ForeignItemKind::Static(t, _m) => visitor.visit_ty(t),
ForeignItemKind::Ty => {}
ForeignItemKind::TyAlias(generics, bounds, ty) => {
visitor.visit_generics(generics);
visit_bounds(bounds, visitor);
visit_opt(ty, |ty| visitor.visit_ty(ty));
}
ForeignItemKind::Macro(mac) => visitor.visit_mac(mac),
}
visitor.visit_id(id);

View File

@ -535,7 +535,11 @@ pub fn walk_foreign_item<'a, V: Visitor<'a>>(visitor: &mut V, item: &'a ForeignI
visitor.visit_fn(kind, item.span, item.id);
}
ForeignItemKind::Static(ref typ, _) => visitor.visit_ty(typ),
ForeignItemKind::Ty => (),
ForeignItemKind::TyAlias(ref generics, ref bounds, ref ty) => {
visitor.visit_generics(generics);
walk_list!(visitor, visit_param_bound, bounds);
walk_list!(visitor, visit_ty, ty);
}
ForeignItemKind::Macro(ref mac) => visitor.visit_mac(mac),
}

View File

@ -0,0 +1,18 @@
#![feature(extern_types)]
fn main() {}
extern "C" {
type A: Ord;
//~^ ERROR bounds on `type`s in `extern` blocks have no effect
type B<'a> where 'a: 'static;
//~^ ERROR `type`s inside `extern` blocks cannot have generic parameters
//~| ERROR `type`s inside `extern` blocks cannot have `where` clauses
type C<T: Ord> where T: 'static;
//~^ ERROR `type`s inside `extern` blocks cannot have generic parameters
//~| ERROR `type`s inside `extern` blocks cannot have `where` clauses
type D = u8;
//~^ ERROR incorrect `type` inside `extern` block
type E: where;
}

View File

@ -0,0 +1,65 @@
error: bounds on `type`s in `extern` blocks have no effect
--> $DIR/foreign-ty-semantic-fail.rs:6:13
|
LL | type A: Ord;
| ^^^
error: `type`s inside `extern` blocks cannot have generic parameters
--> $DIR/foreign-ty-semantic-fail.rs:8:11
|
LL | extern "C" {
| ---------- `extern` block begins here
...
LL | type B<'a> where 'a: 'static;
| ^^^^ help: remove the generic parameters
|
= note: for more information, visit https://doc.rust-lang.org/std/keyword.extern.html
error: `type`s inside `extern` blocks cannot have `where` clauses
--> $DIR/foreign-ty-semantic-fail.rs:8:16
|
LL | extern "C" {
| ---------- `extern` block begins here
...
LL | type B<'a> where 'a: 'static;
| ^^^^^^^^^^^^^^^^^ help: remove the `where` clause
|
= note: for more information, visit https://doc.rust-lang.org/std/keyword.extern.html
error: `type`s inside `extern` blocks cannot have generic parameters
--> $DIR/foreign-ty-semantic-fail.rs:11:11
|
LL | extern "C" {
| ---------- `extern` block begins here
...
LL | type C<T: Ord> where T: 'static;
| ^^^^^^^^ help: remove the generic parameters
|
= note: for more information, visit https://doc.rust-lang.org/std/keyword.extern.html
error: `type`s inside `extern` blocks cannot have `where` clauses
--> $DIR/foreign-ty-semantic-fail.rs:11:20
|
LL | extern "C" {
| ---------- `extern` block begins here
...
LL | type C<T: Ord> where T: 'static;
| ^^^^^^^^^^^^^^^^ help: remove the `where` clause
|
= note: for more information, visit https://doc.rust-lang.org/std/keyword.extern.html
error: incorrect `type` inside `extern` block
--> $DIR/foreign-ty-semantic-fail.rs:14:10
|
LL | extern "C" {
| ---------- `extern` blocks define existing foreign types and types inside of them cannot have a body
...
LL | type D = u8;
| ^ -- the invalid body
| |
| cannot have a body
|
= note: for more information, visit https://doc.rust-lang.org/std/keyword.extern.html
error: aborting due to 6 previous errors

View File

@ -0,0 +1,12 @@
// check-pass
fn main() {}
#[cfg(FALSE)]
extern "C" {
type A: Ord;
type A<'a> where 'a: 'static;
type A<T: Ord> where T: 'static;
type A = u8;
type A<'a: 'static, T: Ord + 'static>: Eq + PartialEq where T: 'static + Copy = Vec<u8>;
}

View File

@ -11,11 +11,11 @@ impl X {
//~| 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 bounds on `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 bounds on `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

@ -14,7 +14,7 @@ LL | type Z: Ord;
| |
| help: provide a definition for the type: `= <type>;`
error: bounds on associated `type`s in `impl`s have no effect
error: bounds on `type`s in `impl`s have no effect
--> $DIR/impl-item-type-no-body-semantic-fail.rs:12:13
|
LL | type Z: Ord;
@ -28,7 +28,7 @@ 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
error: bounds on `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;