@@ -22,6 +22,9 @@ use syntax::expand::is_proc_macro_attr;
2222use syntax:: visit:: { self , AssocCtxt , FnCtxt , FnKind , Visitor } ;
2323use syntax:: walk_list;
2424
25+ const MORE_EXTERN : & str =
26+ "for more information, visit https://doc.rust-lang.org/std/keyword.extern.html" ;
27+
2528/// Is `self` allowed semantically as the first parameter in an `FnDecl`?
2629enum SelfSemantic {
2730 Yes ,
@@ -423,14 +426,59 @@ impl<'a> AstValidator<'a> {
423426 }
424427 }
425428
426- fn check_impl_assoc_type_no_bounds ( & self , bounds : & [ GenericBound ] ) {
429+ fn check_type_no_bounds ( & self , bounds : & [ GenericBound ] , ctx : & str ) {
427430 let span = match bounds {
428431 [ ] => return ,
429432 [ b0] => b0. span ( ) ,
430433 [ b0, .., bl] => b0. span ( ) . to ( bl. span ( ) ) ,
431434 } ;
432435 self . err_handler ( )
433- . struct_span_err ( span, "bounds on associated `type`s in `impl`s have no effect" )
436+ . struct_span_err ( span, & format ! ( "bounds on `type`s in {} have no effect" , ctx) )
437+ . emit ( ) ;
438+ }
439+
440+ fn check_foreign_ty_genericless ( & self , generics : & Generics ) {
441+ let cannot_have = |span, descr, remove_descr| {
442+ self . err_handler ( )
443+ . struct_span_err (
444+ span,
445+ & format ! ( "`type`s inside `extern` blocks cannot have {}" , descr) ,
446+ )
447+ . span_suggestion (
448+ span,
449+ & format ! ( "remove the {}" , remove_descr) ,
450+ String :: new ( ) ,
451+ Applicability :: MaybeIncorrect ,
452+ )
453+ . span_label ( self . current_extern_span ( ) , "`extern` block begins here" )
454+ . note ( MORE_EXTERN )
455+ . emit ( ) ;
456+ } ;
457+
458+ if !generics. params . is_empty ( ) {
459+ cannot_have ( generics. span , "generic parameters" , "generic parameters" ) ;
460+ }
461+
462+ if !generics. where_clause . predicates . is_empty ( ) {
463+ cannot_have ( generics. where_clause . span , "`where` clauses" , "`where` clause" ) ;
464+ }
465+ }
466+
467+ fn check_foreign_ty_bodyless ( & self , ident : Ident , body : Option < & Ty > ) {
468+ let body = match body {
469+ None => return ,
470+ Some ( body) => body,
471+ } ;
472+ self . err_handler ( )
473+ . struct_span_err ( ident. span , "incorrect `type` inside `extern` block" )
474+ . span_label ( ident. span , "cannot have a body" )
475+ . span_label ( body. span , "the invalid body" )
476+ . span_label (
477+ self . current_extern_span ( ) ,
478+ "`extern` blocks define existing foreign types and types \
479+ inside of them cannot have a body",
480+ )
481+ . note ( MORE_EXTERN )
434482 . emit ( ) ;
435483 }
436484
@@ -458,7 +506,7 @@ impl<'a> AstValidator<'a> {
458506 "`extern` blocks define existing foreign functions and functions \
459507 inside of them cannot have a body",
460508 )
461- . note ( "for more information, visit https://doc.rust-lang.org/std/keyword.extern.html" )
509+ . note ( MORE_EXTERN )
462510 . emit ( ) ;
463511 }
464512
@@ -912,7 +960,12 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
912960 self . check_foreign_fn_bodyless ( fi. ident , body. as_deref ( ) ) ;
913961 self . check_foreign_fn_headerless ( fi. ident , fi. span , sig. header ) ;
914962 }
915- ForeignItemKind :: Static ( ..) | ForeignItemKind :: Ty | ForeignItemKind :: Macro ( ..) => { }
963+ ForeignItemKind :: TyAlias ( generics, bounds, body) => {
964+ self . check_foreign_ty_bodyless ( fi. ident , body. as_deref ( ) ) ;
965+ self . check_type_no_bounds ( bounds, "`extern` blocks" ) ;
966+ self . check_foreign_ty_genericless ( generics) ;
967+ }
968+ ForeignItemKind :: Static ( ..) | ForeignItemKind :: Macro ( ..) => { }
916969 }
917970
918971 visit:: walk_foreign_item ( self , fi)
@@ -1159,7 +1212,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
11591212 }
11601213 AssocItemKind :: TyAlias ( _, bounds, body) => {
11611214 self . check_impl_item_provided ( item. span , body, "type" , " = <type>;" ) ;
1162- self . check_impl_assoc_type_no_bounds ( bounds) ;
1215+ self . check_type_no_bounds ( bounds, "`impl`s" ) ;
11631216 }
11641217 _ => { }
11651218 }
0 commit comments