Constify Type* constructor args for ast/sem classes

To avoid breaking things, functions that return the type cast away
the constness for now. This, however, makes it easier to use typ::Type
with these classes, as typ::Type stores pointers to const types. This
also brings us one step closer to constifying types everywhere.

Bug: tint:724
Change-Id: Ia3f4b76f375184dd09b8041c1f60bf1afaefe629
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/48740
Commit-Queue: Antonio Maiorano <amaiorano@google.com>
Reviewed-by: Ben Clayton <bclayton@google.com>
diff --git a/src/ast/access_control.cc b/src/ast/access_control.cc
index 0c1c1d3..635eeb6 100644
--- a/src/ast/access_control.cc
+++ b/src/ast/access_control.cc
@@ -24,7 +24,7 @@
 AccessControl::AccessControl(ProgramID program_id,
                              const Source& source,
                              Access access,
-                             Type* subtype)
+                             const Type* subtype)
     : Base(program_id, source), access_(access), subtype_(subtype) {
   TINT_ASSERT(subtype_);
   TINT_ASSERT(!subtype_->Is<AccessControl>());
diff --git a/src/ast/access_control.h b/src/ast/access_control.h
index 106b31e..08c6db1 100644
--- a/src/ast/access_control.h
+++ b/src/ast/access_control.h
@@ -44,7 +44,7 @@
   AccessControl(ProgramID program_id,
                 const Source& source,
                 Access access,
-                Type* subtype);
+                const Type* subtype);
   /// Move constructor
   AccessControl(AccessControl&&);
   ~AccessControl() override;
@@ -59,7 +59,7 @@
   /// @returns the access control value
   Access access_control() const { return access_; }
   /// @returns the subtype type
-  Type* type() const { return subtype_; }
+  Type* type() const { return const_cast<Type*>(subtype_); }
 
   /// @returns the name for this type
   std::string type_name() const override;
@@ -76,7 +76,7 @@
 
  private:
   Access const access_;
-  Type* const subtype_;
+  const Type* const subtype_;
 };
 
 /// @param out the std::ostream to write to
diff --git a/src/ast/bitcast_expression.cc b/src/ast/bitcast_expression.cc
index a39870b..5a11e5c 100644
--- a/src/ast/bitcast_expression.cc
+++ b/src/ast/bitcast_expression.cc
@@ -23,7 +23,7 @@
 
 BitcastExpression::BitcastExpression(ProgramID program_id,
                                      const Source& source,
-                                     sem::Type* type,
+                                     const sem::Type* type,
                                      Expression* expr)
     : Base(program_id, source), type_(type), expr_(expr) {
   TINT_ASSERT(type_);
@@ -37,7 +37,7 @@
 BitcastExpression* BitcastExpression::Clone(CloneContext* ctx) const {
   // Clone arguments outside of create() call to have deterministic ordering
   auto src = ctx->Clone(source());
-  auto* ty = ctx->Clone(type_);
+  auto* ty = ctx->Clone(type());
   auto* e = ctx->Clone(expr_);
   return ctx->dst->create<BitcastExpression>(src, ty, e);
 }
diff --git a/src/ast/bitcast_expression.h b/src/ast/bitcast_expression.h
index 6b6cc2b..75a5a7a 100644
--- a/src/ast/bitcast_expression.h
+++ b/src/ast/bitcast_expression.h
@@ -30,14 +30,14 @@
   /// @param expr the expr
   BitcastExpression(ProgramID program_id,
                     const Source& source,
-                    sem::Type* type,
+                    const sem::Type* type,
                     Expression* expr);
   /// Move constructor
   BitcastExpression(BitcastExpression&&);
   ~BitcastExpression() override;
 
   /// @returns the left side expression
-  sem::Type* type() const { return type_; }
+  sem::Type* type() const { return const_cast<sem::Type*>(type_); }
   /// @returns the expression
   Expression* expr() const { return expr_; }
 
@@ -58,7 +58,7 @@
  private:
   BitcastExpression(const BitcastExpression&) = delete;
 
-  sem::Type* const type_;
+  const sem::Type* const type_;
   Expression* const expr_;
 };
 
