[validator] Fix return statement type validation for aliases

Unwrap type aliases from the function return type before comparing to
the return value.

Add additional test coverage for aliased and non-aliased cases.

Change-Id: I4aa43f681468cd2c68e84da71222aea952117c1a
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/44923
Commit-Queue: Antonio Maiorano <amaiorano@google.com>
Auto-Submit: James Price <jrprice@google.com>
Reviewed-by: Antonio Maiorano <amaiorano@google.com>
diff --git a/src/validator/validator_function_test.cc b/src/validator/validator_function_test.cc
index e939da4..aa47060 100644
--- a/src/validator/validator_function_test.cc
+++ b/src/validator/validator_function_test.cc
@@ -122,6 +122,24 @@
             "return type, returned '__i32', expected '__void'");
 }
 
+TEST_F(ValidateFunctionTest, FunctionTypeMustMatchReturnStatementTypeF32_pass) {
+  // fn func -> f32 { return 2.0; }
+  Func("func", ast::VariableList{}, ty.f32(),
+       ast::StatementList{
+           create<ast::ReturnStatement>(Source{Source::Location{12, 34}},
+                                        Expr(2.f)),
+       },
+       ast::DecorationList{});
+  Func("main", ast::VariableList{}, ty.void_(), ast::StatementList{},
+       ast::DecorationList{
+           create<ast::StageDecoration>(ast::PipelineStage::kVertex),
+       });
+
+  ValidatorImpl& v = Build();
+
+  EXPECT_TRUE(v.Validate());
+}
+
 TEST_F(ValidateFunctionTest, FunctionTypeMustMatchReturnStatementTypeF32_fail) {
   // fn func -> f32 { return 2; }
   Func("func", ast::VariableList{}, ty.f32(),
@@ -140,6 +158,52 @@
             "return type, returned '__i32', expected '__f32'");
 }
 
+TEST_F(ValidateFunctionTest,
+       FunctionTypeMustMatchReturnStatementTypeF32Alias_pass) {
+  // type myf32 = f32;
+  // fn func -> myf32 { return 2.0; }
+  auto* myf32 = ty.alias("myf32", ty.f32());
+  Func("func", ast::VariableList{}, myf32,
+       ast::StatementList{
+           create<ast::ReturnStatement>(Source{Source::Location{12, 34}},
+                                        Expr(2.f)),
+       },
+       ast::DecorationList{});
+  Func("main", ast::VariableList{}, ty.void_(), ast::StatementList{},
+       ast::DecorationList{
+           create<ast::StageDecoration>(ast::PipelineStage::kVertex),
+       });
+
+  ValidatorImpl& v = Build();
+
+  EXPECT_TRUE(v.Validate());
+}
+
+TEST_F(ValidateFunctionTest,
+       FunctionTypeMustMatchReturnStatementTypeF32Alias_fail) {
+  // type myf32 = f32;
+  // fn func -> myf32 { return 2; }
+  auto* myf32 = ty.alias("myf32", ty.f32());
+  Func("func", ast::VariableList{}, myf32,
+       ast::StatementList{
+           create<ast::ReturnStatement>(Source{Source::Location{12, 34}},
+                                        Expr(2u)),
+       },
+       ast::DecorationList{});
+  Func("main", ast::VariableList{}, ty.void_(), ast::StatementList{},
+       ast::DecorationList{
+           create<ast::StageDecoration>(ast::PipelineStage::kVertex),
+       });
+
+  ValidatorImpl& v = Build();
+
+  EXPECT_FALSE(v.Validate());
+  EXPECT_EQ(
+      v.error(),
+      "12:34 v-000y: return statement type must match its function "
+      "return type, returned '__u32', expected '__alias_tint_symbol_1__f32'");
+}
+
 TEST_F(ValidateFunctionTest, FunctionNamesMustBeUnique_fail) {
   // fn func -> i32 { return 2; }
   // fn func -> i32 { return 2; }
diff --git a/src/validator/validator_impl.cc b/src/validator/validator_impl.cc
index 3a957d4..add2fc1 100644
--- a/src/validator/validator_impl.cc
+++ b/src/validator/validator_impl.cc
@@ -287,7 +287,7 @@
                        ? program_->Sem().Get(ret->value())->Type()->UnwrapAll()
                        : &void_type;
 
-  if (func_type->type_name() != ret_type->type_name()) {
+  if (func_type->UnwrapAll()->type_name() != ret_type->type_name()) {
     add_error(ret->source(), "v-000y",
               "return statement type must match its function return "
               "type, returned '" +