@@ -14,8 +14,9 @@ use crate::{
1414 consteval:: intern_const_scalar,
1515 infer:: { BindingMode , Expectation , InferenceContext , TypeMismatch } ,
1616 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 ,
1920} ;
2021
2122use super :: PatLike ;
@@ -294,7 +295,29 @@ impl<'a> InferenceContext<'a> {
294295 let start_ty = self . infer_expr ( * start, & Expectation :: has_type ( expected. clone ( ) ) ) ;
295296 self . infer_expr ( * end, & Expectation :: has_type ( start_ty) )
296297 }
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+ }
298321 Pat :: Box { inner } => match self . resolve_boxed_box ( ) {
299322 Some ( box_adt) => {
300323 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 {
343366 // FIXME: ConstBlock/Path/Lit might actually evaluate to ref, but inference is unimplemented.
344367 Pat :: Path ( ..) => true ,
345368 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+ }
347372 Pat :: Bind {
348373 mode : BindingAnnotation :: Mutable | BindingAnnotation :: Unannotated ,
349374 subpat : Some ( subpat) ,
0 commit comments