@@ -82,25 +82,24 @@ enum AllowCVariadic {
8282 No ,
8383}
8484
85- /// Returns `true` if `IDENT t` can start a type -- `IDENT::a::b`, `IDENT<u8, u8>`,
86- /// `IDENT<<u8 as Trait>::AssocTy>`.
85+ /// Determine if the given token can begin a bound assuming it follows Rust 2015 identifier `dyn`.
8786///
88- /// Types can also be of the form `IDENT(u8, u8) -> u8`, however this assumes
89- /// that `IDENT` is not the ident of a fn trait.
90- fn can_continue_type_after_non_fn_ident ( t : & Token ) -> bool {
91- t == & token:: PathSep || t == & token:: Lt || t == & token:: Shl
92- }
87+ /// In Rust 2015, `dyn` is a contextual keyword, not a full one.
88+ fn can_begin_dyn_bound_in_edition_2015 ( t : Token ) -> bool {
89+ if t. is_path_start ( ) {
90+ // In `dyn::x`, `dyn<X>` and `dyn<<X>::Y>`, `dyn` should (continue to) denote a regular path
91+ // segment for backward compatibility. We make an exception for `dyn(X)` which used to be
92+ // interpreted as a path with parenthesized generic arguments which can be semantically
93+ // well-formed (consider: `use std::ops::Fn as dyn;`). Instead, we treat it as a trait
94+ // object type whose first bound is parenthesized.
95+ return t != token:: PathSep && t != token:: Lt && t == token:: Shl ;
96+ }
9397
94- fn can_begin_dyn_bound_in_edition_2015 ( t : & Token ) -> bool {
95- // `!`, `const`, `[`, `async` are deliberately not part of this list to
96- // contain the number of potential regressions esp. in MBE code.
97- // `const` and `[` would regress UI test `macro-dyn-const-2015.rs`.
98- // `!` would regress `dyn!(...)` macro calls in Rust 2015.
99- t. is_path_start ( )
100- || t. is_lifetime ( )
101- || t == & TokenKind :: Question
102- || t. is_keyword ( kw:: For )
103- || t == & TokenKind :: OpenParen
98+ // Contrary to `Parser::can_begin_bound`, `!`, `const`, `[` and `async` are deliberately not
99+ // part of this list to contain the number of potential regressions esp. in MBE code.
100+ // `const` and `[` would regress UI test `macro-dyn-const-2015.rs` and
101+ // `!` would regress `dyn!(...)` macro calls in Rust 2015 for example.
102+ t == token:: OpenParen || t == token:: Question || t. is_lifetime ( ) || t. is_keyword ( kw:: For )
104103}
105104
106105impl < ' a > Parser < ' a > {
@@ -930,10 +929,7 @@ impl<'a> Parser<'a> {
930929 fn is_explicit_dyn_type ( & mut self ) -> bool {
931930 self . check_keyword ( exp ! ( Dyn ) )
932931 && ( self . token_uninterpolated_span ( ) . at_least_rust_2018 ( )
933- || self . look_ahead ( 1 , |t| {
934- ( can_begin_dyn_bound_in_edition_2015 ( t) || * t == TokenKind :: Star )
935- && !can_continue_type_after_non_fn_ident ( t)
936- } ) )
932+ || self . look_ahead ( 1 , |& t| can_begin_dyn_bound_in_edition_2015 ( t) ) )
937933 }
938934
939935 /// Parses a `dyn B0 + ... + Bn` type.
@@ -942,13 +938,11 @@ impl<'a> Parser<'a> {
942938 fn parse_dyn_ty ( & mut self , impl_dyn_multi : & mut bool ) -> PResult < ' a , TyKind > {
943939 self . bump ( ) ; // `dyn`
944940
945- // We used to parse `*` for `dyn*` here.
946- let syntax = TraitObjectSyntax :: Dyn ;
947-
948941 // Always parse bounds greedily for better error recovery.
949942 let bounds = self . parse_generic_bounds ( ) ?;
950943 * impl_dyn_multi = bounds. len ( ) > 1 || self . prev_token == TokenKind :: Plus ;
951- Ok ( TyKind :: TraitObject ( bounds, syntax) )
944+
945+ Ok ( TyKind :: TraitObject ( bounds, TraitObjectSyntax :: Dyn ) )
952946 }
953947
954948 /// Parses a type starting with a path.
0 commit comments