diff --git a/src/ast/bool_literal.cc b/src/ast/bool_literal.cc
index b264c4a..097ea15 100644
--- a/src/ast/bool_literal.cc
+++ b/src/ast/bool_literal.cc
@@ -23,7 +23,7 @@
 
 BoolLiteral::BoolLiteral(ProgramID program_id,
                          const Source& source,
-                         sem::Type* type,
+                         const sem::Type* type,
                          bool value)
     : Base(program_id, source, type), value_(value) {}
 
diff --git a/src/ast/bool_literal.h b/src/ast/bool_literal.h
index 4f2fce1..72c44fe 100644
--- a/src/ast/bool_literal.h
+++ b/src/ast/bool_literal.h
@@ -32,7 +32,7 @@
   /// @param value the bool literals value
   BoolLiteral(ProgramID program_id,
               const Source& source,
-              sem::Type* type,
+              const sem::Type* type,
               bool value);
   ~BoolLiteral() override;
 
diff --git a/src/ast/float_literal.cc b/src/ast/float_literal.cc
index b23742c..9089289 100644
--- a/src/ast/float_literal.cc
+++ b/src/ast/float_literal.cc
@@ -25,7 +25,7 @@
 
 FloatLiteral::FloatLiteral(ProgramID program_id,
                            const Source& source,
-                           sem::Type* type,
+                           const sem::Type* type,
                            float value)
     : Base(program_id, source, type), value_(value) {}
 
diff --git a/src/ast/float_literal.h b/src/ast/float_literal.h
index 9d03093..05ddbfc 100644
--- a/src/ast/float_literal.h
+++ b/src/ast/float_literal.h
@@ -32,7 +32,7 @@
   /// @param value the float literals value
   FloatLiteral(ProgramID program_id,
                const Source& source,
-               sem::Type* type,
+               const sem::Type* type,
                float value);
   ~FloatLiteral() override;
 
diff --git a/src/ast/int_literal.cc b/src/ast/int_literal.cc
index b959e0a..c35b923 100644
--- a/src/ast/int_literal.cc
+++ b/src/ast/int_literal.cc
@@ -21,7 +21,7 @@
 
 IntLiteral::IntLiteral(ProgramID program_id,
                        const Source& source,
-                       sem::Type* type,
+                       const sem::Type* type,
                        uint32_t value)
     : Base(program_id, source, type), value_(value) {}
 
diff --git a/src/ast/int_literal.h b/src/ast/int_literal.h
index 5aca29e..3a23a7c 100644
--- a/src/ast/int_literal.h
+++ b/src/ast/int_literal.h
@@ -36,7 +36,7 @@
   /// @param value value of the literal
   IntLiteral(ProgramID program_id,
              const Source& source,
-             sem::Type* type,
+             const sem::Type* type,
              uint32_t value);
 
  private:
diff --git a/src/ast/literal.cc b/src/ast/literal.cc
index bea8d6c..dd632bd 100644
--- a/src/ast/literal.cc
+++ b/src/ast/literal.cc
@@ -19,7 +19,9 @@
 namespace tint {
 namespace ast {
 
-Literal::Literal(ProgramID program_id, const Source& source, sem::Type* type)
+Literal::Literal(ProgramID program_id,
+                 const Source& source,
+                 const sem::Type* type)
     : Base(program_id, source), type_(type) {}
 
 Literal::~Literal() = default;
diff --git a/src/ast/literal.h b/src/ast/literal.h
index 6ea656b..1351f00 100644
--- a/src/ast/literal.h
+++ b/src/ast/literal.h
@@ -28,7 +28,7 @@
   ~Literal() override;
 
   /// @returns the type of the literal
-  sem::Type* type() const { return type_; }
+  sem::Type* type() const { return const_cast<sem::Type*>(type_); }
 
   /// Writes a representation of the node to the output stream
   /// @param sem the semantic info for the program
@@ -50,10 +50,12 @@
   /// @param program_id the identifier of the program that owns this node
   /// @param source the input source
   /// @param type the type of the literal
-  explicit Literal(ProgramID program_id, const Source& source, sem::Type* type);
+  explicit Literal(ProgramID program_id,
+                   const Source& source,
+                   const sem::Type* type);
 
  private:
-  sem::Type* const type_;
+  const sem::Type* const type_;
 };
 
 }  // namespace ast
