@@ -14,8 +14,9 @@ use crate::{
14
14
consteval:: intern_const_scalar,
15
15
infer:: { BindingMode , Expectation , InferenceContext , TypeMismatch } ,
16
16
lower:: lower_to_chalk_mutability,
17
- static_lifetime, ConcreteConst , ConstValue , Interner , Substitution , Ty , TyBuilder , TyExt ,
18
- TyKind ,
17
+ primitive:: UintTy ,
18
+ static_lifetime, ConcreteConst , ConstValue , Interner , Scalar , Substitution , Ty , TyBuilder ,
19
+ TyExt , TyKind ,
19
20
} ;
20
21
21
22
use super :: PatLike ;
@@ -294,7 +295,29 @@ impl<'a> InferenceContext<'a> {
294
295
let start_ty = self . infer_expr ( * start, & Expectation :: has_type ( expected. clone ( ) ) ) ;
295
296
self . infer_expr ( * end, & Expectation :: has_type ( start_ty) )
296
297
}
297
- Pat :: Lit ( expr) => self . infer_expr ( * expr, & Expectation :: has_type ( expected. clone ( ) ) ) ,
298
+ & Pat :: Lit ( expr) => {
299
+ // FIXME: using `Option` here is a workaround until we can use if-let chains in stable.
300
+ let mut pat_ty = None ;
301
+
302
+ // Like slice patterns, byte string patterns can denote both `&[u8; N]` and `&[u8]`.
303
+ if let Expr :: Literal ( Literal :: ByteString ( _) ) = self . body [ expr] {
304
+ if let Some ( ( inner, ..) ) = expected. as_reference ( ) {
305
+ let inner = self . resolve_ty_shallow ( inner) ;
306
+ if matches ! ( inner. kind( Interner ) , TyKind :: Slice ( _) ) {
307
+ let elem_ty = TyKind :: Scalar ( Scalar :: Uint ( UintTy :: U8 ) ) . intern ( Interner ) ;
308
+ let slice_ty = TyKind :: Slice ( elem_ty) . intern ( Interner ) ;
309
+ let ty = TyKind :: Ref ( Mutability :: Not , static_lifetime ( ) , slice_ty)
310
+ . intern ( Interner ) ;
311
+ self . write_expr_ty ( expr, ty. clone ( ) ) ;
312
+ pat_ty = Some ( ty) ;
313
+ }
314
+ }
315
+ }
316
+
317
+ pat_ty. unwrap_or_else ( || {
318
+ self . infer_expr ( expr, & Expectation :: has_type ( expected. clone ( ) ) )
319
+ } )
320
+ }
298
321
Pat :: Box { inner } => match self . resolve_boxed_box ( ) {
299
322
Some ( box_adt) => {
300
323
let ( inner_ty, alloc_ty) = match expected. as_adt ( ) {
@@ -343,7 +366,9 @@ fn is_non_ref_pat(body: &hir_def::body::Body, pat: PatId) -> bool {
343
366
// FIXME: ConstBlock/Path/Lit might actually evaluate to ref, but inference is unimplemented.
344
367
Pat :: Path ( ..) => true ,
345
368
Pat :: ConstBlock ( ..) => true ,
346
- Pat :: Lit ( expr) => !matches ! ( body[ * expr] , Expr :: Literal ( Literal :: String ( ..) ) ) ,
369
+ Pat :: Lit ( expr) => {
370
+ !matches ! ( body[ * expr] , Expr :: Literal ( Literal :: String ( ..) | Literal :: ByteString ( ..) ) )
371
+ }
347
372
Pat :: Bind {
348
373
mode : BindingAnnotation :: Mutable | BindingAnnotation :: Unannotated ,
349
374
subpat : Some ( subpat) ,
0 commit comments