about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMichael Goulet <michael@errs.io>2024-02-06 19:48:16 +0000
committerMichael Goulet <michael@errs.io>2024-02-10 03:31:34 +0000
commitfde695a2d19fc13a5773b8e9168341c67a21912e (patch)
tree551d9a53ee5d8bf059ad2fc8b2161d020fc43775
parent973bbfbd23df736dd3a257e42c6cd7e3fe5b0281 (diff)
downloadrust-fde695a2d19fc13a5773b8e9168341c67a21912e.tar.gz
rust-fde695a2d19fc13a5773b8e9168341c67a21912e.zip
Add a helpful suggestion
-rw-r--r--compiler/rustc_ast_lowering/messages.ftl1
-rw-r--r--compiler/rustc_ast_lowering/src/errors.rs2
-rw-r--r--compiler/rustc_ast_lowering/src/lib.rs63
-rw-r--r--tests/ui/associated-type-bounds/assoc-type-eq-with-dyn-atb-fail.stderr5
-rw-r--r--tests/ui/associated-type-bounds/dyn-impl-trait-type.stderr12
-rw-r--r--tests/ui/associated-type-bounds/dyn-rpit-and-let.stderr12
-rw-r--r--tests/ui/associated-type-bounds/elision.stderr5
7 files changed, 43 insertions, 57 deletions
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<Span>,
 }
 
 #[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,
-                }
-
-                // 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 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,
-                };
+                // 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,
+                    };
 
-                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);
+                    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 => {
-                        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<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
 
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<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