Skip to content

Commit

Permalink
Rollup merge of rust-lang#120719 - compiler-errors:no-dyn-atb, r=lcnr
Browse files Browse the repository at this point in the history
Remove support for `associated_type_bound` nested in `dyn` types

These necessarily desugar to `impl Trait`, which is inconsistent with the `associated_type_bound` feature after rust-lang#120584.

This PR keeps the `is_in_dyn_type` hack, which kind of makes me sad. Ideally, we'd be validating that no object types have associated type bounds somewhere else. Unfortunately, we can't do this later during astconv (i think?), nor can we do it earlier during ast validation (i think?) because of the feature gating of ATB being a *warning* rather than an *error*. Let me know if you have thoughts about this.

r? lcnr
  • Loading branch information
matthiaskrgr authored Feb 10, 2024
2 parents 37893f9 + e6f5af9 commit 9b3c5e1
Show file tree
Hide file tree
Showing 24 changed files with 91 additions and 429 deletions.
7 changes: 4 additions & 3 deletions compiler/rustc_ast_lowering/messages.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@ ast_lowering_arbitrary_expression_in_pattern =
ast_lowering_argument = argument
ast_lowering_assoc_ty_binding_in_dyn =
associated type bounds are not allowed in `dyn` types
.suggestion = use `impl Trait` to introduce a type instead
ast_lowering_assoc_ty_parentheses =
parenthesized generic arguments cannot be used in associated type constraints
Expand Down Expand Up @@ -100,9 +104,6 @@ ast_lowering_match_arm_with_no_body =
`match` arm with no body
.suggestion = add a body after the pattern
ast_lowering_misplaced_assoc_ty_binding =
associated type bounds are only allowed in where clauses and function signatures, not in {$position}
ast_lowering_misplaced_double_dot =
`..` patterns are not allowed here
.note = only allowed in tuple, tuple struct, and slice patterns
Expand Down
7 changes: 4 additions & 3 deletions compiler/rustc_ast_lowering/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -94,11 +94,12 @@ pub struct MisplacedImplTrait<'a> {
}

#[derive(Diagnostic)]
#[diag(ast_lowering_misplaced_assoc_ty_binding)]
pub struct MisplacedAssocTyBinding<'a> {
#[diag(ast_lowering_assoc_ty_binding_in_dyn)]
pub struct MisplacedAssocTyBinding {
#[primary_span]
pub span: Span,
pub position: DiagnosticArgFromDisplay<'a>,
#[suggestion(code = " = impl", applicability = "maybe-incorrect", style = "verbose")]
pub suggestion: Option<Span>,
}

#[derive(Diagnostic, Clone, Copy)]
Expand Down
116 changes: 30 additions & 86 deletions compiler/rustc_ast_lowering/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -197,7 +197,6 @@ trait ResolverAstLoweringExt {
fn get_label_res(&self, id: NodeId) -> Option<NodeId>;
fn get_lifetime_res(&self, id: NodeId) -> Option<LifetimeRes>;
fn take_extra_lifetime_params(&mut self, id: NodeId) -> Vec<(Ident, NodeId, LifetimeRes)>;
fn remap_extra_lifetime_params(&mut self, from: NodeId, to: NodeId);
}