diff --git a/src/ast/sint_literal.cc b/src/ast/sint_literal.cc
index 7d3c151..c3e0a16 100644
--- a/src/ast/sint_literal.cc
+++ b/src/ast/sint_literal.cc
@@ -23,7 +23,7 @@
 
 SintLiteral::SintLiteral(ProgramID program_id,
                          const Source& source,
-                         sem::Type* type,
+                         const sem::Type* type,
                          int32_t value)
     : Base(program_id, source, type, static_cast<uint32_t>(value)) {}
 
diff --git a/src/ast/sint_literal.h b/src/ast/sint_literal.h
index e215382..874ceb5 100644
--- a/src/ast/sint_literal.h
+++ b/src/ast/sint_literal.h
@@ -32,7 +32,7 @@
   /// @param value the signed int literals value
   SintLiteral(ProgramID program_id,
               const Source& source,
-              sem::Type* type,
+              const sem::Type* type,
               int32_t value);
   ~SintLiteral() override;
 
diff --git a/src/ast/type_constructor_expression.cc b/src/ast/type_constructor_expression.cc
index 1b2c3d1..ecfa60c 100644
--- a/src/ast/type_constructor_expression.cc
+++ b/src/ast/type_constructor_expression.cc
@@ -23,7 +23,7 @@
 
 TypeConstructorExpression::TypeConstructorExpression(ProgramID program_id,
                                                      const Source& source,
-                                                     sem::Type* type,
+                                                     const sem::Type* type,
                                                      ExpressionList values)
     : Base(program_id, source), type_(type), values_(std::move(values)) {
   TINT_ASSERT(type_);
diff --git a/src/ast/type_constructor_expression.h b/src/ast/type_constructor_expression.h
index 8270865..5b63f43 100644
--- a/src/ast/type_constructor_expression.h
+++ b/src/ast/type_constructor_expression.h
@@ -33,14 +33,15 @@
   /// @param values the constructor values
   TypeConstructorExpression(ProgramID program_id,
                             const Source& source,
-                            sem::Type* type,
+                            const sem::Type* type,
                             ExpressionList values);
   /// Move constructor
   TypeConstructorExpression(TypeConstructorExpression&&);
   ~TypeConstructorExpression() override;
 
   /// @returns the type
-  sem::Type* type() const { return type_; }
+  sem::Type* type() const { return const_cast<sem::Type*>(type_); }
+
   /// @returns the values
   const ExpressionList& values() const { return values_; }
 
@@ -61,7 +62,7 @@
  private:
   TypeConstructorExpression(const TypeConstructorExpression&) = delete;
 
-  sem::Type* const type_;
+  const sem::Type* const type_;
   ExpressionList const values_;
 };
 
diff --git a/src/ast/uint_literal.cc b/src/ast/uint_literal.cc
index a65a36b..4280855 100644
--- a/src/ast/uint_literal.cc
+++ b/src/ast/uint_literal.cc
@@ -23,7 +23,7 @@
 
 UintLiteral::UintLiteral(ProgramID program_id,
                          const Source& source,
-                         sem::Type* type,
+                         const sem::Type* type,
                          uint32_t value)
     : Base(program_id, source, type, value) {}
 
diff --git a/src/ast/uint_literal.h b/src/ast/uint_literal.h
index 0b12775..6015415 100644
--- a/src/ast/uint_literal.h
+++ b/src/ast/uint_literal.h
@@ -32,7 +32,7 @@
   /// @param value the uint literals value
   UintLiteral(ProgramID program_id,
               const Source& source,
-              sem::Type* type,
+              const sem::Type* type,
               uint32_t value);
   ~UintLiteral() override;
 
diff --git a/src/ast/variable.cc b/src/ast/variable.cc
index 1371ce4..bf42180 100644
--- a/src/ast/variable.cc
+++ b/src/ast/variable.cc
@@ -27,7 +27,7 @@
                    const Source& source,
                    const Symbol& sym,
                    StorageClass declared_storage_class,
