diff --git a/compiler/rustc_ast_passes/src/feature_gate.rs b/compiler/rustc_ast_passes/src/feature_gate.rs index 662357ce88413..42c601add4f8c 100644 --- a/compiler/rustc_ast_passes/src/feature_gate.rs +++ b/compiler/rustc_ast_passes/src/feature_gate.rs @@ -508,6 +508,7 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session, features: &Features) { gate_all!(builtin_syntax, "`builtin #` syntax is unstable"); gate_all!(ergonomic_clones, "ergonomic clones are experimental"); gate_all!(explicit_tail_calls, "`become` expression is experimental"); + gate_all!(explicit_ignored_bindings, "explicit `ignored` binding placeholders are experimental"); gate_all!(generic_const_items, "generic const items are experimental"); gate_all!(guard_patterns, "guard patterns are experimental", "consider using match arm guards"); gate_all!(default_field_values, "default values on fields are experimental"); diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs index 6b220faa66ac4..888b9c34a164b 100644 --- a/compiler/rustc_feature/src/unstable.rs +++ b/compiler/rustc_feature/src/unstable.rs @@ -487,6 +487,8 @@ declare_features! ( (unstable, exhaustive_patterns, "1.13.0", Some(51085)), /// Disallows `extern` without an explicit ABI. (unstable, explicit_extern_abis, "1.88.0", Some(134986)), + /// Allows explicit `ignored` binding placeholders in patterns. + (unstable, explicit_ignored_bindings, "1.90.0", None), /// Allows explicit tail calls via `become` expression. (incomplete, explicit_tail_calls, "1.72.0", Some(112788)), /// Allows using `#[export_stable]` which indicates that an item is exportable. diff --git a/compiler/rustc_parse/src/parser/pat.rs b/compiler/rustc_parse/src/parser/pat.rs index 64653ee2a04c9..202bcdd186817 100644 --- a/compiler/rustc_parse/src/parser/pat.rs +++ b/compiler/rustc_parse/src/parser/pat.rs @@ -765,6 +765,13 @@ impl<'a> Parser<'a> { } else if self.eat_keyword(exp!(Underscore)) { // Parse `_` PatKind::Wild + } else if self.check_keyword(exp!(Ignored)) + && !self.look_ahead(1, |t| matches!(t.kind, token::PathSep | token::Bang)) + { + self.bump(); + // An explicit ignored binding placeholder `ignored` + self.psess.gated_spans.gate(sym::explicit_ignored_bindings, self.prev_token.span); + PatKind::Wild } else if self.eat_keyword(exp!(Mut)) { self.parse_pat_ident_mut()? } else if self.eat_keyword(exp!(Ref)) { diff --git a/compiler/rustc_parse/src/parser/token_type.rs b/compiler/rustc_parse/src/parser/token_type.rs index b91548196a305..bdd705b7437c4 100644 --- a/compiler/rustc_parse/src/parser/token_type.rs +++ b/compiler/rustc_parse/src/parser/token_type.rs @@ -95,6 +95,7 @@ pub enum TokenType { KwFor, KwGen, KwIf, + KwIgnored, KwImpl, KwIn, KwLet, @@ -232,6 +233,7 @@ impl TokenType { KwFor, KwGen, KwIf, + KwIgnored, KwImpl, KwIn, KwLet, @@ -307,6 +309,7 @@ impl TokenType { TokenType::KwFor => Some(kw::For), TokenType::KwGen => Some(kw::Gen), TokenType::KwIf => Some(kw::If), + TokenType::KwIgnored => Some(kw::Ignored), TokenType::KwImpl => Some(kw::Impl), TokenType::KwIn => Some(kw::In), TokenType::KwLet => Some(kw::Let), @@ -521,6 +524,7 @@ macro_rules! exp { (For) => { exp!(@kw, For, KwFor) }; (Gen) => { exp!(@kw, Gen, KwGen) }; (If) => { exp!(@kw, If, KwIf) }; + (Ignored) => { exp!(@kw, Ignored, KwIgnored) }; (Impl) => { exp!(@kw, Impl, KwImpl) }; (In) => { exp!(@kw, In, KwIn) }; (Let) => { exp!(@kw, Let, KwLet) }; diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index d54175548e30e..dfc7fad7e1bc6 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -130,6 +130,7 @@ symbols! { ContractEnsures: "contract_ensures", ContractRequires: "contract_requires", Default: "default", + Ignored: "ignored", MacroRules: "macro_rules", Raw: "raw", Reuse: "reuse", @@ -939,6 +940,7 @@ symbols! { expf128, explicit_extern_abis, explicit_generic_args_with_impl_trait, + explicit_ignored_bindings, explicit_tail_calls, export_name, export_stable, diff --git a/tests/ui/feature-gates/feature-gate-explicit-ignored-bindings.rs b/tests/ui/feature-gates/feature-gate-explicit-ignored-bindings.rs new file mode 100644 index 0000000000000..0da18642cf516 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-explicit-ignored-bindings.rs @@ -0,0 +1,8 @@ +// Testing that explicit `ignored` placeholders need the feature gate + +fn main() { + let (a, ignored) = (1, 2); + //~^ ERROR explicit `ignored` binding placeholders are experimental + let _ = a; +} + diff --git a/tests/ui/feature-gates/feature-gate-explicit-ignored-bindings.stderr b/tests/ui/feature-gates/feature-gate-explicit-ignored-bindings.stderr new file mode 100644 index 0000000000000..a8ad20fa43d0d --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-explicit-ignored-bindings.stderr @@ -0,0 +1,13 @@ +error[E0658]: explicit `ignored` binding placeholders are experimental + --> $DIR/feature-gate-explicit-ignored-bindings.rs:4:13 + | +LL | let (a, ignored) = (1, 2); + | ^^^^^^^ + | + = help: add `#![feature(explicit_ignored_bindings)]` 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: aborting due to previous error + +For more information about this error, try `rustc --explain E0658`. + diff --git a/tests/ui/ignored-bindings/basic.rs b/tests/ui/ignored-bindings/basic.rs new file mode 100644 index 0000000000000..0db449096be1b --- /dev/null +++ b/tests/ui/ignored-bindings/basic.rs @@ -0,0 +1,19 @@ +// check-pass +#![feature(explicit_ignored_bindings)] + +fn main() { + let (a, ignored) = (1, 2); + let _ = a; + + let (ignored, b) = (1, 2); + let _ = b; + + let ((x, ignored), y) = ((1, 2), 3); + let _ = (x, y); + + match (1, 2) { + (ignored, 2) => {} + _ => {} + } +} + diff --git a/tests/ui/parser/raw/raw-idents.rs b/tests/ui/parser/raw/raw-idents.rs index 93015ee6c4942..1de781bbc761a 100644 --- a/tests/ui/parser/raw/raw-idents.rs +++ b/tests/ui/parser/raw/raw-idents.rs @@ -148,6 +148,7 @@ tests!(auto); tests!(builtin); tests!(catch); tests!(default); +tests!(r#ignored); tests!(macro_rules); tests!(raw); tests!(reuse);