Skip to content

Commit e7c4908

Browse files
Move associated type bounds check to ast lowering
This makes the check for when associated type bounds more accurate
1 parent b869e84 commit e7c4908

12 files changed

+168
-136
lines changed

compiler/rustc_ast_lowering/locales/en-US.ftl

+3
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,9 @@ ast_lowering_remove_parentheses = remove these parentheses
1919
ast_lowering_misplaced_impl_trait =
2020
`impl Trait` only allowed in function and inherent method return types, not in {$position}
2121
22+
ast_lowering_misplaced_assoc_ty_binding =
23+
associated type bounds are only allowed in where clauses and function signatures, not in {$position}
24+
2225
ast_lowering_rustc_box_attribute_error =
2326
#[rustc_box] requires precisely one argument and no other attributes are allowed
2427

compiler/rustc_ast_lowering/src/errors.rs

+8
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,14 @@ pub struct MisplacedImplTrait<'a> {
7979
pub position: DiagnosticArgFromDisplay<'a>,
8080
}
8181

82+
#[derive(Diagnostic)]
83+
#[diag(ast_lowering_misplaced_assoc_ty_binding)]
84+
pub struct MisplacedAssocTyBinding<'a> {
85+
#[primary_span]
86+
pub span: Span,
87+
pub position: DiagnosticArgFromDisplay<'a>,
88+
}
89+
8290
#[derive(Diagnostic, Clone, Copy)]
8391
#[diag(ast_lowering_rustc_box_attribute_error)]
8492
pub struct RustcBoxAttributeError {

compiler/rustc_ast_lowering/src/lib.rs

+7-3
Original file line numberDiff line numberDiff line change
@@ -1002,8 +1002,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
10021002
} else {
10031003
self.arena.alloc(hir::GenericArgs::none())
10041004
};
1005-
let itctx_tait = &ImplTraitContext::TypeAliasesOpaqueTy;
1006-
10071005
let kind = match &constraint.kind {
10081006
AssocConstraintKind::Equality { term } => {
10091007
let term = match term {
@@ -1040,7 +1038,13 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
10401038
// then to an opaque type).
10411039
//
10421040
// FIXME: this is only needed until `impl Trait` is allowed in type aliases.
1043-
ImplTraitContext::Disallowed(_) if self.is_in_dyn_type => (true, itctx_tait),
1041+
ImplTraitContext::Disallowed(position) if self.is_in_dyn_type => {
1042+
self.tcx.sess.emit_err(errors::MisplacedAssocTyBinding {
1043+
span: constraint.span,
1044+
position: DiagnosticArgFromDisplay(position),
1045+
});
1046+
(false, itctx)
1047+
}
10441048

10451049
// We are in the parameter position, but not within a dyn type:
10461050
//

compiler/rustc_ast_passes/locales/en-US.ftl

-3
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,6 @@ ast_passes_forbidden_let_stable =
1111
ast_passes_deprecated_where_clause_location =
1212
where clause not allowed here
1313
14-
ast_passes_forbidden_assoc_constraint =
15-
associated type bounds are not allowed within structs, enums, or unions
16-
1714
ast_passes_keyword_lifetime =
1815
lifetimes cannot use keyword names
1916

compiler/rustc_ast_passes/src/ast_validation.rs

+1-32
Original file line numberDiff line numberDiff line change
@@ -71,10 +71,6 @@ struct AstValidator<'a> {
7171
/// or `Foo::Bar<impl Trait>`
7272
is_impl_trait_banned: bool,
7373

74-
/// Used to ban associated type bounds (i.e., `Type<AssocType: Bounds>`) in
75-
/// certain positions.
76-
is_assoc_ty_bound_banned: bool,
77-
7874
/// See [ForbiddenLetReason]
7975
forbidden_let_reason: Option<ForbiddenLetReason>,
8076

@@ -180,30 +176,12 @@ impl<'a> AstValidator<'a> {
180176
}
181177
}
182178

183-
fn with_banned_assoc_ty_bound(&mut self, f: impl FnOnce(&mut Self)) {
184-
let old = mem::replace(&mut self.is_assoc_ty_bound_banned, true);
185-
f(self);
186-
self.is_assoc_ty_bound_banned = old;
187-
}
188-
189179
fn with_impl_trait(&mut self, outer: Option<Span>, f: impl FnOnce(&mut Self)) {
190180
let old = mem::replace(&mut self.outer_impl_trait, outer);
191181
f(self);
192182
self.outer_impl_trait = old;
193183
}
194184

195-
fn visit_assoc_constraint_from_generic_args(&mut self, constraint: &'a AssocConstraint) {
196-
match constraint.kind {
197-
AssocConstraintKind::Equality { .. } => {}
198-
AssocConstraintKind::Bound { .. } => {
199-
if self.is_assoc_ty_bound_banned {
200-
self.session.emit_err(ForbiddenAssocConstraint { span: constraint.span });
201-
}
202-
}
203-
}
204-
self.visit_assoc_constraint(constraint);
205-
}
206-
207185
// Mirrors `visit::walk_ty`, but tracks relevant state.
208186
fn walk_ty(&mut self, t: &'a Ty) {
209187
match &t.kind {
@@ -1248,7 +1226,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
12481226
// are allowed to contain nested `impl Trait`.
12491227
AngleBracketedArg::Constraint(constraint) => {
12501228
self.with_impl_trait(None, |this| {
1251-
this.visit_assoc_constraint_from_generic_args(constraint);
1229+
this.visit_assoc_constraint(constraint);
12521230
});
12531231
}
12541232
}
@@ -1373,14 +1351,6 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
13731351
visit::walk_param_bound(self, bound)
13741352
}
13751353

1376-
fn visit_variant_data(&mut self, s: &'a VariantData) {
1377-
self.with_banned_assoc_ty_bound(|this| visit::walk_struct_def(this, s))
1378-
}
1379-
1380-
fn visit_enum_def(&mut self, enum_definition: &'a EnumDef) {
1381-
self.with_banned_assoc_ty_bound(|this| visit::walk_enum_def(this, enum_definition))
1382-
}
1383-
13841354
fn visit_fn(&mut self, fk: FnKind<'a>, span: Span, id: NodeId) {
13851355
// Only associated `fn`s can have `self` parameters.
13861356
let self_semantic = match fk.ctxt() {
@@ -1709,7 +1679,6 @@ pub fn check_crate(session: &Session, krate: &Crate, lints: &mut LintBuffer) ->
17091679
outer_impl_trait: None,
17101680
disallow_tilde_const: None,
17111681
is_impl_trait_banned: false,
1712-
is_assoc_ty_bound_banned: false,
17131682
forbidden_let_reason: Some(ForbiddenLetReason::GenericForbidden),
17141683
lint_buffer: lints,
17151684
};

compiler/rustc_ast_passes/src/errors.rs

-7
Original file line numberDiff line numberDiff line change
@@ -23,13 +23,6 @@ pub struct ForbiddenLetStable {
2323
pub span: Span,
2424
}
2525

26-
#[derive(Diagnostic)]
27-
#[diag(ast_passes_forbidden_assoc_constraint)]
28-
pub struct ForbiddenAssocConstraint {
29-
#[primary_span]
30-
pub span: Span,
31-
}
32-
3326
#[derive(Diagnostic)]
3427
#[diag(ast_passes_keyword_lifetime)]
3528
pub struct KeywordLifetime {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
#![feature(associated_type_bounds)]
2+
3+
trait B {
4+
type AssocType;
5+
}
6+
7+
fn f()
8+
where
9+
dyn for<'j> B<AssocType: 'j>:,
10+
//~^ ERROR associated type bounds are only allowed in where clauses and function signatures
11+
//~| ERROR the value of the associated type `AssocType` (from trait `B`) must be specified
12+
{
13+
}
14+
15+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
error: associated type bounds are only allowed in where clauses and function signatures, not in bound
2+
--> $DIR/bad-universal-in-dyn-in-where-clause.rs:9:19
3+
|
4+
LL | dyn for<'j> B<AssocType: 'j>:,
5+
| ^^^^^^^^^^^^^
6+
7+
error[E0191]: the value of the associated type `AssocType` (from trait `B`) must be specified
8+
--> $DIR/bad-universal-in-dyn-in-where-clause.rs:9:9
9+
|
10+
LL | type AssocType;
11+
| -------------- `AssocType` defined here
12+
...
13+
LL | dyn for<'j> B<AssocType: 'j>:,
14+
| ^^^^^^^^^^^^^^^^^^^^^^^^ help: specify the associated type: `for<'j> B<AssocType: 'j, AssocType = Type>`
15+
16+
error: aborting due to 2 previous errors
17+
18+
For more information about this error, try `rustc --explain E0191`.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
#![feature(associated_type_bounds)]
2+
3+
trait Trait {
4+
type Item;
5+
}
6+
7+
trait Trait2 {}
8+
9+
// It's not possible to insert a universal `impl Trait` here!
10+
impl dyn Trait<Item: Trait2> {}
11+
//~^ ERROR associated type bounds are only allowed in where clauses and function signatures
12+
//~| ERROR the value of the associated type `Item` (from trait `Trait`) must be specified
13+
14+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
error: associated type bounds are only allowed in where clauses and function signatures, not in impl header
2+
--> $DIR/bad-universal-in-impl-sig.rs:10:16
3+
|
4+
LL | impl dyn Trait<Item: Trait2> {}
5+
| ^^^^^^^^^^^^
6+
7+
error: aborting due to previous error
8+

tests/ui/associated-type-bounds/inside-adt.rs

+18-13
Original file line numberDiff line numberDiff line change
@@ -3,28 +3,33 @@
33
use std::mem::ManuallyDrop;
44

55
struct S1 { f: dyn Iterator<Item: Copy> }
6-
//~^ ERROR associated type bounds are not allowed within structs, enums, or unions
6+
//~^ ERROR associated type bounds are only allowed in where clauses and function signatures
7+
//~| ERROR the value of the associated type `Item` (from trait `Iterator`) must be specified
78
struct S2 { f: Box<dyn Iterator<Item: Copy>> }
8-
//~^ ERROR associated type bounds are not allowed within structs, enums, or unions
9+
//~^ ERROR associated type bounds are only allowed in where clauses and function signatures
10+
//~| ERROR the value of the associated type `Item` (from trait `Iterator`) must be specified
911
struct S3 { f: dyn Iterator<Item: 'static> }
10-
//~^ ERROR associated type bounds are not allowed within structs, enums, or unions
12+
//~^ ERROR associated type bounds are only allowed in where clauses and function signatures
13+
//~| ERROR the value of the associated type `Item` (from trait `Iterator`) must be specified
1114

1215
enum E1 { V(dyn Iterator<Item: Copy>) }
13-
//~^ ERROR associated type bounds are not allowed within structs, enums, or unions
14-
//~| ERROR the size for values of type `(dyn Iterator<Item = impl Copy> + 'static)`
16+
//~^ ERROR associated type bounds are only allowed in where clauses and function signatures
17+
//~| ERROR the value of the associated type `Item` (from trait `Iterator`) must be specified
1518
enum E2 { V(Box<dyn Iterator<Item: Copy>>) }
16-
//~^ ERROR associated type bounds are not allowed within structs, enums, or unions
19+
//~^ ERROR associated type bounds are only allowed in where clauses and function signatures
20+
//~| ERROR the value of the associated type `Item` (from trait `Iterator`) must be specified
1721
enum E3 { V(dyn Iterator<Item: 'static>) }
18-
//~^ ERROR associated type bounds are not allowed within structs, enums, or unions
19-
//~| ERROR the size for values of type `(dyn Iterator<Item = impl Sized + 'static> + 'static)`
22+
//~^ ERROR associated type bounds are only allowed in where clauses and function signatures
23+
//~| ERROR the value of the associated type `Item` (from trait `Iterator`) must be specified
2024

2125
union U1 { f: ManuallyDrop<dyn Iterator<Item: Copy>> }
22-
//~^ ERROR associated type bounds are not allowed within structs, enums, or unions
23-
//~| ERROR the size for values of type `(dyn Iterator<Item = impl Copy> + 'static)`
26+
//~^ ERROR associated type bounds are only allowed in where clauses and function signatures
27+
//~| ERROR the value of the associated type `Item` (from trait `Iterator`) must be specified
2428
union U2 { f: ManuallyDrop<Box<dyn Iterator<Item: Copy>>> }
25-
//~^ ERROR associated type bounds are not allowed within structs, enums, or unions
29+
//~^ ERROR associated type bounds are only allowed in where clauses and function signatures
30+
//~| ERROR the value of the associated type `Item` (from trait `Iterator`) must be specified
2631
union U3 { f: ManuallyDrop<dyn Iterator<Item: 'static>> }
27-
//~^ ERROR associated type bounds are not allowed within structs, enums, or unions
28-
//~| ERROR the size for values of type `(dyn Iterator<Item = impl Sized + 'static> + 'static)`
32+
//~^ ERROR associated type bounds are only allowed in where clauses and function signatures
33+
//~| ERROR the value of the associated type `Item` (from trait `Iterator`) must be specified
2934

3035
fn main() {}

0 commit comments

Comments
 (0)