Skip to content

Commit

Permalink
Add a helpful suggestion
Browse files Browse the repository at this point in the history
  • Loading branch information
compiler-errors committed Feb 8, 2024
1 parent f6a17c5 commit fa92bf8
Show file tree
Hide file tree
Showing 7 changed files with 58 additions and 50 deletions.
1 change: 1 addition & 0 deletions compiler/rustc_ast_lowering/messages.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ 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
2 changes: 2 additions & 0 deletions compiler/rustc_ast_lowering/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,8 @@ pub struct MisplacedImplTrait<'a> {
pub struct MisplacedAssocTyBinding {
#[primary_span]
pub span: Span,
#[suggestion(code = " = impl", applicability = "maybe-incorrect", style = "verbose")]
pub suggestion: Option<Span>,
}

#[derive(Diagnostic, Clone, Copy)]
Expand Down
71 changes: 45 additions & 26 deletions compiler/rustc_ast_lowering/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1088,32 +1088,50 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
AssocConstraintKind::Bound { bounds } => {
enum DesugarKind {
ImplTrait,
Error,
Error(Option<Span>),
Bound,
}

// Piggy-back on the `impl Trait` context to figure out the correct behavior.
let desugar_kind = match itctx {
_ if self.is_in_dyn_type => DesugarKind::Error,

// We are in the return position:
//
// fn foo() -> impl Iterator<Item: Debug>
//
// so desugar to
//
// fn foo() -> impl Iterator<Item = impl Debug>
ImplTraitContext::ReturnPositionOpaqueTy { .. }
| ImplTraitContext::TypeAliasesOpaqueTy { .. } => DesugarKind::ImplTrait,

// 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,
let desugar_kind = if self.is_in_dyn_type {
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());
let colon_span = if bound_end_span.eq_ctxt(constraint.span) {
Some(self.tcx.sess.source_map().next_point(bound_end_span))
} else {
None
};
DesugarKind::Error(colon_span)
}
_ => DesugarKind::Error(None),
}
} else {
match itctx {
// We are in the return position:
//
// fn foo() -> impl Iterator<Item: Debug>
//
// so desugar to
//
// fn foo() -> impl Iterator<Item = impl Debug>
ImplTraitContext::ReturnPositionOpaqueTy { .. }
| ImplTraitContext::TypeAliasesOpaqueTy { .. } => DesugarKind::ImplTrait,

// 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 {
Expand Down Expand Up @@ -1150,10 +1168,11 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {

hir::TypeBindingKind::Constraint { bounds }
}
DesugarKind::Error => {
let guar = self
.dcx()
.emit_err(errors::MisplacedAssocTyBinding { span: constraint.span });
DesugarKind::Error(suggestion) => {
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() }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,11 @@ error: associated type bounds are not allowed in `dyn` types
|
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

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

This file was deleted.

12 changes: 0 additions & 12 deletions tests/ui/associated-type-bounds/dyn-rpit-and-let.stderr

This file was deleted.

5 changes: 5 additions & 0 deletions tests/ui/associated-type-bounds/elision.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,11 @@ error: associated type bounds are not allowed in `dyn` types
|
LL | fn f(x: &mut dyn Iterator<Item: Iterator<Item = &'_ ()>>) -> Option<&'_ ()> { x.next() }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
help: use `impl Trait` to introduce a type instead
|
LL | fn f(x: &mut dyn Iterator<Item = impl Iterator<Item = &'_ ()>>) -> Option<&'_ ()> { x.next() }
| ~~~~~~

error: aborting due to 2 previous errors

Expand Down

0 comments on commit fa92bf8

Please sign in to comment.