11use rustc_ast:: ptr:: P ;
22use rustc_ast:: tokenstream:: TokenStream ;
3- use rustc_ast:: { ExprKind , LitIntType , LitKind , UintTy , token} ;
3+ use rustc_ast:: { ExprKind , LitIntType , LitKind , StrStyle , UintTy , token} ;
44use rustc_expand:: base:: { DummyResult , ExpandResult , ExtCtxt , MacEager , MacroExpanderResult } ;
55use rustc_session:: errors:: report_lit_error;
66use rustc_span:: { ErrorGuaranteed , Span } ;
@@ -21,15 +21,32 @@ fn invalid_type_err(
2121 let snippet = cx. sess . source_map ( ) . span_to_snippet ( span) . ok ( ) ;
2222 let dcx = cx. dcx ( ) ;
2323 match LitKind :: from_token_lit ( token_lit) {
24- Ok ( LitKind :: CStr ( _, _ ) ) => {
24+ Ok ( LitKind :: CStr ( _, style ) ) => {
2525 // Avoid ambiguity in handling of terminal `NUL` by refusing to
2626 // concatenate C string literals as bytes.
27- dcx. emit_err ( errors:: ConcatCStrLit { span } )
27+ let sugg = if let Some ( mut as_bstr) = snippet
28+ && style == StrStyle :: Cooked
29+ && as_bstr. starts_with ( 'c' )
30+ && as_bstr. ends_with ( '"' )
31+ {
32+ // Suggest`c"foo"` -> `b"foo\0"` if we can
33+ as_bstr. replace_range ( 0 ..1 , "b" ) ;
34+ as_bstr. pop ( ) ;
35+ as_bstr. push_str ( r#"\0""# ) ;
36+ Some ( ConcatBytesInvalidSuggestion :: CStrLit { span, as_bstr } )
37+ } else {
38+ // No suggestion for a missing snippet, raw strings, or if for some reason we have
39+ // a span that doesn't match `c"foo"` (possible if a proc macro assigns a span
40+ // that doesn't actually point to a C string).
41+ None
42+ } ;
43+ // We can only provide a suggestion if we have a snip and it is not a raw string
44+ dcx. emit_err ( ConcatBytesInvalid { span, lit_kind : "C string" , sugg, cs_note : Some ( ( ) ) } )
2845 }
2946 Ok ( LitKind :: Char ( _) ) => {
3047 let sugg =
3148 snippet. map ( |snippet| ConcatBytesInvalidSuggestion :: CharLit { span, snippet } ) ;
32- dcx. emit_err ( ConcatBytesInvalid { span, lit_kind : "character" , sugg } )
49+ dcx. emit_err ( ConcatBytesInvalid { span, lit_kind : "character" , sugg, cs_note : None } )
3350 }
3451 Ok ( LitKind :: Str ( _, _) ) => {
3552 // suggestion would be invalid if we are nested
@@ -38,18 +55,21 @@ fn invalid_type_err(
3855 } else {
3956 None
4057 } ;
41- dcx. emit_err ( ConcatBytesInvalid { span, lit_kind : "string" , sugg } )
58+ dcx. emit_err ( ConcatBytesInvalid { span, lit_kind : "string" , sugg, cs_note : None } )
4259 }
4360 Ok ( LitKind :: Float ( _, _) ) => {
44- dcx. emit_err ( ConcatBytesInvalid { span, lit_kind : "float" , sugg : None } )
45- }
46- Ok ( LitKind :: Bool ( _) ) => {
47- dcx. emit_err ( ConcatBytesInvalid { span, lit_kind : "boolean" , sugg : None } )
61+ dcx. emit_err ( ConcatBytesInvalid { span, lit_kind : "float" , sugg : None , cs_note : None } )
4862 }
63+ Ok ( LitKind :: Bool ( _) ) => dcx. emit_err ( ConcatBytesInvalid {
64+ span,
65+ lit_kind : "boolean" ,
66+ sugg : None ,
67+ cs_note : None ,
68+ } ) ,
4969 Ok ( LitKind :: Int ( _, _) ) if !is_nested => {
5070 let sugg =
5171 snippet. map ( |snippet| ConcatBytesInvalidSuggestion :: IntLit { span, snippet } ) ;
52- dcx. emit_err ( ConcatBytesInvalid { span, lit_kind : "numeric" , sugg } )
72+ dcx. emit_err ( ConcatBytesInvalid { span, lit_kind : "numeric" , sugg, cs_note : None } )
5373 }
5474 Ok ( LitKind :: Int ( val, LitIntType :: Unsuffixed | LitIntType :: Unsigned ( UintTy :: U8 ) ) ) => {
5575 assert ! ( val. get( ) > u8 :: MAX . into( ) ) ; // must be an error
0 commit comments