ast: normalize ForeignItemKind::Ty
& AssocItemKind::TyAlias
.
This commit is contained in:
parent
e2ae717265
commit
95dc9b9a73
@ -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),
|
||||
|
@ -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");
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
@ -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(..) => {}
|
||||
|
@ -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(";");
|
||||
|
@ -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 {
|
||||
|
@ -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!(),
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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,
|
||||
}
|
||||
}
|
||||
|
@ -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 {
|
||||
|
@ -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",
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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),
|
||||
}
|
||||
|
||||
|
18
src/test/ui/parser/foreign-ty-semantic-fail.rs
Normal file
18
src/test/ui/parser/foreign-ty-semantic-fail.rs
Normal 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;
|
||||
}
|
65
src/test/ui/parser/foreign-ty-semantic-fail.stderr
Normal file
65
src/test/ui/parser/foreign-ty-semantic-fail.stderr
Normal 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
|
||||
|
12
src/test/ui/parser/foreign-ty-syntactic-pass.rs
Normal file
12
src/test/ui/parser/foreign-ty-syntactic-pass.rs
Normal 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>;
|
||||
}
|
@ -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
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user