@@ -4,6 +4,7 @@ use crate::maybe_whole;
44use rustc_ast:: ast:: { self , AngleBracketedArg , AngleBracketedArgs , GenericArg , ParenthesizedArgs } ;
55use rustc_ast:: ast:: { AnonConst , AssocTyConstraint , AssocTyConstraintKind , BlockCheckMode } ;
66use rustc_ast:: ast:: { Ident , Path , PathSegment , QSelf } ;
7+ use rustc_ast:: ptr:: P ;
78use rustc_ast:: token:: { self , Token } ;
89use rustc_errors:: { pluralize, Applicability , PResult } ;
910use rustc_span:: source_map:: { BytePos , Span } ;
@@ -405,7 +406,8 @@ impl<'a> Parser<'a> {
405406 let lo = self . token . span ;
406407 let ident = self . parse_ident ( ) ?;
407408 let kind = if self . eat ( & token:: Eq ) {
408- AssocTyConstraintKind :: Equality { ty : self . parse_ty ( ) ? }
409+ let ty = self . parse_assoc_equality_term ( ident, self . prev_token . span ) ?;
410+ AssocTyConstraintKind :: Equality { ty }
409411 } else if self . eat ( & token:: Colon ) {
410412 let bounds = self . parse_generic_bounds ( Some ( self . prev_token . span ) ) ?;
411413 AssocTyConstraintKind :: Bound { bounds }
@@ -427,6 +429,46 @@ impl<'a> Parser<'a> {
427429 }
428430 }
429431
432+ /// Parse the term to the right of an associated item equality constraint.
433+ /// That is, parse `<term>` in `Item = <term>`.
434+ /// Right now, this only admits types in `<term>`.
435+ fn parse_assoc_equality_term ( & mut self , ident : Ident , eq : Span ) -> PResult < ' a , P < ast:: Ty > > {
436+ let arg = self . parse_generic_arg ( ) ?;
437+ let span = ident. span . to ( self . prev_token . span ) ;
438+ match arg {
439+ Some ( GenericArg :: Type ( ty) ) => return Ok ( ty) ,
440+ Some ( GenericArg :: Const ( expr) ) => {
441+ self . struct_span_err ( span, "cannot constrain an associated constant to a value" )
442+ . span_label ( ident. span , "the value constrains this associated constant" )
443+ . span_label ( expr. value . span , "the value is given in this expression" )
444+ . emit ( ) ;
445+ }
446+ Some ( GenericArg :: Lifetime ( lt) ) => {
447+ self . struct_span_err ( span, "associated lifetimes are not supported" )
448+ . span_label ( lt. ident . span , "the lifetime is given here" )
449+ . help ( "if you meant to specify a trait object, write `dyn Trait + 'lifetime`" )
450+ . emit ( ) ;
451+ }
452+ None => {
453+ self . struct_span_err ( span, "missing type to the right of `=`" )
454+ . span_suggestion (
455+ span,
456+ "to constrain the associated type, add a type after `=`" ,
457+ format ! ( "{} = TheType" , ident) ,
458+ Applicability :: HasPlaceholders ,
459+ )
460+ . span_suggestion (
461+ eq,
462+ & format ! ( "remove the `=` if `{}` is a type" , ident) ,
463+ String :: new ( ) ,
464+ Applicability :: MaybeIncorrect ,
465+ )
466+ . emit ( ) ;
467+ }
468+ }
469+ Ok ( self . mk_ty ( span, ast:: TyKind :: Err ) )
470+ }
471+
430472 /// Parse a generic argument in a path segment.
431473 /// This does not include constraints, e.g., `Item = u8`, which is handled in `parse_angle_arg`.
432474 fn parse_generic_arg ( & mut self ) -> PResult < ' a , Option < GenericArg > > {
0 commit comments