@@ -1165,17 +1165,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
11651165 ///
11661166 /// This is really an internal helper. From outside the coercion
11671167 /// module, you should instantiate a `CoerceMany` instance.
1168- fn try_find_coercion_lub < E > (
1168+ fn try_find_coercion_lub (
11691169 & self ,
11701170 cause : & ObligationCause < ' tcx > ,
1171- exprs : & [ E ] ,
1171+ exprs : & [ & ' tcx hir :: Expr < ' tcx > ] ,
11721172 prev_ty : Ty < ' tcx > ,
11731173 new : & hir:: Expr < ' _ > ,
11741174 new_ty : Ty < ' tcx > ,
1175- ) -> RelateResult < ' tcx , Ty < ' tcx > >
1176- where
1177- E : AsCoercionSite ,
1178- {
1175+ ) -> RelateResult < ' tcx , Ty < ' tcx > > {
11791176 let prev_ty = self . try_structurally_resolve_type ( cause. span , prev_ty) ;
11801177 let new_ty = self . try_structurally_resolve_type ( new. span , new_ty) ;
11811178 debug ! (
@@ -1269,7 +1266,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
12691266 ty:: FnDef ( ..) => Adjust :: Pointer ( PointerCoercion :: ReifyFnPointer ( sig. safety ( ) ) ) ,
12701267 _ => span_bug ! ( new. span, "should not try to coerce a {new_ty} to a fn pointer" ) ,
12711268 } ;
1272- for expr in exprs. iter ( ) . map ( |e| e . as_coercion_site ( ) ) {
1269+ for expr in exprs. iter ( ) {
12731270 self . apply_adjustments (
12741271 expr,
12751272 vec ! [ Adjustment { kind: prev_adjustment. clone( ) , target: fn_ptr } ] ,
@@ -1316,7 +1313,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
13161313
13171314 let ( adjustments, target) = self . register_infer_ok_obligations ( ok) ;
13181315 for expr in exprs {
1319- let expr = expr. as_coercion_site ( ) ;
13201316 self . apply_adjustments ( expr, adjustments. clone ( ) ) ;
13211317 }
13221318 debug ! (
@@ -1382,41 +1378,23 @@ pub fn can_coerce<'tcx>(
13821378/// }
13831379/// let final_ty = coerce.complete(fcx);
13841380/// ```
1385- pub ( crate ) struct CoerceMany < ' tcx , ' exprs , E : AsCoercionSite > {
1381+ pub ( crate ) struct CoerceMany < ' tcx > {
13861382 expected_ty : Ty < ' tcx > ,
13871383 final_ty : Option < Ty < ' tcx > > ,
1388- expressions : Expressions < ' tcx , ' exprs , E > ,
1389- pushed : usize ,
1390- }
1391-
1392- /// The type of a `CoerceMany` that is storing up the expressions into
1393- /// a buffer. We use this in `check/mod.rs` for things like `break`.
1394- pub ( crate ) type DynamicCoerceMany < ' tcx > = CoerceMany < ' tcx , ' tcx , & ' tcx hir:: Expr < ' tcx > > ;
1395-
1396- enum Expressions < ' tcx , ' exprs , E : AsCoercionSite > {
1397- Dynamic ( Vec < & ' tcx hir:: Expr < ' tcx > > ) ,
1398- UpFront ( & ' exprs [ E ] ) ,
1384+ expressions : Vec < & ' tcx hir:: Expr < ' tcx > > ,
13991385}
14001386
1401- impl < ' tcx , ' exprs , E : AsCoercionSite > CoerceMany < ' tcx , ' exprs , E > {
1402- /// The usual case; collect the set of expressions dynamically.
1403- /// If the full set of coercion sites is known before hand,
1404- /// consider `with_coercion_sites()` instead to avoid allocation.
1387+ impl < ' tcx > CoerceMany < ' tcx > {
1388+ /// Creates a `CoerceMany` with a default capacity of 1. If the full set of
1389+ /// coercion sites is known before hand, consider `with_capacity()` instead
1390+ /// to avoid allocation.
14051391 pub ( crate ) fn new ( expected_ty : Ty < ' tcx > ) -> Self {
1406- Self :: make ( expected_ty, Expressions :: Dynamic ( vec ! [ ] ) )
1392+ Self :: with_capacity ( expected_ty, 1 )
14071393 }
14081394
1409- /// As an optimization, you can create a `CoerceMany` with a
1410- /// preexisting slice of expressions. In this case, you are
1411- /// expected to pass each element in the slice to `coerce(...)` in
1412- /// order. This is used with arrays in particular to avoid
1413- /// needlessly cloning the slice.
1414- pub ( crate ) fn with_coercion_sites ( expected_ty : Ty < ' tcx > , coercion_sites : & ' exprs [ E ] ) -> Self {
1415- Self :: make ( expected_ty, Expressions :: UpFront ( coercion_sites) )
1416- }
1417-
1418- fn make ( expected_ty : Ty < ' tcx > , expressions : Expressions < ' tcx , ' exprs , E > ) -> Self {
1419- CoerceMany { expected_ty, final_ty : None , expressions, pushed : 0 }
1395+ /// Creates a `CoerceMany` with a given capacity.
1396+ pub ( crate ) fn with_capacity ( expected_ty : Ty < ' tcx > , capacity : usize ) -> Self {
1397+ CoerceMany { expected_ty, final_ty : None , expressions : Vec :: with_capacity ( capacity) }
14201398 }
14211399
14221400 /// Returns the "expected type" with which this coercion was
@@ -1529,7 +1507,7 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> {
15291507
15301508 // Handle the actual type unification etc.
15311509 let result = if let Some ( expression) = expression {
1532- if self . pushed == 0 {
1510+ if self . expressions . is_empty ( ) {
15331511 // Special-case the first expression we are coercing.
15341512 // To be honest, I'm not entirely sure why we do this.
15351513 // We don't allow two-phase borrows, see comment in try_find_coercion_lub for why
@@ -1541,22 +1519,13 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> {
15411519 Some ( cause. clone ( ) ) ,
15421520 )
15431521 } else {
1544- match self . expressions {
1545- Expressions :: Dynamic ( ref exprs) => fcx. try_find_coercion_lub (
1546- cause,
1547- exprs,
1548- self . merged_ty ( ) ,
1549- expression,
1550- expression_ty,
1551- ) ,
1552- Expressions :: UpFront ( coercion_sites) => fcx. try_find_coercion_lub (
1553- cause,
1554- & coercion_sites[ 0 ..self . pushed ] ,
1555- self . merged_ty ( ) ,
1556- expression,
1557- expression_ty,
1558- ) ,
1559- }
1522+ fcx. try_find_coercion_lub (
1523+ cause,
1524+ & self . expressions ,
1525+ self . merged_ty ( ) ,
1526+ expression,
1527+ expression_ty,
1528+ )
15601529 }
15611530 } else {
15621531 // this is a hack for cases where we default to `()` because
@@ -1591,18 +1560,7 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> {
15911560 Ok ( v) => {
15921561 self . final_ty = Some ( v) ;
15931562 if let Some ( e) = expression {
1594- match self . expressions {
1595- Expressions :: Dynamic ( ref mut buffer) => buffer. push ( e) ,
1596- Expressions :: UpFront ( coercion_sites) => {
1597- // if the user gave us an array to validate, check that we got
1598- // the next expression in the list, as expected
1599- assert_eq ! (
1600- coercion_sites[ self . pushed] . as_coercion_site( ) . hir_id,
1601- e. hir_id
1602- ) ;
1603- }
1604- }
1605- self . pushed += 1 ;
1563+ self . expressions . push ( e) ;
16061564 }
16071565 }
16081566 Err ( coercion_error) => {
@@ -1955,45 +1913,12 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> {
19551913 } else {
19561914 // If we only had inputs that were of type `!` (or no
19571915 // inputs at all), then the final type is `!`.
1958- assert_eq ! ( self . pushed , 0 ) ;
1916+ assert ! ( self . expressions . is_empty ( ) ) ;
19591917 fcx. tcx . types . never
19601918 }
19611919 }
19621920}
19631921
1964- /// Something that can be converted into an expression to which we can
1965- /// apply a coercion.
1966- pub ( crate ) trait AsCoercionSite {
1967- fn as_coercion_site ( & self ) -> & hir:: Expr < ' _ > ;
1968- }
1969-
1970- impl AsCoercionSite for hir:: Expr < ' _ > {
1971- fn as_coercion_site ( & self ) -> & hir:: Expr < ' _ > {
1972- self
1973- }
1974- }
1975-
1976- impl < ' a , T > AsCoercionSite for & ' a T
1977- where
1978- T : AsCoercionSite ,
1979- {
1980- fn as_coercion_site ( & self ) -> & hir:: Expr < ' _ > {
1981- ( * * self ) . as_coercion_site ( )
1982- }
1983- }
1984-
1985- impl AsCoercionSite for ! {
1986- fn as_coercion_site ( & self ) -> & hir:: Expr < ' _ > {
1987- * self
1988- }
1989- }
1990-
1991- impl AsCoercionSite for hir:: Arm < ' _ > {
1992- fn as_coercion_site ( & self ) -> & hir:: Expr < ' _ > {
1993- self . body
1994- }
1995- }
1996-
19971922/// Recursively visit goals to decide whether an unsizing is possible.
19981923/// `Break`s when it isn't, and an error should be raised.
19991924/// `Continue`s when an unsizing ok based on an implementation of the `Unsize` trait / lang item.
0 commit comments