1
1
use rustc_ast:: ptr:: P ;
2
2
use rustc_ast:: tokenstream:: TokenStream ;
3
- use rustc_ast:: { ExprKind , LitIntType , LitKind , UintTy , token} ;
3
+ use rustc_ast:: { ExprKind , LitIntType , LitKind , StrStyle , UintTy , token} ;
4
4
use rustc_expand:: base:: { DummyResult , ExpandResult , ExtCtxt , MacEager , MacroExpanderResult } ;
5
5
use rustc_session:: errors:: report_lit_error;
6
6
use rustc_span:: { ErrorGuaranteed , Span } ;
@@ -21,15 +21,32 @@ fn invalid_type_err(
21
21
let snippet = cx. sess . source_map ( ) . span_to_snippet ( span) . ok ( ) ;
22
22
let dcx = cx. dcx ( ) ;
23
23
match LitKind :: from_token_lit ( token_lit) {
24
- Ok ( LitKind :: CStr ( _, _ ) ) => {
24
+ Ok ( LitKind :: CStr ( _, style ) ) => {
25
25
// Avoid ambiguity in handling of terminal `NUL` by refusing to
26
26
// 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 ( ( ) ) } )
28
45
}
29
46
Ok ( LitKind :: Char ( _) ) => {
30
47
let sugg =
31
48
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 } )
33
50
}
34
51
Ok ( LitKind :: Str ( _, _) ) => {
35
52
// suggestion would be invalid if we are nested
@@ -38,18 +55,21 @@ fn invalid_type_err(
38
55
} else {
39
56
None
40
57
} ;
41
- dcx. emit_err ( ConcatBytesInvalid { span, lit_kind : "string" , sugg } )
58
+ dcx. emit_err ( ConcatBytesInvalid { span, lit_kind : "string" , sugg, cs_note : None } )
42
59
}
43
60
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 } )
48
62
}
63
+ Ok ( LitKind :: Bool ( _) ) => dcx. emit_err ( ConcatBytesInvalid {
64
+ span,
65
+ lit_kind : "boolean" ,
66
+ sugg : None ,
67
+ cs_note : None ,
68
+ } ) ,
49
69
Ok ( LitKind :: Int ( _, _) ) if !is_nested => {
50
70
let sugg =
51
71
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 } )
53
73
}
54
74
Ok ( LitKind :: Int ( val, LitIntType :: Unsuffixed | LitIntType :: Unsigned ( UintTy :: U8 ) ) ) => {
55
75
assert ! ( val. get( ) > u8 :: MAX . into( ) ) ; // must be an error
0 commit comments