Skip to content

Commit 151537e

Browse files
committed
Emit ForbiddenBound for bounds of type params when parsing
1 parent 5d04477 commit 151537e

6 files changed

Lines changed: 84 additions & 2 deletions

File tree

compiler/rustc_ast_passes/src/feature_gate.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,8 @@ impl<'a> PostExpansionVisitor<'a> {
145145
}
146146

147147
for param in params {
148-
if !param.bounds.is_empty() {
148+
if !matches!(param.kind, ast::GenericParamKind::Type { .. }) && !param.bounds.is_empty()
149+
{
149150
let spans: Vec<_> = param.bounds.iter().map(|b| b.span()).collect();
150151
self.sess.dcx().emit_err(errors::ForbiddenBound { spans });
151152
}

compiler/rustc_parse/src/errors.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4423,6 +4423,13 @@ pub(crate) struct MisspelledKw {
44234423
pub is_incorrect_case: bool,
44244424
}
44254425

4426+
#[derive(Diagnostic)]
4427+
#[diag("bounds cannot be used in this context")]
4428+
pub(crate) struct ForbiddenBound {
4429+
#[primary_span]
4430+
pub spans: Vec<Span>,
4431+
}
4432+
44264433
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
44274434
pub(super) enum TokenDescription {
44284435
ReservedIdentifier,

compiler/rustc_parse/src/parser/ty.rs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1433,6 +1433,24 @@ impl<'a> Parser<'a> {
14331433
self.expect_lt()?;
14341434
let params = self.parse_generic_params()?;
14351435
self.expect_gt()?;
1436+
1437+
// Issue 149695
1438+
// Deny and remove bounds for type parameters in higher-ranked binders,
1439+
// otherwise nested items may have parents not in hir.
1440+
let params = params
1441+
.into_iter()
1442+
.map(|mut param| {
1443+
if matches!(param.kind, ast::GenericParamKind::Type { .. })
1444+
&& !param.bounds.is_empty()
1445+
{
1446+
let spans: Vec<_> = param.bounds.iter().map(|b| b.span()).collect();
1447+
self.dcx().emit_err(errors::ForbiddenBound { spans });
1448+
param.bounds.clear();
1449+
}
1450+
param
1451+
})
1452+
.collect::<ThinVec<_>>();
1453+
14361454
// We rely on AST validation to rule out invalid cases: There must not be
14371455
// type or const parameters, and parameters must not have bounds.
14381456
Ok((params, Some(lo.to(self.prev_token.span))))

src/tools/rustfmt/tests/source/non-lifetime-binders.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
fn main() where for<'a, T: Sized + 'a, const C: usize> [&'a T; C]: Sized {
1+
fn main() where for<'a, T, const C: usize> [&'a T; C]: Sized {
22
let x = for<T>
33
|| {};
44

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
//@ edition: 2024
2+
3+
#![feature(non_lifetime_binders)]
4+
#![expect(incomplete_features)]
5+
6+
fn produce() -> for<A: A<{ //~ ERROR expected a type, found a trait
7+
//~^ ERROR bounds cannot be used in this context
8+
//~^^ ERROR late-bound type parameter not allowed on trait object types
9+
#[derive(Hash)]
10+
enum A {}
11+
struct A<A>;
12+
}>> Trait {} //~ ERROR cannot find trait `Trait` in this scope
13+
14+
fn main() {}
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
error: bounds cannot be used in this context
2+
--> $DIR/bad-bounds.rs:6:24
3+
|
4+
LL | fn produce() -> for<A: A<{
5+
| ________________________^
6+
LL | |
7+
LL | |
8+
LL | | #[derive(Hash)]
9+
LL | | enum A {}
10+
LL | | struct A<A>;
11+
LL | | }>> Trait {}
12+
| |__^
13+
14+
error[E0405]: cannot find trait `Trait` in this scope
15+
--> $DIR/bad-bounds.rs:12:5
16+
|
17+
LL | }>> Trait {}
18+
| ^^^^^ not found in this scope
19+
20+
error: late-bound type parameter not allowed on trait object types
21+
--> $DIR/bad-bounds.rs:6:21
22+
|
23+
LL | fn produce() -> for<A: A<{
24+
| ^
25+
26+
error[E0782]: expected a type, found a trait
27+
--> $DIR/bad-bounds.rs:6:17
28+
|
29+
LL | fn produce() -> for<A: A<{
30+
| _________________^
31+
LL | |
32+
LL | |
33+
LL | | #[derive(Hash)]
34+
LL | | enum A {}
35+
LL | | struct A<A>;
36+
LL | | }>> Trait {}
37+
| |_________^
38+
39+
error: aborting due to 4 previous errors
40+
41+
Some errors have detailed explanations: E0405, E0782.
42+
For more information about an error, try `rustc --explain E0405`.

0 commit comments

Comments
 (0)