From fde695a2d19fc13a5773b8e9168341c67a21912e Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Tue, 6 Feb 2024 19:48:16 +0000 Subject: [PATCH] Add a helpful suggestion --- compiler/rustc_ast_lowering/messages.ftl | 1 + compiler/rustc_ast_lowering/src/errors.rs | 2 + compiler/rustc_ast_lowering/src/lib.rs | 63 +++++++++---------- .../assoc-type-eq-with-dyn-atb-fail.stderr | 5 ++ .../dyn-impl-trait-type.stderr | 12 ---- .../dyn-rpit-and-let.stderr | 12 ---- .../ui/associated-type-bounds/elision.stderr | 5 ++ 7 files changed, 43 insertions(+), 57 deletions(-) delete mode 100644 tests/ui/associated-type-bounds/dyn-impl-trait-type.stderr delete mode 100644 tests/ui/associated-type-bounds/dyn-rpit-and-let.stderr diff --git a/compiler/rustc_ast_lowering/messages.ftl b/compiler/rustc_ast_lowering/messages.ftl index 9c151ec80ee..e87cf05713c 100644 --- a/compiler/rustc_ast_lowering/messages.ftl +++ b/compiler/rustc_ast_lowering/messages.ftl @@ -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 diff --git a/compiler/rustc_ast_lowering/src/errors.rs b/compiler/rustc_ast_lowering/src/errors.rs index fba8ea206f1..274e6b7458c 100644 --- a/compiler/rustc_ast_lowering/src/errors.rs +++ b/compiler/rustc_ast_lowering/src/errors.rs @@ -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, } #[derive(Diagnostic, Clone, Copy)] diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 48cc301219a..7c89600fa28 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -1084,41 +1084,38 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { hir::TypeBindingKind::Equality { term } } AssocConstraintKind::Bound { bounds } => { - enum DesugarKind { - Error, - Bound, - } + // 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, + }; - // 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, + 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); - // We are in the parameter position, but not within a dyn type: - // - // fn foo(x: impl Iterator) - // - // so we leave it as is and this gets expanded in astconv to a bound like - // `::Item: Debug` where `T` is the type parameter for the - // `impl Iterator`. - _ => DesugarKind::Bound, - }; - - match desugar_kind { - 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); - - hir::TypeBindingKind::Constraint { bounds } - } - DesugarKind::Error => { - let guar = self - .dcx() - .emit_err(errors::MisplacedAssocTyBinding { span: constraint.span }); - 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 } } } }; diff --git a/tests/ui/associated-type-bounds/assoc-type-eq-with-dyn-atb-fail.stderr b/tests/ui/associated-type-bounds/assoc-type-eq-with-dyn-atb-fail.stderr index 2d38bbd8c92..ad540909411 100644 --- a/tests/ui/associated-type-bounds/assoc-type-eq-with-dyn-atb-fail.stderr +++ b/tests/ui/associated-type-bounds/assoc-type-eq-with-dyn-atb-fail.stderr @@ -3,6 +3,11 @@ error: associated type bounds are not allowed in `dyn` types | LL | type Out = Box>; | ^^^^^^^^^^^ + | +help: use `impl Trait` to introduce a type instead + | +LL | type Out = Box>; + | ~~~~~~ error: aborting due to 1 previous error diff --git a/tests/ui/associated-type-bounds/dyn-impl-trait-type.stderr b/tests/ui/associated-type-bounds/dyn-impl-trait-type.stderr deleted file mode 100644 index 2e26a434f5d..00000000000 --- a/tests/ui/associated-type-bounds/dyn-impl-trait-type.stderr +++ /dev/null @@ -1,12 +0,0 @@ -warning: method `tr2` is never used - --> $DIR/dyn-impl-trait-type.rs:8:20 - | -LL | trait Tr2<'a> { fn tr2(self) -> &'a Self; } - | --- ^^^ - | | - | method in this trait - | - = note: `#[warn(dead_code)]` on by default - -warning: 1 warning emitted - diff --git a/tests/ui/associated-type-bounds/dyn-rpit-and-let.stderr b/tests/ui/associated-type-bounds/dyn-rpit-and-let.stderr deleted file mode 100644 index 9eddbe46284..00000000000 --- a/tests/ui/associated-type-bounds/dyn-rpit-and-let.stderr +++ /dev/null @@ -1,12 +0,0 @@ -warning: method `tr2` is never used - --> $DIR/dyn-rpit-and-let.rs:10:20 - | -LL | trait Tr2<'a> { fn tr2(self) -> &'a Self; } - | --- ^^^ - | | - | method in this trait - | - = note: `#[warn(dead_code)]` on by default - -warning: 1 warning emitted - diff --git a/tests/ui/associated-type-bounds/elision.stderr b/tests/ui/associated-type-bounds/elision.stderr index 70302d25b2b..749dffdc4d3 100644 --- a/tests/ui/associated-type-bounds/elision.stderr +++ b/tests/ui/associated-type-bounds/elision.stderr @@ -15,6 +15,11 @@ error: associated type bounds are not allowed in `dyn` types | LL | fn f(x: &mut dyn Iterator>) -> Option<&'_ ()> { x.next() } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: use `impl Trait` to introduce a type instead + | +LL | fn f(x: &mut dyn Iterator>) -> Option<&'_ ()> { x.next() } + | ~~~~~~ error: aborting due to 2 previous errors