about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_borrowck/src/type_check/input_output.rs60
-rw-r--r--compiler/rustc_borrowck/src/type_check/mod.rs5
-rw-r--r--compiler/rustc_hir/src/hir.rs16
-rw-r--r--compiler/rustc_middle/src/ty/sty.rs4
-rw-r--r--compiler/rustc_mir_build/src/build/matches/mod.rs2
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs13
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs59
-rw-r--r--compiler/rustc_typeck/src/check/method/suggest.rs20
-rw-r--r--compiler/rustc_typeck/src/collect.rs22
-rwxr-xr-xsrc/ci/run.sh2
-rw-r--r--src/test/ui/borrowck/issue-80772.rs21
-rw-r--r--src/test/ui/consts/const_discriminant.rs7
-rw-r--r--src/test/ui/derives/deriving-copyclone.stderr6
-rw-r--r--src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-90612.rs43
-rw-r--r--src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-90638.rs37
-rw-r--r--src/test/ui/suggest-using-chars.rs7
-rw-r--r--src/test/ui/suggest-using-chars.stderr48
-rw-r--r--src/test/ui/suggestions/issue-85945-check-where-clause-before-suggesting-unsized.rs8
-rw-r--r--src/test/ui/suggestions/issue-85945-check-where-clause-before-suggesting-unsized.stderr18
-rw-r--r--src/test/ui/traits/negative-impls/negated-auto-traits-error.stderr12
-rw-r--r--src/test/ui/typeck/issue-90804-incorrect-reference-suggestion.rs11
-rw-r--r--src/test/ui/typeck/issue-90804-incorrect-reference-suggestion.stderr17
22 files changed, 342 insertions, 96 deletions
diff --git a/compiler/rustc_borrowck/src/type_check/input_output.rs b/compiler/rustc_borrowck/src/type_check/input_output.rs
index 24332690bec..92d2d04f23f 100644
--- a/compiler/rustc_borrowck/src/type_check/input_output.rs
+++ b/compiler/rustc_borrowck/src/type_check/input_output.rs
@@ -7,13 +7,16 @@
 //! `RETURN_PLACE` the MIR arguments) are always fully normalized (and
 //! contain revealed `impl Trait` values).
 
+use crate::type_check::constraint_conversion::ConstraintConversion;
 use rustc_index::vec::Idx;
 use rustc_infer::infer::LateBoundRegionConversionTime;
 use rustc_middle::mir::*;
-use rustc_middle::traits::ObligationCause;
-use rustc_middle::ty::{self, Ty};
+use rustc_middle::ty::Ty;
 use rustc_span::Span;
-use rustc_trait_selection::traits::query::normalize::AtExt;
+use rustc_span::DUMMY_SP;
+use rustc_trait_selection::traits::query::type_op::{self, TypeOp};
+use rustc_trait_selection::traits::query::Fallible;
+use type_op::TypeOpOutput;
 
 use crate::universal_regions::UniversalRegions;
 
@@ -30,6 +33,9 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
         let (&normalized_output_ty, normalized_input_tys) =
             normalized_inputs_and_output.split_last().unwrap();
 
+        debug!(?normalized_output_ty);
+        debug!(?normalized_input_tys);
+
         let mir_def_id = body.source.def_id().expect_local();
 
         // If the user explicitly annotated the input types, extract
@@ -75,10 +81,12 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
                     .delay_span_bug(body.span, "found more normalized_input_ty than local_decls");
                 break;
             }
+
             // In MIR, argument N is stored in local N+1.
             let local = Local::new(argument_index + 1);
 
             let mir_input_ty = body.local_decls[local].ty;
