|
1 | 1 | use alloc::{
|
2 | 2 | borrow::ToOwned,
|
3 | 3 | boxed::Box,
|
| 4 | + format, |
4 | 5 | string::{String, ToString},
|
5 | 6 | vec::Vec,
|
6 | 7 | };
|
@@ -2483,12 +2484,70 @@ impl<'source, 'temp> Lowerer<'source, 'temp> {
|
2483 | 2484 | "select" => {
|
2484 | 2485 | let mut args = ctx.prepare_args(arguments, 3, span);
|
2485 | 2486 |
|
2486 |
| - let reject = self.expression(args.next()?, ctx)?; |
2487 |
| - let accept = self.expression(args.next()?, ctx)?; |
| 2487 | + let reject_orig = args.next()?; |
| 2488 | + let accept_orig = args.next()?; |
| 2489 | + let mut values = [ |
| 2490 | + self.expression_for_abstract(reject_orig, ctx)?, |
| 2491 | + self.expression_for_abstract(accept_orig, ctx)?, |
| 2492 | + ]; |
2488 | 2493 | let condition = self.expression(args.next()?, ctx)?;
|
2489 | 2494 |
|
2490 | 2495 | args.finish()?;
|
2491 | 2496 |
|
| 2497 | + fn expr_ty<'a>( |
| 2498 | + ctx: &'a ExpressionContext<'_, '_, '_>, |
| 2499 | + expr: Handle<ir::Expression>, |
| 2500 | + ) -> &'a ir::TypeInner { |
| 2501 | + ctx.typifier()[expr].inner_with(&ctx.module.types) |
| 2502 | + } |
| 2503 | + let diag_deets = |
| 2504 | + |module: &ir::Module, ty: &ir::TypeInner, orig_expr| { |
| 2505 | + ( |
| 2506 | + ctx.ast_expressions.get_span(orig_expr), |
| 2507 | + format!("`{:?}`", ty.for_debug(&module.types)), |
| 2508 | + ) |
| 2509 | + }; |
| 2510 | + for (&value, orig_value) in |
| 2511 | + values.iter().zip([reject_orig, accept_orig]) |
| 2512 | + { |
| 2513 | + ctx.grow_types(value)?; |
| 2514 | + |
| 2515 | + let value_type = expr_ty(ctx, value); |
| 2516 | + if value_type.vector_size_and_scalar().is_none() { |
| 2517 | + let (arg_span, arg_type) = |
| 2518 | + diag_deets(ctx.module, value_type, orig_value); |
| 2519 | + return Err(Box::new(Error::SelectUnexpectedArgumentType { |
| 2520 | + arg_span, |
| 2521 | + arg_type, |
| 2522 | + })); |
| 2523 | + } |
| 2524 | + } |
| 2525 | + let mut consensus_scalar = ctx |
| 2526 | + .automatic_conversion_consensus(&values) |
| 2527 | + .map_err(|_idx| { |
| 2528 | + let [reject, accept] = values; |
| 2529 | + let [(reject_span, reject_type), (accept_span, accept_type)] = |
| 2530 | + [(reject_orig, reject), (accept_orig, accept)].map( |
| 2531 | + |(orig_expr, expr)| { |
| 2532 | + let ty = expr_ty(ctx, expr); |
| 2533 | + diag_deets(ctx.module, ty, orig_expr) |
| 2534 | + }, |
| 2535 | + ); |
| 2536 | + Error::SelectRejectAndAcceptHaveNoCommonType { |
| 2537 | + reject_span, |
| 2538 | + reject_type, |
| 2539 | + accept_span, |
| 2540 | + accept_type, |
| 2541 | + } |
| 2542 | + })?; |
| 2543 | + if !ctx.is_const(condition) { |
| 2544 | + consensus_scalar = consensus_scalar.concretize(); |
| 2545 | + } |
| 2546 | + |
| 2547 | + ctx.convert_slice_to_common_leaf_scalar(&mut values, consensus_scalar)?; |
| 2548 | + |
| 2549 | + let [reject, accept] = values; |
| 2550 | + |
2492 | 2551 | ir::Expression::Select {
|
2493 | 2552 | reject,
|
2494 | 2553 | accept,
|
|
0 commit comments