impl ResolverAstLoweringExt for ResolverAstLowering {
Expand Down Expand Up @@ -256,11 +255,6 @@ impl ResolverAstLoweringExt for ResolverAstLowering {
fn take_extra_lifetime_params(&mut self, id: NodeId) -> Vec<(Ident, NodeId, LifetimeRes)> {
self.extra_lifetime_params_map.remove(&id).unwrap_or_default()
}

fn remap_extra_lifetime_params(&mut self, from: NodeId, to: NodeId) {
let lifetimes = self.extra_lifetime_params_map.remove(&from).unwrap_or_default();
self.extra_lifetime_params_map.insert(to, lifetimes);
}
}

/// Context of `impl Trait` in code, which determines whether it is allowed in an HIR subtree,
Expand Down Expand Up @@ -1084,88 +1078,38 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
hir::TypeBindingKind::Equality { term }
}
AssocConstraintKind::Bound { bounds } => {
enum DesugarKind {
ImplTrait,
Error(ImplTraitPosition),
Bound,
}

// Piggy-back on the `impl Trait` context to figure out the correct behavior.
let desugar_kind = match itctx {
// in an argument, RPIT, or TAIT, if we are within a dyn type:
//
// fn foo(x: dyn Iterator<Item: Debug>)
//
// then desugar to:
//
// fn foo(x: dyn Iterator<Item = impl Debug>)
//
// This is because dyn traits must have all of their associated types specified.
ImplTraitContext::ReturnPositionOpaqueTy { .. }
| ImplTraitContext::TypeAliasesOpaqueTy { .. }
| ImplTraitContext::Universal
if self.is_in_dyn_type =>
{
DesugarKind::ImplTrait
}

ImplTraitContext::Disallowed(position) if self.is_in_dyn_type => {
DesugarKind::Error(position)
}

// We are in the parameter position, but not within a dyn type:
//
// fn foo(x: impl Iterator<Item: Debug>)
//
// so we leave it as is and this gets expanded in astconv to a bound like
// `<T as Iterator>::Item: Debug` where `T` is the type parameter for the
// `impl Iterator`.
_ => DesugarKind::Bound,
};

match desugar_kind {
DesugarKind::ImplTrait => {
// Desugar `AssocTy: Bounds` into `AssocTy = impl Bounds`. We do this by
// constructing the HIR for `impl bounds...` and then lowering that.

let impl_trait_node_id = self.next_node_id();
// Shift `impl Trait` lifetime captures from the associated type bound's
// node id to the opaque node id, so that the opaque can actually use
// these lifetime bounds.
self.resolver
.remap_extra_lifetime_params(constraint.id, impl_trait_node_id);

self.with_dyn_type_scope(false, |this| {
let node_id = this.next_node_id();
let ty = this.lower_ty(
&Ty {
id: node_id,
kind: TyKind::ImplTrait(impl_trait_node_id, bounds.clone()),
span: this.lower_span(constraint.span),
tokens: None,
},
itctx,
);
// Disallow ATB in dyn types
if self.is_in_dyn_type {
let suggestion = match itctx {
ImplTraitContext::ReturnPositionOpaqueTy { .. }
| ImplTraitContext::TypeAliasesOpaqueTy { .. }
| ImplTraitContext::Universal => {
let bound_end_span = constraint
.gen_args
.as_ref()
.map_or(constraint.ident.span, |args| args.span());
if bound_end_span.eq_ctxt(constraint.span) {
Some(self.tcx.sess.source_map().next_point(bound_end_span))
} else {
None
}
}
_ => None,
};

hir::TypeBindingKind::Equality { term: ty.into() }
})
}
DesugarKind::Bound => {
// Desugar `AssocTy: Bounds` into a type binding where the
// later desugars into a trait predicate.
let bounds = self.lower_param_bounds(bounds, itctx);
let guar = self.dcx().emit_err(errors::MisplacedAssocTyBinding {
span: constraint.span,
suggestion,
});
let err_ty =
&*self.arena.alloc(self.ty(constraint.span, hir::TyKind::Err(guar)));
hir::TypeBindingKind::Equality { term: err_ty.into() }
} else {
// Desugar `AssocTy: Bounds` into a type binding where the
// later desugars into a trait predicate.
let bounds = self.lower_param_bounds(bounds, itctx);

hir::TypeBindingKind::Constraint { bounds }
}
DesugarKind::Error(position) => {
let guar = self.dcx().emit_err(errors::MisplacedAssocTyBinding {
span: constraint.span,
position: DiagnosticArgFromDisplay(&position),
});
let err_ty =
&*self.arena.alloc(self.ty(constraint.span, hir::TyKind::Err(guar)));
hir::TypeBindingKind::Equality { term: err_ty.into() }
}
hir::TypeBindingKind::Constraint { bounds }
}
}
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,9 @@ impl Bar for AssocNoCopy {

impl Thing for AssocNoCopy {
type Out = Box<dyn Bar<Assoc: Copy>>;
//~^ ERROR associated type bounds are not allowed in `dyn` types

fn func() -> Self::Out {
//~^ ERROR the trait bound `String: Copy` is not satisfied
Box::new(AssocNoCopy)
}
}
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
error[E0277]: the trait bound `String: Copy` is not satisfied
--> $DIR/assoc-type-eq-with-dyn-atb-fail.rs:32:18
error: associated type bounds are not allowed in `dyn` types
--> $DIR/assoc-type-eq-with-dyn-atb-fail.rs:30:28
|
LL | fn func() -> Self::Out {
| ^^^^^^^^^ the trait `Copy` is not implemented for `String`
LL | type Out = Box<dyn Bar<Assoc: Copy>>;
| ^^^^^^^^^^^
|
help: use `impl Trait` to introduce a type instead
|
LL | type Out = Box<dyn Bar<Assoc = impl Copy>>;
| ~~~~~~

error: aborting due to 1 previous error

For more information about this error, try `rustc --explain E0277`.
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ trait B {
fn f()
where
dyn for<'j> B<AssocType: 'j>:,
//~^ ERROR associated type bounds are only allowed in where clauses and function signatures
//~^ ERROR associated type bounds are not allowed in `dyn` types
{
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
error: associated type bounds are only allowed in where clauses and function signatures, not in bounds
error: associated type bounds are not allowed in `dyn` types
--> $DIR/bad-universal-in-dyn-in-where-clause.rs:9:19
|
LL | dyn for<'j> B<AssocType: 'j>:,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,6 @@ trait Trait2 {}

// It's not possible to insert a universal `impl Trait` here!
impl dyn Trait<Item: Trait2> {}
//~^ ERROR associated type bounds are only allowed in where clauses and function signatures
//~^ ERROR associated type bounds are not allowed in `dyn` types

fn main() {}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
error: associated type bounds are only allowed in where clauses and function signatures, not in impl headers
error: associated type bounds are not allowed in `dyn` types
--> $DIR/bad-universal-in-impl-sig.rs:10:16
|
LL | impl dyn Trait<Item: Trait2> {}
Expand Down
7 changes: 0 additions & 7 deletions tests/ui/associated-type-bounds/duplicate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -261,11 +261,4 @@ trait TRA3 {
//~^ ERROR the value of the associated type `Item` in trait `Iterator` is already specified [E0719]
}

type TADyn1 = dyn Iterator<Item: Copy, Item: Send>;
//~^ ERROR the value of the associated type `Item` in trait `Iterator` is already specified [E0719]
type TADyn2 = Box<dyn Iterator<Item: Copy, Item: Copy>>;
//~^ ERROR the value of the associated type `Item` in trait `Iterator` is already specified [E0719]
type TADyn3 = dyn Iterator<Item: 'static, Item: 'static>;
//~^ ERROR the value of the associated type `Item` in trait `Iterator` is already specified [E0719]

fn main() {}
26 changes: 1 addition & 25 deletions tests/ui/associated-type-bounds/duplicate.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -6,30 +6,6 @@ LL | struct SI1<T: Iterator<Item: Copy, Item: Send>> {
| |
| `Item` bound here first

error[E0719]: the value of the associated type `Item` in trait `Iterator` is already specified
--> $DIR/duplicate.rs:264:40
|
LL | type TADyn1 = dyn Iterator<Item: Copy, Item: Send>;
| ---------- ^^^^^^^^^^ re-bound here
| |
| `Item` bound here first

error[E0719]: the value of the associated type `Item` in trait `Iterator` is already specified
--> $DIR/duplicate.rs:266:44
|
LL | type TADyn2 = Box<dyn Iterator<Item: Copy, Item: Copy>>;
| ---------- ^^^^^^^^^^ re-bound here
| |
| `Item` bound here first

error[E0719]: the value of the associated type `Item` in trait `Iterator` is already specified
--> $DIR/duplicate.rs:268:43
|
LL | type TADyn3 = dyn Iterator<Item: 'static, Item: 'static>;
| ------------- ^^^^^^^^^^^^^ re-bound here
| |
| `Item` bound here first

error[E0719]: the value of the associated type `Item` in trait `Iterator` is already specified
--> $DIR/duplicate.rs:11:36
|
Expand Down Expand Up @@ -631,7 +607,7 @@ LL | Self: Iterator<Item: 'static, Item: 'static>,
|
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`

error: aborting due to 75 previous errors
error: aborting due to 72 previous errors

Some errors have detailed explanations: E0282, E0719.
For more information about an error, try `rustc --explain E0282`.
66 changes: 0 additions & 66 deletions tests/ui/associated-type-bounds/dyn-impl-trait-type.rs

This file was deleted.

12 changes: 0 additions & 12 deletions tests/ui/associated-type-bounds/dyn-impl-trait-type.stderr

This file was deleted.

Loading

0 comments on commit 9b3c5e1

Please sign in to comment.