]> git.lizzy.rs Git - rust.git/blobdiff - compiler/rustc_parse/src/parser/diagnostics.rs
Parse `Ty?` as `Option<Ty>` and provide structured suggestion
[rust.git] / compiler / rustc_parse / src / parser / diagnostics.rs
index 9677e7642b88c9c4f522eb51dae3a4ac2b76fd0c..b844e96d39c54132877b2e69bbb87d818648afe1 100644 (file)
@@ -1,5 +1,5 @@
 use super::pat::Expected;
-use super::ty::AllowPlus;
+use super::ty::{AllowPlus, IsAsCast};
 use super::{
     BlockMode, Parser, PathStyle, RecoverColon, RecoverComma, Restrictions, SemiColonMode, SeqSep,
     TokenExpectType, TokenType,
@@ -1032,6 +1032,34 @@ pub(super) fn maybe_report_ambiguous_plus(
         }
     }
 
+    /// Swift lets users write `Ty?` to mean `Option<Ty>`. Parse the construct and recover from it.
+    pub(super) fn maybe_recover_from_question_mark(
+        &mut self,
+        ty: P<Ty>,
+        is_as_cast: IsAsCast,
+    ) -> P<Ty> {
+        if let IsAsCast::Yes = is_as_cast {
+            return ty;
+        }
+        if self.token == token::Question {
+            self.bump();
+            self.struct_span_err(self.prev_token.span, "invalid `?` in type")
+                .span_label(self.prev_token.span, "`?` is only allowed on expressions, not types")
+                .multipart_suggestion(
+                    "if you meant to express that the type might not contain a value, use the `Option` wrapper type",
+                    vec![
+                        (ty.span.shrink_to_lo(), "Option<".to_string()),
+                        (self.prev_token.span, ">".to_string()),
+                    ],
+                    Applicability::MachineApplicable,
+                )
+                .emit();
+            self.mk_ty(ty.span.to(self.prev_token.span), TyKind::Err)
+        } else {
+            ty
+        }
+    }
+
     pub(super) fn maybe_recover_from_bad_type_plus(
         &mut self,
         allow_plus: AllowPlus,