diff --git a/compiler/rustc_ast_passes/src/feature_gate.rs b/compiler/rustc_ast_passes/src/feature_gate.rs index 34c73b545df87..b18c1a9b2b996 100644 --- a/compiler/rustc_ast_passes/src/feature_gate.rs +++ b/compiler/rustc_ast_passes/src/feature_gate.rs @@ -145,7 +145,8 @@ impl<'a> PostExpansionVisitor<'a> { } for param in params { - if !param.bounds.is_empty() { + if !matches!(param.kind, ast::GenericParamKind::Type { .. }) && !param.bounds.is_empty() + { let spans: Vec<_> = param.bounds.iter().map(|b| b.span()).collect(); self.sess.dcx().emit_err(errors::ForbiddenBound { spans }); } diff --git a/compiler/rustc_parse/src/errors.rs b/compiler/rustc_parse/src/errors.rs index e73d9a1bf56ab..b9d90dbdc835a 100644 --- a/compiler/rustc_parse/src/errors.rs +++ b/compiler/rustc_parse/src/errors.rs @@ -4423,6 +4423,13 @@ pub(crate) struct MisspelledKw { pub is_incorrect_case: bool, } +#[derive(Diagnostic)] +#[diag("bounds cannot be used in this context")] +pub(crate) struct ForbiddenBound { + #[primary_span] + pub spans: Vec, +} + #[derive(Clone, Copy, Debug, PartialEq, Eq)] pub(super) enum TokenDescription { ReservedIdentifier, diff --git a/compiler/rustc_parse/src/parser/ty.rs b/compiler/rustc_parse/src/parser/ty.rs index 6ff165eb22b71..a7cf0e0088e4a 100644 --- a/compiler/rustc_parse/src/parser/ty.rs +++ b/compiler/rustc_parse/src/parser/ty.rs @@ -1433,6 +1433,24 @@ impl<'a> Parser<'a> { self.expect_lt()?; let params = self.parse_generic_params()?; self.expect_gt()?; + + // Issue 149695 + // Deny and remove bounds for type parameters in higher-ranked binders, + // otherwise nested items may have parents not in hir. + let params = params + .into_iter() + .map(|mut param| { + if matches!(param.kind, ast::GenericParamKind::Type { .. }) + && !param.bounds.is_empty() + { + let spans: Vec<_> = param.bounds.iter().map(|b| b.span()).collect(); + self.dcx().emit_err(errors::ForbiddenBound { spans }); + param.bounds.clear(); + } + param + }) + .collect::>(); + // We rely on AST validation to rule out invalid cases: There must not be // type or const parameters, and parameters must not have bounds. Ok((params, Some(lo.to(self.prev_token.span)))) diff --git a/src/tools/rustfmt/tests/source/non-lifetime-binders.rs b/src/tools/rustfmt/tests/source/non-lifetime-binders.rs index c26393c8f895c..1649f4676985f 100644 --- a/src/tools/rustfmt/tests/source/non-lifetime-binders.rs +++ b/src/tools/rustfmt/tests/source/non-lifetime-binders.rs @@ -1,4 +1,4 @@ -fn main() where for<'a, T: Sized + 'a, const C: usize> [&'a T; C]: Sized { +fn main() where for<'a, T, const C: usize> [&'a T; C]: Sized { let x = for || {}; diff --git a/src/tools/rustfmt/tests/target/non-lifetime-binders.rs b/src/tools/rustfmt/tests/target/non-lifetime-binders.rs index ca6941a0c00be..44d9d7be80767 100644 --- a/src/tools/rustfmt/tests/target/non-lifetime-binders.rs +++ b/src/tools/rustfmt/tests/target/non-lifetime-binders.rs @@ -1,6 +1,6 @@ fn main() where - for<'a, T: Sized + 'a, const C: usize> [&'a T; C]: Sized, + for<'a, T, const C: usize> [&'a T; C]: Sized, { let x = for || {}; diff --git a/tests/ui/traits/non_lifetime_binders/bad-bounds.rs b/tests/ui/traits/non_lifetime_binders/bad-bounds.rs new file mode 100644 index 0000000000000..c01792b9f1075 --- /dev/null +++ b/tests/ui/traits/non_lifetime_binders/bad-bounds.rs @@ -0,0 +1,14 @@ +//@ edition: 2024 + +#![feature(non_lifetime_binders)] +#![expect(incomplete_features)] + +fn produce() -> for; +}>> Trait {} //~ ERROR cannot find trait `Trait` in this scope + +fn main() {} diff --git a/tests/ui/traits/non_lifetime_binders/bad-bounds.stderr b/tests/ui/traits/non_lifetime_binders/bad-bounds.stderr new file mode 100644 index 0000000000000..4e55788927fc4 --- /dev/null +++ b/tests/ui/traits/non_lifetime_binders/bad-bounds.stderr @@ -0,0 +1,42 @@ +error: bounds cannot be used in this context + --> $DIR/bad-bounds.rs:6:24 + | +LL | fn produce() -> for; +LL | | }>> Trait {} + | |__^ + +error[E0405]: cannot find trait `Trait` in this scope + --> $DIR/bad-bounds.rs:12:5 + | +LL | }>> Trait {} + | ^^^^^ not found in this scope + +error: late-bound type parameter not allowed on trait object types + --> $DIR/bad-bounds.rs:6:21 + | +LL | fn produce() -> for $DIR/bad-bounds.rs:6:17 + | +LL | fn produce() -> for; +LL | | }>> Trait {} + | |_________^ + +error: aborting due to 4 previous errors + +Some errors have detailed explanations: E0405, E0782. +For more information about an error, try `rustc --explain E0405`.