From d3992fac9491d397f8d41d7f34f98f1420d7728f Mon Sep 17 00:00:00 2001
From: Sasha Pourcelot <sasha.pourcelot@protonmail.com>
Date: Tue, 28 Apr 2026 18:01:12 +0000
Subject: [PATCH 1/2] Add feature gate for view_types

---
 compiler/rustc_feature/src/unstable.rs        |  2 +
 compiler/rustc_span/src/symbol.rs             |  1 +
 .../feature-gates/feature-gate-view-types.rs  | 16 ++++++
 .../feature-gate-view-types.stderr            | 49 +++++++++++++++++++
 4 files changed, 68 insertions(+)
 create mode 100644 tests/ui/feature-gates/feature-gate-view-types.rs
 create mode 100644 tests/ui/feature-gates/feature-gate-view-types.stderr

diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs
index 3bb4bc863def2..9712879fce6f7 100644
--- a/compiler/rustc_feature/src/unstable.rs
+++ b/compiler/rustc_feature/src/unstable.rs
@@ -723,6 +723,8 @@ declare_features! (
     (internal, unsized_fn_params, "1.49.0", Some(48055)),
     /// Allows using the `#[used(linker)]` (or `#[used(compiler)]`) attribute.
     (unstable, used_with_arg, "1.60.0", Some(93798)),
+    /// Allows view types.
+    (unstable, view_types, "CURRENT_RUSTC_VERSION", Some(155938)),
     /// Target features on wasm.
     (unstable, wasm_target_feature, "1.30.0", Some(150260)),
     /// Allows use of attributes in `where` clauses.
diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs
index 4cacdbd3408a5..3db4921d6ec0a 100644
--- a/compiler/rustc_span/src/symbol.rs
+++ b/compiler/rustc_span/src/symbol.rs
@@ -2232,6 +2232,7 @@ symbols! {
         verbatim,
         version,
         vfp2,
+        view_types,
         vis,
         visible_private_types,
         volatile,
diff --git a/tests/ui/feature-gates/feature-gate-view-types.rs b/tests/ui/feature-gates/feature-gate-view-types.rs
new file mode 100644
index 0000000000000..26ca0ee4206b2
--- /dev/null
+++ b/tests/ui/feature-gates/feature-gate-view-types.rs
@@ -0,0 +1,16 @@
+//@ known-bug: #155938
+
+struct Foo {
+    a: usize,
+    b: usize,
+}
+
+fn bar(a: &mut Foo.{ a }, b: &mut Foo.{ b }) {
+    a.a += 1;
+    b.b += 1;
+}
+
+fn main() {
+    let mut foo = Foo { a: 0, b: 0 };
+    bar(&mut foo, &mut foo);
+}
diff --git a/tests/ui/feature-gates/feature-gate-view-types.stderr b/tests/ui/feature-gates/feature-gate-view-types.stderr
new file mode 100644
index 0000000000000..436b7ea769ed3
--- /dev/null
+++ b/tests/ui/feature-gates/feature-gate-view-types.stderr
@@ -0,0 +1,49 @@
+error: expected parameter name, found `{`
+  --> $DIR/feature-gate-view-types.rs:8:20
+   |
+LL | fn bar(a: &mut Foo.{ a }, b: &mut Foo.{ b }) {
+   |                    ^ expected parameter name
+
+error: expected one of `!`, `(`, `)`, `,`, `::`, or `<`, found `.`
+  --> $DIR/feature-gate-view-types.rs:8:19
+   |
+LL | fn bar(a: &mut Foo.{ a }, b: &mut Foo.{ b }) {
+   |                   ^
+   |                   |
+   |                   expected one of `!`, `(`, `)`, `,`, `::`, or `<`
+   |                   help: missing `,`
+
+error: expected parameter name, found `{`
+  --> $DIR/feature-gate-view-types.rs:8:39
+   |
+LL | fn bar(a: &mut Foo.{ a }, b: &mut Foo.{ b }) {
+   |                                       ^ expected parameter name
+
+error: expected one of `!`, `(`, `)`, `,`, `::`, or `<`, found `.`
+  --> $DIR/feature-gate-view-types.rs:8:38
+   |
+LL | fn bar(a: &mut Foo.{ a }, b: &mut Foo.{ b }) {
+   |                                      ^
+   |                                      |
+   |                                      expected one of `!`, `(`, `)`, `,`, `::`, or `<`
+   |                                      help: missing `,`
+
+error[E0061]: this function takes 4 arguments but 2 arguments were supplied
+  --> $DIR/feature-gate-view-types.rs:15:5
+   |
+LL |     bar(&mut foo, &mut foo);
+   |     ^^^-------------------- two arguments are missing
+   |
+note: function defined here
+  --> $DIR/feature-gate-view-types.rs:8:4
+   |
+LL | fn bar(a: &mut Foo.{ a }, b: &mut Foo.{ b }) {
+   |    ^^^                    -----------------
+help: provide the arguments
+   |
+LL |     bar(&mut foo, &mut foo, /* &mut Foo */, /* _ */);
+   |                           +++++++++++++++++++++++++
+
+error: aborting due to 5 previous errors
+
+For more information about this error, try `rustc --explain E0061`.

From 77fb8d1d5c5f5e2058049b3b90abde3f8bccef4f Mon Sep 17 00:00:00 2001
From: Sasha Pourcelot <sasha.pourcelot@protonmail.com>
Date: Wed, 29 Apr 2026 09:03:26 +0000
Subject: [PATCH 2/2] Parse view type syntax, mark it as unstable

---
 compiler/rustc_ast_passes/src/feature_gate.rs |  1 +
 compiler/rustc_parse/src/parser/ty.rs         | 21 ++++++-
 .../feature-gates/feature-gate-view-types.rs  |  5 +-
 .../feature-gate-view-types.stderr            | 58 +++++++------------
 4 files changed, 45 insertions(+), 40 deletions(-)

diff --git a/compiler/rustc_ast_passes/src/feature_gate.rs b/compiler/rustc_ast_passes/src/feature_gate.rs
index 5831636a81b2c..3d51770f6ba79 100644
--- a/compiler/rustc_ast_passes/src/feature_gate.rs
+++ b/compiler/rustc_ast_passes/src/feature_gate.rs
@@ -510,6 +510,7 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session, features: &Features) {
     gate_all!(try_blocks_heterogeneous, "`try bikeshed` expression is experimental");
     gate_all!(unsafe_binders, "unsafe binder types are experimental");
     gate_all!(unsafe_fields, "`unsafe` fields are experimental");
+    gate_all!(view_types, "view types are experimental");
     gate_all!(where_clause_attrs, "attributes in `where` clause are unstable");
     gate_all!(yeet_expr, "`do yeet` expression is experimental");
     // tidy-alphabetical-end
diff --git a/compiler/rustc_parse/src/parser/ty.rs b/compiler/rustc_parse/src/parser/ty.rs
index 072975f445bf4..b5151cf20ab02 100644
--- a/compiler/rustc_parse/src/parser/ty.rs
+++ b/compiler/rustc_parse/src/parser/ty.rs
@@ -19,7 +19,7 @@ use crate::errors::{
     NeedPlusAfterTraitObjectLifetime, NestedCVariadicType, ReturnTypesUseThinArrow,
 };
 use crate::parser::item::FrontMatterParsingMode;
-use crate::parser::{FnContext, FnParseMode};
+use crate::parser::{ExpTokenPair, FnContext, FnParseMode};
 use crate::{exp, maybe_recover_from_interpolated_ty_qpath};
 
 /// Signals whether parsing a type should allow `+`.
@@ -768,6 +768,25 @@ impl<'a> Parser<'a> {
             self.bump_with((dyn_tok, dyn_tok_sp));
         }
         let ty = self.parse_ty_no_plus()?;
+        if self.token == TokenKind::Dot && self.look_ahead(1, |t| t.kind == TokenKind::OpenBrace) {
+            // & [mut] <type> . { <fields> }
+            //                ^
+            //                we are here
+            let view_start_span = self.token.span;
+            self.bump();
+            let fields = self
+                .parse_delim_comma_seq(
+                    ExpTokenPair { tok: TokenKind::OpenBrace, token_type: TokenType::OpenBrace },
+                    ExpTokenPair { tok: TokenKind::CloseBrace, token_type: TokenType::CloseBrace },
+                    |p| p.parse_ident(),
+                )?
+                .0;
+            // FIXME(scrabsha): actually propagate field view in the AST.
+            let _ = fields;
+            let view_end_span = self.prev_token.span;
+            let span = view_start_span.to(view_end_span);
+            self.psess.gated_spans.gate(sym::view_types, span);
+        }
         Ok(match pinned {
             Pinnedness::Not => TyKind::Ref(opt_lifetime, MutTy { ty, mutbl }),
             Pinnedness::Pinned => TyKind::PinnedRef(opt_lifetime, MutTy { ty, mutbl }),
diff --git a/tests/ui/feature-gates/feature-gate-view-types.rs b/tests/ui/feature-gates/feature-gate-view-types.rs
index 26ca0ee4206b2..eb0c26d61db4a 100644
--- a/tests/ui/feature-gates/feature-gate-view-types.rs
+++ b/tests/ui/feature-gates/feature-gate-view-types.rs
@@ -1,11 +1,11 @@
-//@ known-bug: #155938
-
 struct Foo {
     a: usize,
     b: usize,
 }
 
 fn bar(a: &mut Foo.{ a }, b: &mut Foo.{ b }) {
+    //~^ ERROR view types are experimental
+    //~| ERROR view types are experimental
     a.a += 1;
     b.b += 1;
 }
@@ -13,4 +13,5 @@ fn bar(a: &mut Foo.{ a }, b: &mut Foo.{ b }) {
 fn main() {
     let mut foo = Foo { a: 0, b: 0 };
     bar(&mut foo, &mut foo);
+    //~^ ERROR cannot borrow `foo` as mutable more than once at a time
 }
diff --git a/tests/ui/feature-gates/feature-gate-view-types.stderr b/tests/ui/feature-gates/feature-gate-view-types.stderr
index 436b7ea769ed3..661783ec59202 100644
--- a/tests/ui/feature-gates/feature-gate-view-types.stderr
+++ b/tests/ui/feature-gates/feature-gate-view-types.stderr
@@ -1,49 +1,33 @@
-error: expected parameter name, found `{`
-  --> $DIR/feature-gate-view-types.rs:8:20
+error[E0658]: view types are experimental
+  --> $DIR/feature-gate-view-types.rs:6:19
    |
 LL | fn bar(a: &mut Foo.{ a }, b: &mut Foo.{ b }) {
-   |                    ^ expected parameter name
-
-error: expected one of `!`, `(`, `)`, `,`, `::`, or `<`, found `.`
-  --> $DIR/feature-gate-view-types.rs:8:19
+   |                   ^^^^^^
    |
-LL | fn bar(a: &mut Foo.{ a }, b: &mut Foo.{ b }) {
-   |                   ^
-   |                   |
-   |                   expected one of `!`, `(`, `)`, `,`, `::`, or `<`
-   |                   help: missing `,`
+   = note: see issue #155938 <https://github.com/rust-lang/rust/issues/155938> for more information
+   = help: add `#![feature(view_types)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error: expected parameter name, found `{`
-  --> $DIR/feature-gate-view-types.rs:8:39
+error[E0658]: view types are experimental
+  --> $DIR/feature-gate-view-types.rs:6:38
    |
 LL | fn bar(a: &mut Foo.{ a }, b: &mut Foo.{ b }) {
-   |                                       ^ expected parameter name
-
-error: expected one of `!`, `(`, `)`, `,`, `::`, or `<`, found `.`
-  --> $DIR/feature-gate-view-types.rs:8:38
+   |                                      ^^^^^^
    |
-LL | fn bar(a: &mut Foo.{ a }, b: &mut Foo.{ b }) {
-   |                                      ^
-   |                                      |
-   |                                      expected one of `!`, `(`, `)`, `,`, `::`, or `<`
-   |                                      help: missing `,`
+   = note: see issue #155938 <https://github.com/rust-lang/rust/issues/155938> for more information
+   = help: add `#![feature(view_types)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0061]: this function takes 4 arguments but 2 arguments were supplied
-  --> $DIR/feature-gate-view-types.rs:15:5
+error[E0499]: cannot borrow `foo` as mutable more than once at a time
+  --> $DIR/feature-gate-view-types.rs:15:19
    |
 LL |     bar(&mut foo, &mut foo);
-   |     ^^^-------------------- two arguments are missing
-   |
-note: function defined here
-  --> $DIR/feature-gate-view-types.rs:8:4
-   |
-LL | fn bar(a: &mut Foo.{ a }, b: &mut Foo.{ b }) {
-   |    ^^^                    -----------------
-help: provide the arguments
-   |
-LL |     bar(&mut foo, &mut foo, /* &mut Foo */, /* _ */);
-   |                           +++++++++++++++++++++++++
+   |     --- --------  ^^^^^^^^ second mutable borrow occurs here
+   |     |   |
+   |     |   first mutable borrow occurs here
+   |     first borrow later used by call
 
-error: aborting due to 5 previous errors
+error: aborting due to 3 previous errors
 
-For more information about this error, try `rustc --explain E0061`.
+Some errors have detailed explanations: E0499, E0658.
+For more information about an error, try `rustc --explain E0499`.