-                   sem::Type* declared_type,
+                   const sem::Type* declared_type,
                    bool is_const,
                    Expression* constructor,
                    DecorationList decorations)
diff --git a/src/ast/variable.h b/src/ast/variable.h
index 9094f9e..1327c56 100644
--- a/src/ast/variable.h
+++ b/src/ast/variable.h
@@ -103,7 +103,7 @@
            const Source& source,
            const Symbol& sym,
            StorageClass declared_storage_class,
-           sem::Type* declared_type,
+           const sem::Type* declared_type,
            bool is_const,
            Expression* constructor,
            DecorationList decorations);
@@ -116,7 +116,9 @@
   const Symbol& symbol() const { return symbol_; }
 
   /// @returns the declared type
-  sem::Type* declared_type() const { return declared_type_; }
+  sem::Type* declared_type() const {
+    return const_cast<sem::Type*>(declared_type_);
+  }
 
   /// @returns the declared storage class
   StorageClass declared_storage_class() const {
@@ -175,7 +177,7 @@
 
   Symbol const symbol_;
   // The value type if a const or formal paramter, and the store type if a var
-  sem::Type* const declared_type_;
+  const sem::Type* const declared_type_;
   bool const is_const_;
   Expression* const constructor_;
   DecorationList const decorations_;
diff --git a/src/sem/access_control_type.cc b/src/sem/access_control_type.cc
index 6c3101f..03bfbc0 100644
--- a/src/sem/access_control_type.cc
+++ b/src/sem/access_control_type.cc
@@ -21,7 +21,8 @@
 namespace tint {
 namespace sem {
 
-AccessControl::AccessControl(ast::AccessControl::Access access, Type* subtype)
+AccessControl::AccessControl(ast::AccessControl::Access access,
+                             const Type* subtype)
     : access_(access), subtype_(subtype) {
   TINT_ASSERT(subtype_);
   TINT_ASSERT(!subtype_->Is<AccessControl>());
diff --git a/src/sem/access_control_type.h b/src/sem/access_control_type.h
index 5772970..bf0db33 100644
--- a/src/sem/access_control_type.h
+++ b/src/sem/access_control_type.h
@@ -29,7 +29,7 @@
   /// Constructor
   /// @param access the access control setting
   /// @param subtype the access controlled type
-  AccessControl(ast::AccessControl::Access access, Type* subtype);
+  AccessControl(ast::AccessControl::Access access, const Type* subtype);
   /// Move constructor
   AccessControl(AccessControl&&);
   ~AccessControl() override;
@@ -44,7 +44,7 @@
   /// @returns the access control value
   ast::AccessControl::Access access_control() const { return access_; }
   /// @returns the subtype type
-  Type* type() const { return subtype_; }
+  Type* type() const { return const_cast<Type*>(subtype_); }
 
   /// @returns the name for this type
   std::string type_name() const override;
@@ -61,7 +61,7 @@
 
  private:
   ast::AccessControl::Access const access_;
-  Type* const subtype_;
+  const Type* const subtype_;
 };
 
 }  // namespace sem
diff --git a/src/sem/alias_type.cc b/src/sem/alias_type.cc
index 6288ed8..d40001c 100644
--- a/src/sem/alias_type.cc
+++ b/src/sem/alias_type.cc
@@ -21,7 +21,7 @@
 namespace tint {
 namespace sem {
 
-Alias::Alias(const Symbol& sym, Type* subtype)
+Alias::Alias(const Symbol& sym, const Type* subtype)
     : symbol_(sym), subtype_(subtype) {
   TINT_ASSERT(subtype_);
 }
diff --git a/src/sem/alias_type.h b/src/sem/alias_type.h
index f65ee2e..e4544e0 100644
--- a/src/sem/alias_type.h
+++ b/src/sem/alias_type.h
@@ -28,7 +28,7 @@
   /// Constructor
   /// @param sym the symbol for the alias
   /// @param subtype the alias'd type
-  Alias(const Symbol& sym, Type* subtype);
+  Alias(const Symbol& sym, const Type* subtype);
   /// Move constructor
   Alias(Alias&&);
   /// Destructor
@@ -37,7 +37,7 @@
   /// @returns the alias symbol
   Symbol symbol() const { return symbol_; }
   /// @returns the alias type
-  Type* type() const { return subtype_; }
+  Type* type() const { return const_cast<Type*>(subtype_); }
 
   /// @returns the type_name for this type
   std::string type_name() const override;
@@ -54,7 +54,7 @@
 
  private:
   Symbol const symbol_;
-  Type* const subtype_;
+  const Type* const subtype_;
 };
 
 }  // namespace sem
diff --git a/src/sem/expression.cc b/src/sem/expression.cc
index b3b2ee6..254c559 100644
--- a/src/sem/expression.cc
+++ b/src/sem/expression.cc
@@ -20,7 +20,7 @@
 namespace sem {
 
 Expression::Expression(ast::Expression* declaration,
-                       sem::Type* type,
+                       const sem::Type* type,
                        Statement* statement)
     : declaration_(declaration),
       type_(type->UnwrapIfNeeded()),
diff --git a/src/sem/expression.h b/src/sem/expression.h
index 10d3eeb..73d971f 100644
--- a/src/sem/expression.h
+++ b/src/sem/expression.h
@@ -32,11 +32,11 @@
   /// @param type the resolved type of the expression
   /// @param statement the statement that owns this expression
   Expression(ast::Expression* declaration,
-             sem::Type* type,
+             const sem::Type* type,
              Statement* statement);
 
   /// @return the resolved type of the expression
-  sem::Type* Type() const { return type_; }
+  sem::Type* Type() const { return const_cast<sem::Type*>(type_); }
 
   /// @return the statement that owns this expression
   Statement* Stmt() const { return statement_; }
@@ -46,7 +46,7 @@
 
  private:
   ast::Expression* declaration_;
-  sem::Type* const type_;
+  const sem::Type* const type_;
   Statement* const statement_;
 };
 
diff --git a/src/sem/member_accessor_expression.cc b/src/sem/member_accessor_expression.cc
index b2fccb9..78f55b2 100644
--- a/src/sem/member_accessor_expression.cc
+++ b/src/sem/member_accessor_expression.cc
@@ -26,7 +26,7 @@
 
 MemberAccessorExpression::MemberAccessorExpression(
     ast::MemberAccessorExpression* declaration,
-    sem::Type* type,
+    const sem::Type* type,
     Statement* statement)
     : Base(declaration, type, statement) {}
 
@@ -34,7 +34,7 @@
 
 StructMemberAccess::StructMemberAccess(
     ast::MemberAccessorExpression* declaration,
-    sem::Type* type,
+    const sem::Type* type,
     Statement* statement,
     const StructMember* member)
     : Base(declaration, type, statement), member_(member) {}
@@ -42,7 +42,7 @@
 StructMemberAccess::~StructMemberAccess() = default;
 
 Swizzle::Swizzle(ast::MemberAccessorExpression* declaration,
-                 sem::Type* type,
+                 const sem::Type* type,
                  Statement* statement,
                  std::vector<uint32_t> indices)
     : Base(declaration, type, statement), indices_(std::move(indices)) {}
diff --git a/src/sem/member_accessor_expression.h b/src/sem/member_accessor_expression.h
index d8665de..e298024 100644
--- a/src/sem/member_accessor_expression.h
+++ b/src/sem/member_accessor_expression.h
@@ -42,7 +42,7 @@
   /// @param type the resolved type of the expression
   /// @param statement the statement that owns this expression
   MemberAccessorExpression(ast::MemberAccessorExpression* declaration,
-                           sem::Type* type,
+                           const sem::Type* type,
                            Statement* statement);
 
   /// Destructor
@@ -61,7 +61,7 @@
   /// @param statement the statement that owns this expression
   /// @param member the structure member
   StructMemberAccess(ast::MemberAccessorExpression* declaration,
-                     sem::Type* type,
+                     const sem::Type* type,
                      Statement* statement,
                      const StructMember* member);
 
@@ -85,7 +85,7 @@
   /// @param statement the statement that
   /// @param indices the swizzle indices
   Swizzle(ast::MemberAccessorExpression* declaration,
-          sem::Type* type,
+          const sem::Type* type,
           Statement* statement,
           std::vector<uint32_t> indices);
 
diff --git a/src/sem/multisampled_texture_type.cc b/src/sem/multisampled_texture_type.cc
index 62125f8..d0c01c3 100644
--- a/src/sem/multisampled_texture_type.cc
+++ b/src/sem/multisampled_texture_type.cc
@@ -21,7 +21,8 @@
 namespace tint {
 namespace sem {
 
-MultisampledTexture::MultisampledTexture(ast::TextureDimension dim, Type* type)
+MultisampledTexture::MultisampledTexture(ast::TextureDimension dim,
+                                         const Type* type)
     : Base(dim), type_(type) {
   TINT_ASSERT(type_);
 }
diff --git a/src/sem/multisampled_texture_type.h b/src/sem/multisampled_texture_type.h
index b6d022a..5b3064f 100644
--- a/src/sem/multisampled_texture_type.h
+++ b/src/sem/multisampled_texture_type.h
@@ -28,13 +28,13 @@
   /// Constructor
   /// @param dim the dimensionality of the texture
   /// @param type the data type of the multisampled texture
-  MultisampledTexture(ast::TextureDimension dim, Type* type);
+  MultisampledTexture(ast::TextureDimension dim, const Type* type);
   /// Move constructor
   MultisampledTexture(MultisampledTexture&&);
   ~MultisampledTexture() override;
 
   /// @returns the subtype of the sampled texture
-  Type* type() const { return type_; }
+  Type* type() const { return const_cast<Type*>(type_); }
 
   /// @returns the name for this type
   std::string type_name() const override;
@@ -50,7 +50,7 @@
   MultisampledTexture* Clone(CloneContext* ctx) const override;
 
  private:
-  Type* const type_;
+  const Type* const type_;
 };
 
 }  // namespace sem
diff --git a/src/sem/sampled_texture_type.cc b/src/sem/sampled_texture_type.cc
index 251b05e..8f8ee77 100644
--- a/src/sem/sampled_texture_type.cc
+++ b/src/sem/sampled_texture_type.cc
@@ -21,7 +21,7 @@
 namespace tint {
 namespace sem {
 
-SampledTexture::SampledTexture(ast::TextureDimension dim, Type* type)
+SampledTexture::SampledTexture(ast::TextureDimension dim, const Type* type)
     : Base(dim), type_(type) {
   TINT_ASSERT(type_);
 }
diff --git a/src/sem/sampled_texture_type.h b/src/sem/sampled_texture_type.h
index ba01759..605de68 100644
--- a/src/sem/sampled_texture_type.h
+++ b/src/sem/sampled_texture_type.h
@@ -28,13 +28,13 @@
   /// Constructor
   /// @param dim the dimensionality of the texture
   /// @param type the data type of the sampled texture
-  SampledTexture(ast::TextureDimension dim, Type* type);
+  SampledTexture(ast::TextureDimension dim, const Type* type);
   /// Move constructor
   SampledTexture(SampledTexture&&);
   ~SampledTexture() override;
 
   /// @returns the subtype of the sampled texture
-  Type* type() const { return type_; }
+  Type* type() const { return const_cast<Type*>(type_); }
 
   /// @returns the name for this type
   std::string type_name() const override;
@@ -50,7 +50,7 @@
   SampledTexture* Clone(CloneContext* ctx) const override;
 
  private:
-  Type* const type_;
+  const Type* const type_;
 };
 
 }  // namespace sem
diff --git a/src/sem/type.h b/src/sem/type.h
index 870bc16..186cf97 100644
--- a/src/sem/type.h
+++ b/src/sem/type.h
@@ -48,10 +48,21 @@
   /// @returns the pointee type if this is a pointer, `this` otherwise
   Type* UnwrapPtrIfNeeded();
 
+  /// @returns the pointee type if this is a pointer, `this` otherwise
+  const Type* UnwrapPtrIfNeeded() const {
+    return const_cast<Type*>(this)->UnwrapPtrIfNeeded();
+  }
+
   /// @returns the most deeply nested aliased type if this is an alias, `this`
   /// otherwise
   Type* UnwrapAliasIfNeeded();
 
+  /// @returns the most deeply nested aliased type if this is an alias, `this`
+  /// otherwise
+  const Type* UnwrapAliasIfNeeded() const {
+    return const_cast<Type*>(this)->UnwrapAliasIfNeeded();
+  }
+
   /// Removes all levels of aliasing and access control.
   /// This is just enough to assist with WGSL translation
   /// in that you want see through one level of pointer to get from an
@@ -60,6 +71,16 @@
   /// @returns the completely unaliased type.
   Type* UnwrapIfNeeded();
 
+  /// Removes all levels of aliasing and access control.
+  /// This is just enough to assist with WGSL translation
+  /// in that you want see through one level of pointer to get from an
+  /// identifier-like expression as an l-value to its corresponding r-value,
+  /// plus see through the wrappers on either side.
+  /// @returns the completely unaliased type.
+  const Type* UnwrapIfNeeded() const {
+    return const_cast<Type*>(this)->UnwrapIfNeeded();
+  }
+
   /// Returns the type found after:
   /// - removing all layers of aliasing and access control if they exist, then
   /// - removing the pointer, if it exists, then
@@ -67,6 +88,13 @@
   /// @returns the unwrapped type
   Type* UnwrapAll();
 
+  /// Returns the type found after:
+  /// - removing all layers of aliasing and access control if they exist, then
+  /// - removing the pointer, if it exists, then
+  /// - removing all further layers of aliasing or access control, if they exist
+  /// @returns the unwrapped type
+  const Type* UnwrapAll() const { return const_cast<Type*>(this)->UnwrapAll(); }
+
   /// @returns true if this type is a scalar
   bool is_scalar() const;
   /// @returns true if this type is a numeric scalar
diff --git a/src/sem/variable.cc b/src/sem/variable.cc
index 89e4bec..8db2a70 100644
--- a/src/sem/variable.cc
+++ b/src/sem/variable.cc
@@ -24,7 +24,7 @@
 namespace sem {
 
 Variable::Variable(const ast::Variable* declaration,
-                   sem::Type* type,
+                   const sem::Type* type,
                    ast::StorageClass storage_class)
     : declaration_(declaration), type_(type), storage_class_(storage_class) {}
 
@@ -35,7 +35,7 @@
 }
 
 VariableUser::VariableUser(ast::IdentifierExpression* declaration,
-                           sem::Type* type,
+                           const sem::Type* type,
                            Statement* statement,
                            sem::Variable* variable)
     : Base(declaration, type, statement), variable_(variable) {}
diff --git a/src/sem/variable.h b/src/sem/variable.h
index 6a0a618..c6bea3b 100644
--- a/src/sem/variable.h
+++ b/src/sem/variable.h
@@ -42,7 +42,7 @@
   /// @param type the variable type
   /// @param storage_class the variable storage class
   Variable(const ast::Variable* declaration,
-           sem::Type* type,
+           const sem::Type* type,
            ast::StorageClass storage_class);
 
   /// Destructor
@@ -52,7 +52,7 @@
   const ast::Variable* Declaration() const { return declaration_; }
 
   /// @returns the canonical type for the variable
-  sem::Type* Type() const { return type_; }
+  sem::Type* Type() const { return const_cast<sem::Type*>(type_); }
 
   /// @returns the AST node's type. May be nullptr.
   sem::Type* DeclaredType() const;
@@ -68,7 +68,7 @@
 
  private:
   const ast::Variable* const declaration_;
-  sem::Type* const type_;
+  const sem::Type* const type_;
   ast::StorageClass const storage_class_;
   std::vector<const VariableUser*> users_;
 };
@@ -83,7 +83,7 @@
   /// @param statement the statement that owns this expression
   /// @param variable the semantic variable
   VariableUser(ast::IdentifierExpression* declaration,
-               sem::Type* type,
+               const sem::Type* type,
                Statement* statement,
                sem::Variable* variable);