about summary refs log tree commit diff
path: root/compiler
diff options
context:
space:
mode:
authorMatthias Krüger <matthias.krueger@famsik.de>2021-11-27 11:46:44 +0100
committerGitHub <noreply@github.com>2021-11-27 11:46:44 +0100
commit7c5bcd548be2d2020c1476346304a1cc64078e2f (patch)
tree584a77060ba36a80307abd6c30cf505a118ca3d9 /compiler
parent55f8b5f559ffa61434d844de94963af3c2258276 (diff)
parent4954389a9dccf2e915a639155b7039f1454acc9c (diff)
downloadrust-7c5bcd548be2d2020c1476346304a1cc64078e2f.tar.gz
rust-7c5bcd548be2d2020c1476346304a1cc64078e2f.zip
Rollup merge of #91208 - estebank:eq-constraint, r=cjgillot
Account for incorrect `where T::Assoc = Ty` bound

Provide suggestoin to constrain trait bound for associated type.
Revert incorrect changes to `missing-bounds` test.

Address part of #20041.
Diffstat (limited to 'compiler')
-rw-r--r--compiler/rustc_ast_passes/src/ast_validation.rs49
-rw-r--r--compiler/rustc_ast_passes/src/lib.rs1
2 files changed, 49 insertions, 1 deletions
diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs
index 1822ba6ec99..efc30121987 100644
--- a/compiler/rustc_ast_passes/src/ast_validation.rs
+++ b/compiler/rustc_ast_passes/src/ast_validation.rs
@@ -23,7 +23,7 @@ use rustc_span::symbol::{kw, sym, Ident};
 use rustc_span::Span;
 use rustc_target::spec::abi;
 use std::mem;
-use std::ops::DerefMut;
+use std::ops::{Deref, DerefMut};
 
 const MORE_EXTERN: &str =
     "for more information, visit https://doc.rust-lang.org/std/keyword.extern.html";
@@ -1714,6 +1714,53 @@ fn deny_equality_constraints(
             }
         }
     }
+    // Given `A: Foo, A::Bar = RhsTy`, suggest `A: Foo<Bar = RhsTy>`.
+    if let TyKind::Path(None, full_path) = &predicate.lhs_ty.kind {
+        if let [potential_param, potential_assoc] = &full_path.segments[..] {
+            for param in &generics.params {
+                if param.ident == potential_param.ident {
+                    for bound in &param.bounds {
+                        if let ast::GenericBound::Trait(trait_ref, TraitBoundModifier::None) = bound
+                        {
+                            if let [trait_segment] = &trait_ref.trait_ref.path.segments[..] {
+                                let assoc = pprust::path_to_string(&ast::Path::from_ident(
+                                    potential_assoc.ident,
+                                ));
+                                let ty = pprust::ty_to_string(&predicate.rhs_ty);
+                                let (args, span) = match &trait_segment.args {
+                                    Some(args) => match args.deref() {
+                                        ast::GenericArgs::AngleBracketed(args) => {
+                                            let Some(arg) = args.args.last() else {
+                                                continue;
+                                            };
+                                            (
+                                                format!(", {} = {}", assoc, ty),
+                                                arg.span().shrink_to_hi(),
+                                            )
+                                        }
+                                        _ => continue,
+                                    },
+                                    None => (
+                                        format!("<{} = {}>", assoc, ty),
+                                        trait_segment.span().shrink_to_hi(),
+                                    ),
+                                };
+                                err.multipart_suggestion(
+                                    &format!(
+                                        "if `{}::{}` is an associated type you're trying to set, \
+                                        use the associated type binding syntax",
+                                        trait_segment.ident, potential_assoc.ident,
+                                    ),
+                                    vec![(span, args), (predicate.span, String::new())],
+                                    Applicability::MaybeIncorrect,
+                                );
+                            }
+                        }
+                    }
+                }
+            }
+        }
+    }
     err.note(
         "see issue #20041 <https://github.com/rust-lang/rust/issues/20041> for more information",
     );
diff --git a/compiler/rustc_ast_passes/src/lib.rs b/compiler/rustc_ast_passes/src/lib.rs
index 47666670b2b..adc4d117b80 100644
--- a/compiler/rustc_ast_passes/src/lib.rs
+++ b/compiler/rustc_ast_passes/src/lib.rs
@@ -6,6 +6,7 @@
 
 #![feature(iter_is_partitioned)]
 #![feature(box_patterns)]
+#![feature(let_else)]
 #![recursion_limit = "256"]
 
 pub mod ast_validation;