@@ -102,7 +102,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
102102 // While we don't allow *arbitrary* coercions here, we *do* allow
103103 // coercions from ! to `expected`.
104104 if self . try_structurally_resolve_type ( expr. span , ty) . is_never ( )
105- && self . expr_guaranteed_to_constitute_read_for_never ( expr)
105+ && self . tcx . expr_guaranteed_to_constitute_read_for_never ( expr)
106106 {
107107 if let Some ( adjustments) = self . typeck_results . borrow ( ) . adjustments ( ) . get ( expr. hir_id ) {
108108 let reported = self . dcx ( ) . span_delayed_bug (
@@ -320,7 +320,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
320320 // diverging would be unsound since we may never actually read the `!`.
321321 // e.g. `let _ = *never_ptr;` with `never_ptr: *const !`.
322322 if self . try_structurally_resolve_type ( expr. span , ty) . is_never ( )
323- && self . expr_guaranteed_to_constitute_read_for_never ( expr)
323+ && self . tcx . expr_guaranteed_to_constitute_read_for_never ( expr)
324324 {
325325 self . diverges . set ( self . diverges . get ( ) | Diverges :: always ( expr. span ) ) ;
326326 }
@@ -339,199 +339,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
339339 ty
340340 }
341341
342- /// Whether this expression constitutes a read of value of the type that
343- /// it evaluates to.
344- ///
345- /// This is used to determine if we should consider the block to diverge
346- /// if the expression evaluates to `!`, and if we should insert a `NeverToAny`
347- /// coercion for values of type `!`.
348- ///
349- /// This function generally returns `false` if the expression is a place
350- /// expression and the *parent* expression is the scrutinee of a match or
351- /// the pointee of an `&` addr-of expression, since both of those parent
352- /// expressions take a *place* and not a value.
353- pub ( super ) fn expr_guaranteed_to_constitute_read_for_never (
354- & self ,
355- expr : & ' tcx hir:: Expr < ' tcx > ,
356- ) -> bool {
357- // We only care about place exprs. Anything else returns an immediate
358- // which would constitute a read. We don't care about distinguishing
359- // "syntactic" place exprs since if the base of a field projection is
360- // not a place then it would've been UB to read from it anyways since
361- // that constitutes a read.
362- if !expr. is_syntactic_place_expr ( ) {
363- return true ;
364- }
365-
366- let parent_node = self . tcx . parent_hir_node ( expr. hir_id ) ;
367- match parent_node {
368- hir:: Node :: Expr ( parent_expr) => {
369- match parent_expr. kind {
370- // Addr-of, field projections, and LHS of assignment don't constitute reads.
371- // Assignment does call `drop_in_place`, though, but its safety
372- // requirements are not the same.
373- ExprKind :: AddrOf ( ..) | hir:: ExprKind :: Field ( ..) => false ,
374-
375- // Place-preserving expressions only constitute reads if their
376- // parent expression constitutes a read.
377- ExprKind :: Type ( ..) | ExprKind :: UnsafeBinderCast ( ..) => {
378- self . expr_guaranteed_to_constitute_read_for_never ( expr)
379- }
380-
381- ExprKind :: Assign ( lhs, _, _) => {
382- // Only the LHS does not constitute a read
383- expr. hir_id != lhs. hir_id
384- }
385-
386- // See note on `PatKind::Or` below for why this is `all`.
387- ExprKind :: Match ( scrutinee, arms, _) => {
388- assert_eq ! ( scrutinee. hir_id, expr. hir_id) ;
389- arms. iter ( )
390- . all ( |arm| self . pat_guaranteed_to_constitute_read_for_never ( arm. pat ) )
391- }
392- ExprKind :: Let ( hir:: LetExpr { init, pat, .. } ) => {
393- assert_eq ! ( init. hir_id, expr. hir_id) ;
394- self . pat_guaranteed_to_constitute_read_for_never ( * pat)
395- }
396-
397- // Any expression child of these expressions constitute reads.
398- ExprKind :: Array ( _)
399- | ExprKind :: Call ( _, _)
400- | ExprKind :: Use ( _, _)
401- | ExprKind :: MethodCall ( _, _, _, _)
402- | ExprKind :: Tup ( _)
403- | ExprKind :: Binary ( _, _, _)
404- | ExprKind :: Unary ( _, _)
405- | ExprKind :: Cast ( _, _)
406- | ExprKind :: DropTemps ( _)
407- | ExprKind :: If ( _, _, _)
408- | ExprKind :: Closure ( _)
409- | ExprKind :: Block ( _, _)
410- | ExprKind :: AssignOp ( _, _, _)
411- | ExprKind :: Index ( _, _, _)
412- | ExprKind :: Break ( _, _)
413- | ExprKind :: Ret ( _)
414- | ExprKind :: Become ( _)
415- | ExprKind :: InlineAsm ( _)
416- | ExprKind :: Struct ( _, _, _)
417- | ExprKind :: Repeat ( _, _)
418- | ExprKind :: Yield ( _, _) => true ,
419-
420- // These expressions have no (direct) sub-exprs.
421- ExprKind :: ConstBlock ( _)
422- | ExprKind :: Loop ( _, _, _, _)
423- | ExprKind :: Lit ( _)
424- | ExprKind :: Path ( _)
425- | ExprKind :: Continue ( _)
426- | ExprKind :: OffsetOf ( _, _)
427- | ExprKind :: Err ( _) => unreachable ! ( "no sub-expr expected for {:?}" , expr. kind) ,
428- }
429- }
430-
431- // If we have a subpattern that performs a read, we want to consider this
432- // to diverge for compatibility to support something like `let x: () = *never_ptr;`.
433- hir:: Node :: LetStmt ( hir:: LetStmt { init : Some ( target) , pat, .. } ) => {
434- assert_eq ! ( target. hir_id, expr. hir_id) ;
435- self . pat_guaranteed_to_constitute_read_for_never ( * pat)
436- }
437-
438- // These nodes (if they have a sub-expr) do constitute a read.
439- hir:: Node :: Block ( _)
440- | hir:: Node :: Arm ( _)
441- | hir:: Node :: ExprField ( _)
442- | hir:: Node :: AnonConst ( _)
443- | hir:: Node :: ConstBlock ( _)
444- | hir:: Node :: ConstArg ( _)
445- | hir:: Node :: Stmt ( _)
446- | hir:: Node :: Item ( hir:: Item {
447- kind : hir:: ItemKind :: Const ( ..) | hir:: ItemKind :: Static ( ..) ,
448- ..
449- } )
450- | hir:: Node :: TraitItem ( hir:: TraitItem {
451- kind : hir:: TraitItemKind :: Const ( ..) , ..
452- } )
453- | hir:: Node :: ImplItem ( hir:: ImplItem { kind : hir:: ImplItemKind :: Const ( ..) , .. } ) => true ,
454-
455- hir:: Node :: TyPat ( _) | hir:: Node :: Pat ( _) => {
456- self . dcx ( ) . span_delayed_bug ( expr. span , "place expr not allowed in pattern" ) ;
457- true
458- }
459-
460- // These nodes do not have direct sub-exprs.
461- hir:: Node :: Param ( _)
462- | hir:: Node :: Item ( _)
463- | hir:: Node :: ForeignItem ( _)
464- | hir:: Node :: TraitItem ( _)
465- | hir:: Node :: ImplItem ( _)
466- | hir:: Node :: Variant ( _)
467- | hir:: Node :: Field ( _)
468- | hir:: Node :: PathSegment ( _)
469- | hir:: Node :: Ty ( _)
470- | hir:: Node :: AssocItemConstraint ( _)
471- | hir:: Node :: TraitRef ( _)
472- | hir:: Node :: PatField ( _)
473- | hir:: Node :: PatExpr ( _)
474- | hir:: Node :: LetStmt ( _)
475- | hir:: Node :: Synthetic
476- | hir:: Node :: Err ( _)
477- | hir:: Node :: Ctor ( _)
478- | hir:: Node :: Lifetime ( _)
479- | hir:: Node :: GenericParam ( _)
480- | hir:: Node :: Crate ( _)
481- | hir:: Node :: Infer ( _)
482- | hir:: Node :: WherePredicate ( _)
483- | hir:: Node :: PreciseCapturingNonLifetimeArg ( _)
484- | hir:: Node :: OpaqueTy ( _) => {
485- unreachable ! ( "no sub-expr expected for {parent_node:?}" )
486- }
487- }
488- }
489-
490- /// Whether this pattern constitutes a read of value of the scrutinee that
491- /// it is matching against. This is used to determine whether we should
492- /// perform `NeverToAny` coercions.
493- ///
494- /// See above for the nuances of what happens when this returns true.
495- pub ( super ) fn pat_guaranteed_to_constitute_read_for_never ( & self , pat : & hir:: Pat < ' _ > ) -> bool {
496- match pat. kind {
497- // Does not constitute a read.
498- hir:: PatKind :: Wild => false ,
499-
500- // Might not constitute a read, since the condition might be false.
501- hir:: PatKind :: Guard ( _, _) => true ,
502-
503- // This is unnecessarily restrictive when the pattern that doesn't
504- // constitute a read is unreachable.
505- //
506- // For example `match *never_ptr { value => {}, _ => {} }` or
507- // `match *never_ptr { _ if false => {}, value => {} }`.
508- //
509- // It is however fine to be restrictive here; only returning `true`
510- // can lead to unsoundness.
511- hir:: PatKind :: Or ( subpats) => {
512- subpats. iter ( ) . all ( |pat| self . pat_guaranteed_to_constitute_read_for_never ( pat) )
513- }
514-
515- // Does constitute a read, since it is equivalent to a discriminant read.
516- hir:: PatKind :: Never => true ,
517-
518- // All of these constitute a read, or match on something that isn't `!`,
519- // which would require a `NeverToAny` coercion.
520- hir:: PatKind :: Missing
521- | hir:: PatKind :: Binding ( _, _, _, _)
522- | hir:: PatKind :: Struct ( _, _, _)
523- | hir:: PatKind :: TupleStruct ( _, _, _)
524- | hir:: PatKind :: Tuple ( _, _)
525- | hir:: PatKind :: Box ( _)
526- | hir:: PatKind :: Ref ( _, _, _)
527- | hir:: PatKind :: Deref ( _)
528- | hir:: PatKind :: Expr ( _)
529- | hir:: PatKind :: Range ( _, _, _)
530- | hir:: PatKind :: Slice ( _, _, _)
531- | hir:: PatKind :: Err ( _) => true ,
532- }
533- }
534-
535342 #[ instrument( skip( self , expr) , level = "debug" ) ]
536343 fn check_expr_kind (
537344 & self ,
0 commit comments