@@ -1733,7 +1733,7 @@ impl<'a> Parser<'a> {
17331733 }
17341734 } else if self . eat_keyword ( keywords:: Impl ) {
17351735 // Always parse bounds greedily for better error recovery.
1736- let bounds = self . parse_generic_bounds ( ) ?;
1736+ let bounds = self . parse_generic_bounds ( None ) ?;
17371737 impl_dyn_multi = bounds. len ( ) > 1 || self . prev_token_kind == PrevTokenKind :: Plus ;
17381738 TyKind :: ImplTrait ( ast:: DUMMY_NODE_ID , bounds)
17391739 } else if self . check_keyword ( keywords:: Dyn ) &&
@@ -1742,13 +1742,13 @@ impl<'a> Parser<'a> {
17421742 !can_continue_type_after_non_fn_ident ( t) ) ) {
17431743 self . bump ( ) ; // `dyn`
17441744 // Always parse bounds greedily for better error recovery.
1745- let bounds = self . parse_generic_bounds ( ) ?;
1745+ let bounds = self . parse_generic_bounds ( None ) ?;
17461746 impl_dyn_multi = bounds. len ( ) > 1 || self . prev_token_kind == PrevTokenKind :: Plus ;
17471747 TyKind :: TraitObject ( bounds, TraitObjectSyntax :: Dyn )
17481748 } else if self . check ( & token:: Question ) ||
17491749 self . check_lifetime ( ) && self . look_ahead ( 1 , |t| t. is_like_plus ( ) ) {
17501750 // Bound list (trait object type)
1751- TyKind :: TraitObject ( self . parse_generic_bounds_common ( allow_plus) ?,
1751+ TyKind :: TraitObject ( self . parse_generic_bounds_common ( allow_plus, None ) ?,
17521752 TraitObjectSyntax :: None )
17531753 } else if self . eat_lt ( ) {
17541754 // Qualified path
@@ -1794,7 +1794,7 @@ impl<'a> Parser<'a> {
17941794 let mut bounds = vec ! [ GenericBound :: Trait ( poly_trait_ref, TraitBoundModifier :: None ) ] ;
17951795 if parse_plus {
17961796 self . eat_plus ( ) ; // `+`, or `+=` gets split and `+` is discarded
1797- bounds. append ( & mut self . parse_generic_bounds ( ) ?) ;
1797+ bounds. append ( & mut self . parse_generic_bounds ( None ) ?) ;
17981798 }
17991799 Ok ( TyKind :: TraitObject ( bounds, TraitObjectSyntax :: None ) )
18001800 }
@@ -1819,7 +1819,7 @@ impl<'a> Parser<'a> {
18191819 }
18201820
18211821 self . bump ( ) ; // `+`
1822- let bounds = self . parse_generic_bounds ( ) ?;
1822+ let bounds = self . parse_generic_bounds ( None ) ?;
18231823 let sum_span = ty. span . to ( self . prev_span ) ;
18241824
18251825 let mut err = struct_span_err ! ( self . sess. span_diagnostic, sum_span, E0178 ,
@@ -5496,18 +5496,24 @@ impl<'a> Parser<'a> {
54965496 /// TY_BOUND = TY_BOUND_NOPAREN | (TY_BOUND_NOPAREN)
54975497 /// TY_BOUND_NOPAREN = [?] [for<LT_PARAM_DEFS>] SIMPLE_PATH (e.g., `?for<'a: 'b> m::Trait<'a>`)
54985498 /// ```
5499- fn parse_generic_bounds_common ( & mut self , allow_plus : bool ) -> PResult < ' a , GenericBounds > {
5499+ fn parse_generic_bounds_common ( & mut self ,
5500+ allow_plus : bool ,
5501+ colon_span : Option < Span > ) -> PResult < ' a , GenericBounds > {
55005502 let mut bounds = Vec :: new ( ) ;
5503+ let mut negative_bounds = Vec :: new ( ) ;
5504+ let mut last_plus_span = None ;
55015505 loop {
55025506 // This needs to be synchronized with `Token::can_begin_bound`.
55035507 let is_bound_start = self . check_path ( ) || self . check_lifetime ( ) ||
5508+ self . check ( & token:: Not ) || // used for error reporting only
55045509 self . check ( & token:: Question ) ||
55055510 self . check_keyword ( keywords:: For ) ||
55065511 self . check ( & token:: OpenDelim ( token:: Paren ) ) ;
55075512 if is_bound_start {
55085513 let lo = self . span ;
55095514 let has_parens = self . eat ( & token:: OpenDelim ( token:: Paren ) ) ;
55105515 let inner_lo = self . span ;
5516+ let is_negative = self . eat ( & token:: Not ) ;
55115517 let question = if self . eat ( & token:: Question ) { Some ( self . prev_span ) } else { None } ;
55125518 if self . token . is_lifetime ( ) {
55135519 if let Some ( question_span) = question {
@@ -5538,28 +5544,60 @@ impl<'a> Parser<'a> {
55385544 if has_parens {
55395545 self . expect ( & token:: CloseDelim ( token:: Paren ) ) ?;
55405546 }
5541- let poly_trait = PolyTraitRef :: new ( lifetime_defs, path, lo. to ( self . prev_span ) ) ;
5542- let modifier = if question. is_some ( ) {
5543- TraitBoundModifier :: Maybe
5547+ let poly_span = lo. to ( self . prev_span ) ;
5548+ if is_negative {
5549+ negative_bounds. push (
5550+ last_plus_span. or ( colon_span) . unwrap ( )
5551+ . to ( poly_span) ) ;
55445552 } else {
5545- TraitBoundModifier :: None
5546- } ;
5547- bounds. push ( GenericBound :: Trait ( poly_trait, modifier) ) ;
5553+ let poly_trait = PolyTraitRef :: new ( lifetime_defs, path, poly_span) ;
5554+ let modifier = if question. is_some ( ) {
5555+ TraitBoundModifier :: Maybe
5556+ } else {
5557+ TraitBoundModifier :: None
5558+ } ;
5559+ bounds. push ( GenericBound :: Trait ( poly_trait, modifier) ) ;
5560+ }
55485561 }
55495562 } else {
55505563 break
55515564 }
55525565
55535566 if !allow_plus || !self . eat_plus ( ) {
55545567 break
5555- }
5568+ } else {
5569+ last_plus_span = Some ( self . prev_span ) ;
5570+ }
5571+ }
5572+
5573+ if !negative_bounds. is_empty ( ) {
5574+ let plural = negative_bounds. len ( ) > 1 ;
5575+ let mut err = self . struct_span_err ( negative_bounds,
5576+ "negative trait bounds are not supported" ) ;
5577+ let bound_list = colon_span. unwrap ( ) . to ( self . prev_span ) ;
5578+ let mut new_bound_list = String :: new ( ) ;
5579+ if !bounds. is_empty ( ) {
5580+ let mut snippets = bounds. iter ( ) . map ( |bound| bound. span ( ) )
5581+ . map ( |span| self . sess . source_map ( ) . span_to_snippet ( span) ) ;
5582+ while let Some ( Ok ( snippet) ) = snippets. next ( ) {
5583+ new_bound_list. push_str ( " + " ) ;
5584+ new_bound_list. push_str ( & snippet) ;
5585+ }
5586+ new_bound_list = new_bound_list. replacen ( " +" , ":" , 1 ) ;
5587+ }
5588+ err. span_suggestion_short ( bound_list,
5589+ & format ! ( "remove the trait bound{}" ,
5590+ if plural { "s" } else { "" } ) ,
5591+ new_bound_list,
5592+ Applicability :: MachineApplicable ) ;
5593+ err. emit ( ) ;
55565594 }
55575595
55585596 return Ok ( bounds) ;
55595597 }
55605598
5561- fn parse_generic_bounds ( & mut self ) -> PResult < ' a , GenericBounds > {
5562- self . parse_generic_bounds_common ( true )
5599+ fn parse_generic_bounds ( & mut self , colon_span : Option < Span > ) -> PResult < ' a , GenericBounds > {
5600+ self . parse_generic_bounds_common ( true , colon_span )
55635601 }
55645602
55655603 /// Parses bounds of a lifetime parameter `BOUND + BOUND + BOUND`, possibly with trailing `+`.
@@ -5587,7 +5625,7 @@ impl<'a> Parser<'a> {
55875625
55885626 // Parse optional colon and param bounds.
55895627 let bounds = if self . eat ( & token:: Colon ) {
5590- self . parse_generic_bounds ( ) ?
5628+ self . parse_generic_bounds ( None ) ?
55915629 } else {
55925630 Vec :: new ( )
55935631 } ;
@@ -5619,7 +5657,7 @@ impl<'a> Parser<'a> {
56195657
56205658 // Parse optional colon and param bounds.
56215659 let bounds = if self . eat ( & token:: Colon ) {
5622- self . parse_generic_bounds ( ) ?
5660+ self . parse_generic_bounds ( None ) ?
56235661 } else {
56245662 Vec :: new ( )
56255663 } ;
@@ -6032,7 +6070,7 @@ impl<'a> Parser<'a> {
60326070 // or with mandatory equality sign and the second type.
60336071 let ty = self . parse_ty ( ) ?;
60346072 if self . eat ( & token:: Colon ) {
6035- let bounds = self . parse_generic_bounds ( ) ?;
6073+ let bounds = self . parse_generic_bounds ( None ) ?;
60366074 where_clause. predicates . push ( ast:: WherePredicate :: BoundPredicate (
60376075 ast:: WhereBoundPredicate {
60386076 span : lo. to ( self . prev_span ) ,
@@ -6546,14 +6584,14 @@ impl<'a> Parser<'a> {
65466584
65476585 // Parse optional colon and supertrait bounds.
65486586 let bounds = if self . eat ( & token:: Colon ) {
6549- self . parse_generic_bounds ( ) ?
6587+ self . parse_generic_bounds ( Some ( self . prev_span ) ) ?
65506588 } else {
65516589 Vec :: new ( )
65526590 } ;
65536591
65546592 if self . eat ( & token:: Eq ) {
65556593 // it's a trait alias
6556- let bounds = self . parse_generic_bounds ( ) ?;
6594+ let bounds = self . parse_generic_bounds ( None ) ?;
65576595 tps. where_clause = self . parse_where_clause ( ) ?;
65586596 self . expect ( & token:: Semi ) ?;
65596597 if is_auto == IsAuto :: Yes {
@@ -7588,7 +7626,7 @@ impl<'a> Parser<'a> {
75887626 tps. where_clause = self . parse_where_clause ( ) ?;
75897627 let alias = if existential {
75907628 self . expect ( & token:: Colon ) ?;
7591- let bounds = self . parse_generic_bounds ( ) ?;
7629+ let bounds = self . parse_generic_bounds ( None ) ?;
75927630 AliasKind :: Existential ( bounds)
75937631 } else {
75947632 self . expect ( & token:: Eq ) ?;
0 commit comments