+
             let mir_input_span = body.local_decls[local].source_info.span;
             self.equate_normalized_input_or_output(
                 normalized_input_ty,
@@ -100,6 +108,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
                 // If the user explicitly annotated the input types, enforce those.
                 let user_provided_input_ty =
                     self.normalize(user_provided_input_ty, Locations::All(mir_input_span));
+
                 self.equate_normalized_input_or_output(
                     user_provided_input_ty,
                     mir_input_ty,
@@ -167,30 +176,14 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
             // `rustc_traits::normalize_after_erasing_regions`. Ideally, we'd
             // like to normalize *before* inserting into `local_decls`, but
             // doing so ends up causing some other trouble.
-            let b = match self
-                .infcx
-                .at(&ObligationCause::dummy(), ty::ParamEnv::empty())
-                .normalize(b)
-            {
-                Ok(n) => {
-                    debug!("equate_inputs_and_outputs: {:?}", n);
-                    if n.obligations.iter().all(|o| {
-                        matches!(
-                            o.predicate.kind().skip_binder(),
-                            ty::PredicateKind::RegionOutlives(_)
-                                | ty::PredicateKind::TypeOutlives(_)
-                        )
-                    }) {
-                        n.value
-                    } else {
-                        b
-                    }
-                }
+            let b = match self.normalize_and_add_constraints(b) {
+                Ok(n) => n,
                 Err(_) => {
                     debug!("equate_inputs_and_outputs: NoSolution");
                     b
                 }
             };
+
             // Note: if we have to introduce new placeholders during normalization above, then we won't have
             // added those universes to the universe info, which we would want in `relate_tys`.
             if let Err(terr) =
@@ -207,4 +200,27 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
             }
         }
     }
+
+    pub(crate) fn normalize_and_add_constraints(&mut self, t: Ty<'tcx>) -> Fallible<Ty<'tcx>> {
+        let TypeOpOutput { output: norm_ty, constraints, .. } =
+            self.param_env.and(type_op::normalize::Normalize::new(t)).fully_perform(self.infcx)?;
+
+        debug!("{:?} normalized to {:?}", t, norm_ty);
+
+        for data in constraints.into_iter().collect::<Vec<_>>() {
+            ConstraintConversion::new(
+                self.infcx,
+                &self.borrowck_context.universal_regions,
+                &self.region_bound_pairs,
+                Some(self.implicit_region_bound),
+                self.param_env,
+                Locations::All(DUMMY_SP),
+                ConstraintCategory::Internal,
+                &mut self.borrowck_context.constraints,
+            )
+            .convert_all(&*data);
+        }
+
+        Ok(norm_ty)
+    }
 }
diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs
index ddd077c22fa..da26d9c7b87 100644
--- a/compiler/rustc_borrowck/src/type_check/mod.rs
+++ b/compiler/rustc_borrowck/src/type_check/mod.rs
@@ -893,11 +893,11 @@ struct TypeChecker<'a, 'tcx> {
 }
 
 struct BorrowCheckContext<'a, 'tcx> {
-    universal_regions: &'a UniversalRegions<'tcx>,
+    pub(crate) universal_regions: &'a UniversalRegions<'tcx>,
     location_table: &'a LocationTable,
     all_facts: &'a mut Option<AllFacts>,
     borrow_set: &'a BorrowSet<'tcx>,
-    constraints: &'a mut MirTypeckRegionConstraints<'tcx>,
+    pub(crate) constraints: &'a mut MirTypeckRegionConstraints<'tcx>,
     upvars: &'a [Upvar<'tcx>],
 }
 
@@ -1157,6 +1157,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
         self.relate_types(sup, ty::Variance::Contravariant, sub, locations, category)
     }
 
+    #[instrument(skip(self, category), level = "debug")]
     fn eq_types(
         &mut self,
         expected: Ty<'tcx>,
diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs
index a441a635c1e..e00c5789fe9 100644
--- a/compiler/rustc_hir/src/hir.rs
+++ b/compiler/rustc_hir/src/hir.rs
@@ -647,6 +647,22 @@ pub struct WhereBoundPredicate<'hir> {
     pub bounds: GenericBounds<'hir>,
 }
 
+impl WhereBoundPredicate<'hir> {
+    /// Returns `true` if `param_def_id` matches the `bounded_ty` of this predicate.
+    pub fn is_param_bound(&self, param_def_id: DefId) -> bool {
+        let path = match self.bounded_ty.kind {
+            TyKind::Path(QPath::Resolved(None, path)) => path,
+            _ => return false,
+        };
+        match path.res {
+            Res::Def(DefKind::TyParam, def_id) | Res::SelfTy(Some(def_id), None) => {
+                def_id == param_def_id
+            }
+            _ => false,
+        }
+    }
+}
+
 /// A lifetime predicate (e.g., `'a: 'b + 'c`).
 #[derive(Debug, HashStable_Generic)]
 pub struct WhereRegionPredicate<'hir> {
diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs
index 5e807b2f55c..610f9bd8f82 100644
--- a/compiler/rustc_middle/src/ty/sty.rs
+++ b/compiler/rustc_middle/src/ty/sty.rs
@@ -2067,7 +2067,9 @@ impl<'tcx> TyS<'tcx> {
     ) -> Option<Discr<'tcx>> {
         match self.kind() {
             TyKind::Adt(adt, _) if adt.variants.is_empty() => {
-                bug!("discriminant_for_variant called on zero variant enum");
+                // This can actually happen during CTFE, see
+                // https://github.com/rust-lang/rust/issues/89765.
+                None
             }
             TyKind::Adt(adt, _) if adt.is_enum() => {
                 Some(adt.discriminant_for_variant(tcx, variant_index))
diff --git a/compiler/rustc_mir_build/src/build/matches/mod.rs b/compiler/rustc_mir_build/src/build/matches/mod.rs
index 4df073c40e2..6320d5d4749 100644
--- a/compiler/rustc_mir_build/src/build/matches/mod.rs
+++ b/compiler/rustc_mir_build/src/build/matches/mod.rs
@@ -1762,8 +1762,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
     ) -> BlockAnd<()> {
         let expr_span = expr.span;
         let expr_place_builder = unpack!(block = self.lower_scrutinee(block, expr, expr_span));
-        let mut guard_candidate = Candidate::new(expr_place_builder.clone(), &pat, false);
         let wildcard = Pat::wildcard_from_ty(pat.ty);
+        let mut guard_candidate = Candidate::new(expr_place_builder.clone(), &pat, false);
         let mut otherwise_candidate = Candidate::new(expr_place_builder.clone(), &wildcard, false);
         let fake_borrow_temps = self.lower_match_tree(
             block,
diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
index 79194718d1e..f8df0e25959 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
@@ -2009,6 +2009,19 @@ impl<'a, 'tcx> InferCtxtPrivExt<'tcx> for InferCtxt<'a, 'tcx> {
             Some(param) => param,
             _ => return,
         };
+        let param_def_id = self.tcx.hir().local_def_id(param.hir_id).to_def_id();
+        let preds = generics.where_clause.predicates.iter();
+        let explicitly_sized = preds
+            .filter_map(|pred| match pred {
+                hir::WherePredicate::BoundPredicate(bp) => Some(bp),
+                _ => None,
+            })
+            .filter(|bp| bp.is_param_bound(param_def_id))
+            .flat_map(|bp| bp.bounds)
+            .any(|bound| bound.trait_ref().and_then(|tr| tr.trait_def_id()) == sized_trait);
+        if explicitly_sized {
+            return;
+        }
         debug!("maybe_suggest_unsized_generics: param={:?}", param);
         match node {
             hir::Node::Item(
diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
index bdec7163cd9..0bf01afb575 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
@@ -706,36 +706,29 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
         }
 
         let param_env = obligation.param_env;
-        let trait_ref = poly_trait_ref.skip_binder();
-
-        let found_ty = trait_ref.self_ty();
-        let found_ty_str = found_ty.to_string();
-        let imm_borrowed_found_ty = self.tcx.mk_imm_ref(self.tcx.lifetimes.re_static, found_ty);
-        let imm_substs = self.tcx.mk_substs_trait(imm_borrowed_found_ty, &[]);
-        let mut_borrowed_found_ty = self.tcx.mk_mut_ref(self.tcx.lifetimes.re_static, found_ty);
-        let mut_substs = self.tcx.mk_substs_trait(mut_borrowed_found_ty, &[]);
 
         // Try to apply the original trait binding obligation by borrowing.
-        let mut try_borrowing = |new_imm_trait_ref: ty::Binder<'tcx, ty::TraitRef<'tcx>>,
-                                 new_mut_trait_ref: ty::Binder<'tcx, ty::TraitRef<'tcx>>,
-                                 expected_trait_ref: ty::Binder<'tcx, ty::TraitRef<'tcx>>,
+        let mut try_borrowing = |old_ref: ty::Binder<'tcx, ty::TraitRef<'tcx>>,
                                  blacklist: &[DefId]|
          -> bool {
-            if blacklist.contains(&expected_trait_ref.def_id()) {
+            if blacklist.contains(&old_ref.def_id()) {
                 return false;
             }
 
-            let imm_result = self.predicate_must_hold_modulo_regions(&Obligation::new(
-                ObligationCause::dummy(),
-                param_env,
-                new_imm_trait_ref.without_const().to_predicate(self.tcx),
-            ));
-
-            let mut_result = self.predicate_must_hold_modulo_regions(&Obligation::new(
-                ObligationCause::dummy(),
-                param_env,
-                new_mut_trait_ref.without_const().to_predicate(self.tcx),
-            ));
+            let orig_ty = old_ref.self_ty().skip_binder();
+            let mk_result = |new_ty| {
+                let new_ref = old_ref.rebind(ty::TraitRef::new(
+                    old_ref.def_id(),
+                    self.tcx.mk_substs_trait(new_ty, &old_ref.skip_binder().substs[1..]),
+                ));
+                self.predicate_must_hold_modulo_regions(&Obligation::new(
+                    ObligationCause::dummy(),
+                    param_env,
+                    new_ref.without_const().to_predicate(self.tcx),
+                ))
+            };
+            let imm_result = mk_result(self.tcx.mk_imm_ref(self.tcx.lifetimes.re_static, orig_ty));
+            let mut_result = mk_result(self.tcx.mk_mut_ref(self.tcx.lifetimes.re_static, orig_ty));
 
             if imm_result || mut_result {
                 if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span) {
@@ -747,8 +740,8 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
 
                     let msg = format!(
                         "the trait bound `{}: {}` is not satisfied",
-                        found_ty_str,
-                        expected_trait_ref.print_only_trait_path(),
+                        orig_ty.to_string(),
+                        old_ref.print_only_trait_path(),
                     );
                     if has_custom_message {
                         err.note(&msg);
@@ -764,7 +757,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
                         span,
                         &format!(
                             "expected an implementor of trait `{}`",
-                            expected_trait_ref.print_only_trait_path(),
+                            old_ref.print_only_trait_path(),
                         ),
                     );
 
@@ -807,21 +800,11 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
         };
 
         if let ObligationCauseCode::ImplDerivedObligation(obligation) = &*code {
-            let expected_trait_ref = obligation.parent_trait_ref;
-            let new_imm_trait_ref = poly_trait_ref
-                .rebind(ty::TraitRef::new(obligation.parent_trait_ref.def_id(), imm_substs));
-            let new_mut_trait_ref = poly_trait_ref
-                .rebind(ty::TraitRef::new(obligation.parent_trait_ref.def_id(), mut_substs));
-            return try_borrowing(new_imm_trait_ref, new_mut_trait_ref, expected_trait_ref, &[]);
+            try_borrowing(obligation.parent_trait_ref, &[])
         } else if let ObligationCauseCode::BindingObligation(_, _)
         | ObligationCauseCode::ItemObligation(_) = &*code
         {
-            return try_borrowing(
-                poly_trait_ref.rebind(ty::TraitRef::new(trait_ref.def_id, imm_substs)),
-                poly_trait_ref.rebind(ty::TraitRef::new(trait_ref.def_id, mut_substs)),
-                *poly_trait_ref,
-                &never_suggest_borrow[..],
-            );
+            try_borrowing(*poly_trait_ref, &never_suggest_borrow[..])
         } else {
             false
         }
diff --git a/compiler/rustc_typeck/src/check/method/suggest.rs b/compiler/rustc_typeck/src/check/method/suggest.rs
index 71cd8a43329..661ced952c7 100644
--- a/compiler/rustc_typeck/src/check/method/suggest.rs
+++ b/compiler/rustc_typeck/src/check/method/suggest.rs
@@ -478,6 +478,26 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 let mut label_span_not_found = || {
                     if unsatisfied_predicates.is_empty() {
                         err.span_label(span, format!("{item_kind} not found in `{ty_str}`"));
+                        let is_string_or_ref_str = match actual.kind() {
+                            ty::Ref(_, ty, _) => {
+                                ty.is_str()
+                                    || matches!(
+                                        ty.kind(),
+                                        ty::Adt(adt, _) if self.tcx.is_diagnostic_item(sym::String, adt.did)
+                                    )
+                            }
+                            ty::Adt(adt, _) => self.tcx.is_diagnostic_item(sym::String, adt.did),
+                            _ => false,
+                        };
+                        if is_string_or_ref_str && item_name.name == sym::iter {
+                            err.span_suggestion_verbose(
+                                item_name.span,
+                                "because of the in-memory representation of `&str`, to obtain \
+                                 an `Iterator` over each of its codepoint use method `chars`",
+                                String::from("chars"),
+                                Applicability::MachineApplicable,
+                            );
+                        }
                         if let ty::Adt(adt, _) = rcvr_ty.kind() {
                             let mut inherent_impls_candidate = self
                                 .tcx
diff --git a/compiler/rustc_typeck/src/collect.rs b/compiler/rustc_typeck/src/collect.rs
index 2274db76c05..2f427305782 100644
--- a/compiler/rustc_typeck/src/collect.rs
+++ b/compiler/rustc_typeck/src/collect.rs
@@ -28,7 +28,7 @@ use rustc_data_structures::captures::Captures;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexSet};
 use rustc_errors::{struct_span_err, Applicability};
 use rustc_hir as hir;
-use rustc_hir::def::{CtorKind, DefKind, Res};
+use rustc_hir::def::{CtorKind, DefKind};
 use rustc_hir::def_id::{DefId, LocalDefId, LOCAL_CRATE};
 use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor};
 use rustc_hir::weak_lang_items;
@@ -668,6 +668,7 @@ impl ItemCtxt<'tcx> {
             })
             .flat_map(|b| predicates_from_bound(self, ty, b));
 
+        let param_def_id = self.tcx.hir().local_def_id(param_id).to_def_id();
         let from_where_clauses = ast_generics
             .where_clause
             .predicates
@@ -677,7 +678,7 @@ impl ItemCtxt<'tcx> {
                 _ => None,
             })
             .flat_map(|bp| {
-                let bt = if is_param(self.tcx, bp.bounded_ty, param_id) {
+                let bt = if bp.is_param_bound(param_def_id) {
                     Some(ty)
                 } else if !only_self_bounds.0 {
                     Some(self.to_ty(bp.bounded_ty))
@@ -714,23 +715,6 @@ impl ItemCtxt<'tcx> {
     }
 }
 
-/// Tests whether this is the AST for a reference to the type
-/// parameter with ID `param_id`. We use this so as to avoid running
-/// `ast_ty_to_ty`, because we want to avoid triggering an all-out
-/// conversion of the type to avoid inducing unnecessary cycles.
-fn is_param(tcx: TyCtxt<'_>, ast_ty: &hir::Ty<'_>, param_id: hir::HirId) -> bool {
-    if let hir::TyKind::Path(hir::QPath::Resolved(None, path)) = ast_ty.kind {
-        match path.res {
-            Res::SelfTy(Some(def_id), None) | Res::Def(DefKind::TyParam, def_id) => {
-                def_id == tcx.hir().local_def_id(param_id).to_def_id()
-            }
-            _ => false,
-        }
-    } else {
-        false
-    }
-}
-
 fn convert_item(tcx: TyCtxt<'_>, item_id: hir::ItemId) {
     let it = tcx.hir().item(item_id);
     debug!("convert: item {} with id {}", it.ident, it.hir_id());
diff --git a/src/ci/run.sh b/src/ci/run.sh
index a21b40cfb77..948445427d9 100755
--- a/src/ci/run.sh
+++ b/src/ci/run.sh
@@ -117,7 +117,7 @@ datecheck() {
   echo -n "  local time: "
   date
   echo -n "  network time: "
-  curl -fs --head http://detectportal.firefox.com/success.txt | grep ^Date: \
+  curl -fs --head http://ci-caches.rust-lang.org | grep ^Date: \
       | sed 's/Date: //g' || true
   echo "== end clock drift check =="
 }
diff --git a/src/test/ui/borrowck/issue-80772.rs b/src/test/ui/borrowck/issue-80772.rs
new file mode 100644
index 00000000000..1b8caa3f8ac
--- /dev/null
+++ b/src/test/ui/borrowck/issue-80772.rs
@@ -0,0 +1,21 @@
+// check-pass
+
+trait SomeTrait {}
+
+pub struct Exhibit {
+    constant: usize,
+    factory: fn(&usize) -> Box<dyn SomeTrait>,
+}
+
+pub const A_CONSTANT: &[Exhibit] = &[
+    Exhibit {
+        constant: 1,
+        factory: |_| unimplemented!(),
+    },
+    Exhibit {
+        constant: "Hello world".len(),
+        factory: |_| unimplemented!(),
+    },
+];
+
+fn main() {}
diff --git a/src/test/ui/consts/const_discriminant.rs b/src/test/ui/consts/const_discriminant.rs
index a47f6af0296..f623c5101f4 100644
--- a/src/test/ui/consts/const_discriminant.rs
+++ b/src/test/ui/consts/const_discriminant.rs
@@ -25,6 +25,13 @@ enum SingleVariant {
 
 const TEST_V: Discriminant<SingleVariant> = discriminant(&SingleVariant::V);
 
+pub const TEST_VOID: () = {
+    // This is UB, but CTFE does not check validity so it does not detect this.
+    // This is a regression test for https://github.com/rust-lang/rust/issues/89765.
+    unsafe { std::mem::discriminant(&*(&() as *const () as *const Void)); };
+};
+
+
 fn main() {
     assert_eq!(TEST_A, TEST_A_OTHER);
     assert_eq!(TEST_A, discriminant(black_box(&Test::A(17))));
diff --git a/src/test/ui/derives/deriving-copyclone.stderr b/src/test/ui/derives/deriving-copyclone.stderr
index 1d0554ad047..13097edf0ad 100644
--- a/src/test/ui/derives/deriving-copyclone.stderr
+++ b/src/test/ui/derives/deriving-copyclone.stderr
@@ -1,4 +1,4 @@
-error[E0277]: the trait bound `C: Copy` is not satisfied
+error[E0277]: the trait bound `B<C>: Copy` is not satisfied
   --> $DIR/deriving-copyclone.rs:31:13
    |
 LL |     is_copy(B { a: 1, b: C });
@@ -22,7 +22,7 @@ help: consider borrowing here
 LL |     is_copy(&B { a: 1, b: C });
    |             +
 
-error[E0277]: the trait bound `C: Clone` is not satisfied
+error[E0277]: the trait bound `B<C>: Clone` is not satisfied
   --> $DIR/deriving-copyclone.rs:32:14
    |
 LL |     is_clone(B { a: 1, b: C });
@@ -46,7 +46,7 @@ help: consider borrowing here
 LL |     is_clone(&B { a: 1, b: C });
    |              +
 
-error[E0277]: the trait bound `D: Copy` is not satisfied
+error[E0277]: the trait bound `B<D>: Copy` is not satisfied
   --> $DIR/deriving-copyclone.rs:35:13
    |
 LL |     is_copy(B { a: 1, b: D });
diff --git a/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-90612.rs b/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-90612.rs
new file mode 100644
index 00000000000..e150ecfe9a0
--- /dev/null
+++ b/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-90612.rs
@@ -0,0 +1,43 @@
+// check-pass
+
+#![feature(generic_associated_types)]
+
+use std::marker::PhantomData;
+
+trait Family: Sized {
+    type Item<'a>;
+
+    fn apply_all<F>(&self, f: F)
+    where
+        F: FamilyItemFn<Self> { }
+}
+
+struct Array<T>(PhantomData<T>);
+
+impl<T: 'static> Family for Array<T> {
+    type Item<'a> = &'a T;
+}
+
+trait FamilyItemFn<T: Family> {
+    fn apply(&self, item: T::Item<'_>);
+}
+
+impl<T, F> FamilyItemFn<T> for F
+where
+    T: Family,
+    for<'a> F: Fn(T::Item<'a>)
+{
+    fn apply(&self, item: T::Item<'_>) {
+        (*self)(item);
+    }
+}
+
+fn process<T: 'static>(array: Array<T>) {
+    // Works
+    array.apply_all(|x: &T| { });
+
+    // ICE: NoSolution
+    array.apply_all(|x: <Array<T> as Family>::Item<'_>| { });
+}
+
+fn main() {}
diff --git a/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-90638.rs b/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-90638.rs
new file mode 100644
index 00000000000..18b7f383482
--- /dev/null
+++ b/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-90638.rs
@@ -0,0 +1,37 @@
+//check-pass
+
+#![feature(generic_associated_types)]
+
+trait Yokeable<'a>: 'static {
+    type Output: 'a;
+}
+
+trait IsCovariant<'a> {}
+
+struct Yoke<Y: for<'a> Yokeable<'a>> {
+    data: Y,
+}
+
+impl<Y: for<'a> Yokeable<'a>> Yoke<Y> {
+    fn project<Y2: for<'a> Yokeable<'a>>(&self, _f: for<'a> fn(<Y as Yokeable<'a>>::Output, &'a ())
+      -> <Y2 as Yokeable<'a>>::Output) -> Yoke<Y2> {
+
+        unimplemented!()
+    }
+}
+
+fn _upcast<Y>(x: Yoke<Y>) -> Yoke<Box<dyn IsCovariant<'static> + 'static>> where
+    Y: for<'a> Yokeable<'a>,
+    for<'a> <Y as Yokeable<'a>>::Output: IsCovariant<'a>
+    {
+    x.project(|data, _| {
+        Box::new(data)
+    })
+}
+
+
+impl<'a> Yokeable<'a> for Box<dyn IsCovariant<'static> + 'static> {
+    type Output = Box<dyn IsCovariant<'a> + 'a>;
+}
+
+fn main() {}
diff --git a/src/test/ui/suggest-using-chars.rs b/src/test/ui/suggest-using-chars.rs
new file mode 100644
index 00000000000..95732881baf
--- /dev/null
+++ b/src/test/ui/suggest-using-chars.rs
@@ -0,0 +1,7 @@
+pub fn main() {
+    let _ = "foo".iter(); //~ ERROR no method named `iter` found for reference `&'static str` in the current scope
+    let _ = "foo".foo(); //~ ERROR no method named `foo` found for reference `&'static str` in the current scope
+    let _ = String::from("bar").iter(); //~ ERROR no method named `iter` found for struct `String` in the current scope
+    let _ = (&String::from("bar")).iter(); //~ ERROR no method named `iter` found for reference `&String` in the current scope
+    let _ = 0.iter(); //~ ERROR no method named `iter` found for type `{integer}` in the current scope
+}
diff --git a/src/test/ui/suggest-using-chars.stderr b/src/test/ui/suggest-using-chars.stderr
new file mode 100644
index 00000000000..99bcfb08a08
--- /dev/null
+++ b/src/test/ui/suggest-using-chars.stderr
@@ -0,0 +1,48 @@
+error[E0599]: no method named `iter` found for reference `&'static str` in the current scope
+  --> $DIR/suggest-using-chars.rs:2:19
+   |
+LL |     let _ = "foo".iter();
+   |                   ^^^^ method not found in `&'static str`
+   |
+help: because of the in-memory representation of `&str`, to obtain an `Iterator` over each of its codepoint use method `chars`
+   |
+LL |     let _ = "foo".chars();
+   |                   ~~~~~
+
+error[E0599]: no method named `foo` found for reference `&'static str` in the current scope
+  --> $DIR/suggest-using-chars.rs:3:19
+   |
+LL |     let _ = "foo".foo();
+   |                   ^^^ method not found in `&'static str`
+
+error[E0599]: no method named `iter` found for struct `String` in the current scope
+  --> $DIR/suggest-using-chars.rs:4:33
+   |
+LL |     let _ = String::from("bar").iter();
+   |                                 ^^^^ method not found in `String`
+   |
+help: because of the in-memory representation of `&str`, to obtain an `Iterator` over each of its codepoint use method `chars`
+   |
+LL |     let _ = String::from("bar").chars();
+   |                                 ~~~~~
+
+error[E0599]: no method named `iter` found for reference `&String` in the current scope
+  --> $DIR/suggest-using-chars.rs:5:36
+   |
+LL |     let _ = (&String::from("bar")).iter();
+   |                                    ^^^^ method not found in `&String`
+   |
+help: because of the in-memory representation of `&str`, to obtain an `Iterator` over each of its codepoint use method `chars`
+   |
+LL |     let _ = (&String::from("bar")).chars();
+   |                                    ~~~~~
+
+error[E0599]: no method named `iter` found for type `{integer}` in the current scope
+  --> $DIR/suggest-using-chars.rs:6:15
+   |
+LL |     let _ = 0.iter();
+   |               ^^^^ method not found in `{integer}`
+
+error: aborting due to 5 previous errors
+
+For more information about this error, try `rustc --explain E0599`.
diff --git a/src/test/ui/suggestions/issue-85945-check-where-clause-before-suggesting-unsized.rs b/src/test/ui/suggestions/issue-85945-check-where-clause-before-suggesting-unsized.rs
new file mode 100644
index 00000000000..5cfaf4be96a
--- /dev/null
+++ b/src/test/ui/suggestions/issue-85945-check-where-clause-before-suggesting-unsized.rs
@@ -0,0 +1,8 @@
+// Regression test for #85945: Don't suggest `?Sized` bound if an explicit
+// `Sized` bound is already in a `where` clause.
+fn foo<T>(_: &T) where T: Sized {}
+fn bar() { foo(""); }
+//~^ERROR the size for values of type
+
+pub fn main() {
+}
diff --git a/src/test/ui/suggestions/issue-85945-check-where-clause-before-suggesting-unsized.stderr b/src/test/ui/suggestions/issue-85945-check-where-clause-before-suggesting-unsized.stderr
new file mode 100644
index 00000000000..92be9f764cc
--- /dev/null
+++ b/src/test/ui/suggestions/issue-85945-check-where-clause-before-suggesting-unsized.stderr
@@ -0,0 +1,18 @@
+error[E0277]: the size for values of type `str` cannot be known at compilation time
+  --> $DIR/issue-85945-check-where-clause-before-suggesting-unsized.rs:4:16
+   |
+LL | fn bar() { foo(""); }
+   |            --- ^^ doesn't have a size known at compile-time
+   |            |
+   |            required by a bound introduced by this call
+   |
+   = help: the trait `Sized` is not implemented for `str`
+note: required by a bound in `foo`
+  --> $DIR/issue-85945-check-where-clause-before-suggesting-unsized.rs:3:8
+   |
+LL | fn foo<T>(_: &T) where T: Sized {}
+   |        ^ required by this bound in `foo`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/traits/negative-impls/negated-auto-traits-error.stderr b/src/test/ui/traits/negative-impls/negated-auto-traits-error.stderr
index 1cf73fcdebd..1ab130e0ab1 100644
--- a/src/test/ui/traits/negative-impls/negated-auto-traits-error.stderr
+++ b/src/test/ui/traits/negative-impls/negated-auto-traits-error.stderr
@@ -65,7 +65,7 @@ LL |     is_send(Box::new(TestType));
    |     |
    |     required by a bound introduced by this call
    |
-   = note: the trait bound `dummy2::TestType: Send` is not satisfied
+   = note: the trait bound `Unique<dummy2::TestType>: Send` is not satisfied
    = note: required because of the requirements on the impl of `Send` for `Unique<dummy2::TestType>`
    = note: required because it appears within the type `Box<dummy2::TestType>`
 note: required by a bound in `is_send`
@@ -104,11 +104,11 @@ error[E0277]: `main::TestType` cannot be sent between threads safely
   --> $DIR/negated-auto-traits-error.rs:66:13
    |
 LL |     is_sync(Outer2(TestType));
-   |     ------- ^^^^^^^^^^^^^^^^ expected an implementor of trait `Sync`
+   |     ------- ^^^^^^^^^^^^^^^^ `main::TestType` cannot be sent between threads safely
    |     |
    |     required by a bound introduced by this call
    |
-   = note: the trait bound `main::TestType: Sync` is not satisfied
+   = help: the trait `Send` is not implemented for `main::TestType`
 note: required because of the requirements on the impl of `Sync` for `Outer2<main::TestType>`
   --> $DIR/negated-auto-traits-error.rs:14:22
    |
@@ -119,12 +119,6 @@ note: required by a bound in `is_sync`
    |
 LL | fn is_sync<T: Sync>(_: T) {}
    |               ^^^^ required by this bound in `is_sync`
-help: consider borrowing here
-   |
-LL |     is_sync(&Outer2(TestType));
-   |             +
-LL |     is_sync(&mut Outer2(TestType));
-   |             ++++
 
 error: aborting due to 7 previous errors
 
diff --git a/src/test/ui/typeck/issue-90804-incorrect-reference-suggestion.rs b/src/test/ui/typeck/issue-90804-incorrect-reference-suggestion.rs
new file mode 100644
index 00000000000..f891a42fc2a
--- /dev/null
+++ b/src/test/ui/typeck/issue-90804-incorrect-reference-suggestion.rs
@@ -0,0 +1,11 @@
+// Do not suggest referencing the parameter to `check`
+
+trait Marker<T> {}
+
+impl<T> Marker<i32> for T {}
+
+pub fn check<T: Marker<u32>>(_: T) {}
+
+pub fn main() {
+    check::<()>(()); //~ ERROR [E0277]
+}
diff --git a/src/test/ui/typeck/issue-90804-incorrect-reference-suggestion.stderr b/src/test/ui/typeck/issue-90804-incorrect-reference-suggestion.stderr
new file mode 100644
index 00000000000..08eab025370
--- /dev/null
+++ b/src/test/ui/typeck/issue-90804-incorrect-reference-suggestion.stderr
@@ -0,0 +1,17 @@
+error[E0277]: the trait bound `(): Marker<u32>` is not satisfied
+  --> $DIR/issue-90804-incorrect-reference-suggestion.rs:10:17
+   |
+LL |     check::<()>(());
+   |     ----------- ^^ the trait `Marker<u32>` is not implemented for `()`
+   |     |
+   |     required by a bound introduced by this call
+   |
+note: required by a bound in `check`
+  --> $DIR/issue-90804-incorrect-reference-suggestion.rs:7:17
+   |
+LL | pub fn check<T: Marker<u32>>(_: T) {}
+   |                 ^^^^^^^^^^^ required by this bound in `check`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.