about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2021-07-03 01:42:06 +0000
committerbors <bors@rust-lang.org>2021-07-03 01:42:06 +0000
commitcd48e61c5d8f83fbfbfc28db0b0bce1354d0ced1 (patch)
treefa2742d26eae638d47bae349b0b6a831879af62c
parent798baebde1fe77e5a660490ec64e727a5d79970d (diff)
parent58f6cb4557b2d63d311420bbf6bc63aa119f8306 (diff)
downloadrust-cd48e61c5d8f83fbfbfc28db0b0bce1354d0ced1.tar.gz
rust-cd48e61c5d8f83fbfbfc28db0b0bce1354d0ced1.zip
Auto merge of #86795 - JohnTitor:fix-bind, r=jackh726
Fix const-generics ICE related to binding

Fixes #83765, fixes #85848
r? `@jackh726` as you're familiar with `Binding`. I'd like to get some views if the current approach is right path.
-rw-r--r--compiler/rustc_middle/src/ty/fold.rs82
-rw-r--r--compiler/rustc_middle/src/ty/sty.rs8
-rw-r--r--compiler/rustc_middle/src/ty/util.rs6
-rw-r--r--compiler/rustc_mir/src/transform/check_consts/validation.rs7
-rw-r--r--compiler/rustc_trait_selection/src/traits/project.rs2
-rw-r--r--compiler/rustc_ty_utils/src/instance.rs109
-rw-r--r--compiler/rustc_ty_utils/src/lib.rs1
-rw-r--r--compiler/rustc_typeck/src/astconv/mod.rs2
-rw-r--r--compiler/rustc_typeck/src/check/compare_method.rs11
-rw-r--r--compiler/rustc_typeck/src/check/method/confirm.rs10
-rw-r--r--compiler/rustc_typeck/src/check/method/mod.rs2
-rw-r--r--compiler/rustc_typeck/src/check/wfcheck.rs5
-rw-r--r--compiler/rustc_typeck/src/collect.rs18
-rw-r--r--src/test/ui/const-generics/issues/issue-83765.rs38
-rw-r--r--src/test/ui/const-generics/issues/issue-83765.stderr29
-rw-r--r--src/test/ui/const-generics/issues/issue-85848.rs31
-rw-r--r--src/test/ui/const-generics/issues/issue-85848.stderr44
17 files changed, 280 insertions, 125 deletions
diff --git a/compiler/rustc_middle/src/ty/fold.rs b/compiler/rustc_middle/src/ty/fold.rs
index eb6d163312c..a40210d5a36 100644
--- a/compiler/rustc_middle/src/ty/fold.rs
+++ b/compiler/rustc_middle/src/ty/fold.rs
@@ -754,88 +754,6 @@ impl<'tcx> TyCtxt<'tcx> {
     }
 }
 
-pub struct BoundVarsCollector<'tcx> {
-    binder_index: ty::DebruijnIndex,
-    vars: BTreeMap<u32, ty::BoundVariableKind>,
-    // We may encounter the same variable at different levels of binding, so
-    // this can't just be `Ty`
-    visited: SsoHashSet<(ty::DebruijnIndex, Ty<'tcx>)>,
-}
-
-impl<'tcx> BoundVarsCollector<'tcx> {
-    pub fn new() -> Self {
-        BoundVarsCollector {
-            binder_index: ty::INNERMOST,
-            vars: BTreeMap::new(),
-            visited: SsoHashSet::default(),
-        }
-    }
-
-    pub fn into_vars(self, tcx: TyCtxt<'tcx>) -> &'tcx ty::List<ty::BoundVariableKind> {
-        let max = self.vars.iter().map(|(k, _)| *k).max().unwrap_or_else(|| 0);
-        for i in 0..max {
-            if let None = self.vars.get(&i) {
-                panic!("Unknown variable: {:?}", i);
-            }
-        }
-
-        tcx.mk_bound_variable_kinds(self.vars.into_iter().map(|(_, v)| v))
-    }
-}
-
-impl<'tcx> TypeVisitor<'tcx> for BoundVarsCollector<'tcx> {
-    type BreakTy = ();
-
-    fn visit_binder<T: TypeFoldable<'tcx>>(
-        &mut self,
-        t: &Binder<'tcx, T>,
-    ) -> ControlFlow<Self::BreakTy> {
-        self.binder_index.shift_in(1);
-        let result = t.super_visit_with(self);
-        self.binder_index.shift_out(1);
-        result
-    }
-
-    fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
-        if t.outer_exclusive_binder < self.binder_index
-            || !self.visited.insert((self.binder_index, t))
-        {
-            return ControlFlow::CONTINUE;
-        }
-        use std::collections::btree_map::Entry;
-        match *t.kind() {
-            ty::Bound(debruijn, bound_ty) if debruijn == self.binder_index => {
-                match self.vars.entry(bound_ty.var.as_u32()) {
-                    Entry::Vacant(entry) => {
-                        entry.insert(ty::BoundVariableKind::Ty(bound_ty.kind));
-                    }
-                    Entry::Occupied(entry) => match entry.get() {
-                        ty::BoundVariableKind::Ty(_) => {}
-                        _ => bug!("Conflicting bound vars"),
-                    },
-                }
-            }
-
-            _ => (),
-        };
-
-        t.super_visit_with(self)
-    }
-
-    fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow<Self::BreakTy> {
-        match r {
-            ty::ReLateBound(index, _br) if *index == self.binder_index => {
-                // If you hit this, you should be using `Binder::bind_with_vars` or `Binder::rebind`
-                bug!("Trying to collect bound vars with a bound region: {:?} {:?}", index, _br)
-            }
-
-            _ => (),
-        };
-
-        r.super_visit_with(self)
-    }
-}
-
 pub struct ValidateBoundVars<'tcx> {
     bound_vars: &'tcx ty::List<ty::BoundVariableKind>,
     binder_index: ty::DebruijnIndex,
diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs
index 2959ea24d24..73f0811a504 100644
--- a/compiler/rustc_middle/src/ty/sty.rs
+++ b/compiler/rustc_middle/src/ty/sty.rs
@@ -5,7 +5,6 @@
 use self::TyKind::*;
 
 use crate::infer::canonical::Canonical;
-use crate::ty::fold::BoundVarsCollector;
 use crate::ty::fold::ValidateBoundVars;
 use crate::ty::subst::{GenericArg, InternalSubsts, Subst, SubstsRef};
 use crate::ty::InferTy::{self, *};
@@ -970,13 +969,6 @@ where
         Binder(value, ty::List::empty())
     }
 
-    /// Wraps `value` in a binder, binding higher-ranked vars (if any).
-    pub fn bind(value: T, tcx: TyCtxt<'tcx>) -> Binder<'tcx, T> {
-        let mut collector = BoundVarsCollector::new();
-        value.visit_with(&mut collector);
-        Binder(value, collector.into_vars(tcx))
-    }
-
     pub fn bind_with_vars(value: T, vars: &'tcx List<BoundVariableKind>) -> Binder<'tcx, T> {
         if cfg!(debug_assertions) {
             let mut validator = ValidateBoundVars::new(vars);
diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs
index 7bf69b9e637..24a9cea6d21 100644
--- a/compiler/rustc_middle/src/ty/util.rs
+++ b/compiler/rustc_middle/src/ty/util.rs
@@ -7,7 +7,7 @@ use crate::ty::layout::IntegerExt;
 use crate::ty::query::TyCtxtAt;
 use crate::ty::subst::{GenericArgKind, Subst, SubstsRef};
 use crate::ty::TyKind::*;
-use crate::ty::{self, DefIdTree, List, Ty, TyCtxt, TypeFoldable};
+use crate::ty::{self, DebruijnIndex, DefIdTree, List, Ty, TyCtxt, TypeFoldable};
 use rustc_apfloat::Float as _;
 use rustc_ast as ast;
 use rustc_attr::{self as attr, SignedInt, UnsignedInt};
@@ -905,6 +905,10 @@ impl<'tcx> ty::TyS<'tcx> {
         }
         ty
     }
+
+    pub fn outer_exclusive_binder(&'tcx self) -> DebruijnIndex {
+        self.outer_exclusive_binder
+    }
 }
 
 pub enum ExplicitSelf<'tcx> {
diff --git a/compiler/rustc_mir/src/transform/check_consts/validation.rs b/compiler/rustc_mir/src/transform/check_consts/validation.rs
index 4fbd27c89d9..6216ff6656e 100644
--- a/compiler/rustc_mir/src/transform/check_consts/validation.rs
+++ b/compiler/rustc_mir/src/transform/check_consts/validation.rs
@@ -822,12 +822,7 @@ impl Visitor<'tcx> for Validator<'mir, 'tcx> {
                     let obligation = Obligation::new(
                         ObligationCause::dummy(),
                         param_env,
-                        Binder::bind(
-                            TraitPredicate {
-                                trait_ref: TraitRef::from_method(tcx, trait_id, substs),
-                            },
-                            tcx,
-                        ),
+                        Binder::dummy(TraitPredicate { trait_ref }),
                     );
 
                     let implsrc = tcx.infer_ctxt().enter(|infcx| {
diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs
index 388413ae06b..352829234a4 100644
--- a/compiler/rustc_trait_selection/src/traits/project.rs
+++ b/compiler/rustc_trait_selection/src/traits/project.rs
@@ -1301,7 +1301,7 @@ fn confirm_pointee_candidate<'cx, 'tcx>(
         ty: self_ty.ptr_metadata_ty(tcx),
     };
 
-    confirm_param_env_candidate(selcx, obligation, ty::Binder::bind(predicate, tcx), false)
+    confirm_param_env_candidate(selcx, obligation, ty::Binder::dummy(predicate), false)
 }
 
 fn confirm_fn_pointer_candidate<'cx, 'tcx>(
diff --git a/compiler/rustc_ty_utils/src/instance.rs b/compiler/rustc_ty_utils/src/instance.rs
index 874289d0293..469ac04e545 100644
--- a/compiler/rustc_ty_utils/src/instance.rs
+++ b/compiler/rustc_ty_utils/src/instance.rs
@@ -2,14 +2,114 @@ use rustc_errors::ErrorReported;
 use rustc_hir::def_id::{DefId, LocalDefId};
 use rustc_infer::infer::TyCtxtInferExt;
 use rustc_middle::ty::subst::SubstsRef;
-use rustc_middle::ty::{self, Instance, TyCtxt, TypeFoldable};
+use rustc_middle::ty::{self, Binder, Instance, Ty, TyCtxt, TypeFoldable, TypeVisitor};
 use rustc_span::{sym, DUMMY_SP};
 use rustc_target::spec::abi::Abi;
 use rustc_trait_selection::traits;
 use traits::{translate_substs, Reveal};
 
+use rustc_data_structures::sso::SsoHashSet;
+use std::collections::btree_map::Entry;
+use std::collections::BTreeMap;
+use std::ops::ControlFlow;
+
 use tracing::debug;
 
+// FIXME(#86795): `BoundVarsCollector` here should **NOT** be used
+// outside of `resolve_associated_item`. It's just to address #64494,
+// #83765, and #85848 which are creating bound types/regions that lose
+// their `Binder` *unintentionally*.
+// It's ideal to remove `BoundVarsCollector` and just use
+// `ty::Binder::*` methods but we use this stopgap until we figure out
+// the "real" fix.
+struct BoundVarsCollector<'tcx> {
+    binder_index: ty::DebruijnIndex,
+    vars: BTreeMap<u32, ty::BoundVariableKind>,
+    // We may encounter the same variable at different levels of binding, so
+    // this can't just be `Ty`
+    visited: SsoHashSet<(ty::DebruijnIndex, Ty<'tcx>)>,
+}
+
+impl<'tcx> BoundVarsCollector<'tcx> {
+    fn new() -> Self {
+        BoundVarsCollector {
+            binder_index: ty::INNERMOST,
+            vars: BTreeMap::new(),
+            visited: SsoHashSet::default(),
+        }
+    }
+
+    fn into_vars(self, tcx: TyCtxt<'tcx>) -> &'tcx ty::List<ty::BoundVariableKind> {
+        let max = self.vars.iter().map(|(k, _)| *k).max().unwrap_or(0);
+        for i in 0..max {
+            if let None = self.vars.get(&i) {
+                panic!("Unknown variable: {:?}", i);
+            }
+        }
+
+        tcx.mk_bound_variable_kinds(self.vars.into_iter().map(|(_, v)| v))
+    }
+}
+
+impl<'tcx> TypeVisitor<'tcx> for BoundVarsCollector<'tcx> {
+    type BreakTy = ();
+
+    fn visit_binder<T: TypeFoldable<'tcx>>(
+        &mut self,
+        t: &Binder<'tcx, T>,
+    ) -> ControlFlow<Self::BreakTy> {
+        self.binder_index.shift_in(1);
+        let result = t.super_visit_with(self);
+        self.binder_index.shift_out(1);
+        result
+    }
+
+    fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
+        if t.outer_exclusive_binder() < self.binder_index
+            || !self.visited.insert((self.binder_index, t))
+        {
+            return ControlFlow::CONTINUE;
+        }
+        match *t.kind() {
+            ty::Bound(debruijn, bound_ty) if debruijn == self.binder_index => {
+                match self.vars.entry(bound_ty.var.as_u32()) {
+                    Entry::Vacant(entry) => {
+                        entry.insert(ty::BoundVariableKind::Ty(bound_ty.kind));
+                    }
+                    Entry::Occupied(entry) => match entry.get() {
+                        ty::BoundVariableKind::Ty(_) => {}
+                        _ => bug!("Conflicting bound vars"),
+                    },
+                }
+            }
+
+            _ => (),
+        };
+
+        t.super_visit_with(self)
+    }
+
+    fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow<Self::BreakTy> {
+        match r {
+            ty::ReLateBound(index, br) if *index == self.binder_index => {
+                match self.vars.entry(br.var.as_u32()) {
+                    Entry::Vacant(entry) => {
+                        entry.insert(ty::BoundVariableKind::Region(br.kind));
+                    }
+                    Entry::Occupied(entry) => match entry.get() {
+                        ty::BoundVariableKind::Region(_) => {}
+                        _ => bug!("Conflicting bound vars"),
+                    },
+                }
+            }
+
+            _ => (),
+        };
+
+        r.super_visit_with(self)
+    }
+}
+
 #[instrument(level = "debug", skip(tcx))]
 fn resolve_instance<'tcx>(
     tcx: TyCtxt<'tcx>,
@@ -115,7 +215,12 @@ fn resolve_associated_item<'tcx>(
     );
 
     let trait_ref = ty::TraitRef::from_method(tcx, trait_id, rcvr_substs);
-    let vtbl = tcx.codegen_fulfill_obligation((param_env, ty::Binder::bind(trait_ref, tcx)))?;
+
+    // See FIXME on `BoundVarsCollector`.
+    let mut bound_vars_collector = BoundVarsCollector::new();
+    trait_ref.visit_with(&mut bound_vars_collector);
+    let trait_binder = ty::Binder::bind_with_vars(trait_ref, bound_vars_collector.into_vars(tcx));
+    let vtbl = tcx.codegen_fulfill_obligation((param_env, trait_binder))?;
 
     // Now that we know which impl is being used, we can dispatch to
     // the actual function:
diff --git a/compiler/rustc_ty_utils/src/lib.rs b/compiler/rustc_ty_utils/src/lib.rs
index 67a692eceac..313571274c3 100644
--- a/compiler/rustc_ty_utils/src/lib.rs
+++ b/compiler/rustc_ty_utils/src/lib.rs
@@ -5,6 +5,7 @@
 //! This API is completely unstable and subject to change.
 
 #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
+#![feature(control_flow_enum)]
 #![feature(half_open_range_patterns)]
 #![feature(exclusive_range_pattern)]
 #![feature(nll)]
diff --git a/compiler/rustc_typeck/src/astconv/mod.rs b/compiler/rustc_typeck/src/astconv/mod.rs
index 10a7d69d5d3..2e42d65cce2 100644
--- a/compiler/rustc_typeck/src/astconv/mod.rs
+++ b/compiler/rustc_typeck/src/astconv/mod.rs
@@ -1694,7 +1694,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                 };
 
                 self.one_bound_for_assoc_type(
-                    || traits::supertraits(tcx, ty::Binder::bind(trait_ref, tcx)),
+                    || traits::supertraits(tcx, ty::Binder::dummy(trait_ref)),
                     || "Self".to_string(),
                     assoc_ident,
                     span,
diff --git a/compiler/rustc_typeck/src/check/compare_method.rs b/compiler/rustc_typeck/src/check/compare_method.rs
index 95a1bfbbb01..12d0c14a3d5 100644
--- a/compiler/rustc_typeck/src/check/compare_method.rs
+++ b/compiler/rustc_typeck/src/check/compare_method.rs
@@ -222,12 +222,7 @@ fn compare_predicate_entailment<'tcx>(
         let mut selcx = traits::SelectionContext::new(&infcx);
 
         let impl_m_own_bounds = impl_m_predicates.instantiate_own(tcx, impl_to_placeholder_substs);
-        let (impl_m_own_bounds, _) = infcx.replace_bound_vars_with_fresh_vars(
-            impl_m_span,
-            infer::HigherRankedType,
-            ty::Binder::bind(impl_m_own_bounds.predicates, tcx),
-        );
-        for predicate in impl_m_own_bounds {
+        for predicate in impl_m_own_bounds.predicates {
             let traits::Normalized { value: predicate, obligations } =
                 traits::normalize(&mut selcx, param_env, normalize_cause.clone(), predicate);
 
@@ -258,14 +253,14 @@ fn compare_predicate_entailment<'tcx>(
         );
         let impl_sig =
             inh.normalize_associated_types_in(impl_m_span, impl_m_hir_id, param_env, impl_sig);
-        let impl_fty = tcx.mk_fn_ptr(ty::Binder::bind(impl_sig, tcx));
+        let impl_fty = tcx.mk_fn_ptr(ty::Binder::dummy(impl_sig));
         debug!("compare_impl_method: impl_fty={:?}", impl_fty);
 
         let trait_sig = tcx.liberate_late_bound_regions(impl_m.def_id, tcx.fn_sig(trait_m.def_id));
         let trait_sig = trait_sig.subst(tcx, trait_to_placeholder_substs);
         let trait_sig =
             inh.normalize_associated_types_in(impl_m_span, impl_m_hir_id, param_env, trait_sig);
-        let trait_fty = tcx.mk_fn_ptr(ty::Binder::bind(trait_sig, tcx));
+        let trait_fty = tcx.mk_fn_ptr(ty::Binder::dummy(trait_sig));
 
         debug!("compare_impl_method: trait_fty={:?}", trait_fty);
 
diff --git a/compiler/rustc_typeck/src/check/method/confirm.rs b/compiler/rustc_typeck/src/check/method/confirm.rs
index f546a0d8963..75299bae5dd 100644
--- a/compiler/rustc_typeck/src/check/method/confirm.rs
+++ b/compiler/rustc_typeck/src/check/method/confirm.rs
@@ -101,6 +101,7 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
 
         let (method_sig, method_predicates) =
             self.normalize_associated_types_in(self.span, (method_sig, method_predicates));
+        let method_sig = ty::Binder::dummy(method_sig);
 
         // Make sure nobody calls `drop()` explicitly.
         self.enforce_illegal_method_limitations(&pick);
@@ -119,12 +120,15 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
         // We won't add these if we encountered an illegal sized bound, so that we can use
         // a custom error in that case.
         if illegal_sized_bound.is_none() {
-            let method_ty = self.tcx.mk_fn_ptr(ty::Binder::bind(method_sig, self.tcx));
-            self.add_obligations(method_ty, all_substs, method_predicates);
+            self.add_obligations(self.tcx.mk_fn_ptr(method_sig), all_substs, method_predicates);
         }
 
         // Create the final `MethodCallee`.
-        let callee = MethodCallee { def_id: pick.item.def_id, substs: all_substs, sig: method_sig };
+        let callee = MethodCallee {
+            def_id: pick.item.def_id,
+            substs: all_substs,
+            sig: method_sig.skip_binder(),
+        };
         ConfirmResult { callee, illegal_sized_bound }
     }
 
diff --git a/compiler/rustc_typeck/src/check/method/mod.rs b/compiler/rustc_typeck/src/check/method/mod.rs
index be6bc625d89..2136d925423 100644
--- a/compiler/rustc_typeck/src/check/method/mod.rs
+++ b/compiler/rustc_typeck/src/check/method/mod.rs
@@ -404,7 +404,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         obligations.extend(traits::predicates_for_generics(cause.clone(), self.param_env, bounds));
 
         // Also add an obligation for the method type being well-formed.
-        let method_ty = tcx.mk_fn_ptr(ty::Binder::bind(fn_sig, tcx));
+        let method_ty = tcx.mk_fn_ptr(ty::Binder::dummy(fn_sig));
         debug!(
             "lookup_in_trait_adjusted: matched method method_ty={:?} obligation={:?}",
             method_ty, obligation
diff --git a/compiler/rustc_typeck/src/check/wfcheck.rs b/compiler/rustc_typeck/src/check/wfcheck.rs
index 7436edccf84..0e063c86f2f 100644
--- a/compiler/rustc_typeck/src/check/wfcheck.rs
+++ b/compiler/rustc_typeck/src/check/wfcheck.rs
@@ -1087,14 +1087,9 @@ fn check_method_receiver<'fcx, 'tcx>(
     debug!("check_method_receiver: sig={:?}", sig);
 
     let self_ty = fcx.normalize_associated_types_in(span, self_ty);
-    let self_ty =
-        fcx.tcx.liberate_late_bound_regions(method.def_id, ty::Binder::bind(self_ty, fcx.tcx));
 
     let receiver_ty = sig.inputs()[0];
-
     let receiver_ty = fcx.normalize_associated_types_in(span, receiver_ty);
-    let receiver_ty =
-        fcx.tcx.liberate_late_bound_regions(method.def_id, ty::Binder::bind(receiver_ty, fcx.tcx));
 
     if fcx.tcx.features().arbitrary_self_types {
         if !receiver_is_valid(fcx, span, receiver_ty, self_ty, true) {
diff --git a/compiler/rustc_typeck/src/collect.rs b/compiler/rustc_typeck/src/collect.rs
index 91e65cffc58..b0e5453b7db 100644
--- a/compiler/rustc_typeck/src/collect.rs
+++ b/compiler/rustc_typeck/src/collect.rs
@@ -1737,11 +1737,12 @@ fn fn_sig(tcx: TyCtxt<'_>, def_id: DefId) -> ty::PolyFnSig<'_> {
                         ty::ReErased => tcx.lifetimes.re_static,
                         _ => r,
                     });
+                    let fn_sig = ty::Binder::dummy(fn_sig);
 
                     let mut visitor = PlaceholderHirTyCollector::default();
                     visitor.visit_ty(ty);
                     let mut diag = bad_placeholder_type(tcx, visitor.0, "return type");
-                    let ret_ty = fn_sig.output();
+                    let ret_ty = fn_sig.skip_binder().output();
                     if ret_ty != tcx.ty_error() {
                         if !ret_ty.is_closure() {
                             let ret_ty_str = match ret_ty.kind() {
@@ -1767,7 +1768,7 @@ fn fn_sig(tcx: TyCtxt<'_>, def_id: DefId) -> ty::PolyFnSig<'_> {
                     }
                     diag.emit();
 
-                    ty::Binder::bind(fn_sig, tcx)
+                    fn_sig
                 }
                 None => <dyn AstConv<'_>>::ty_of_fn(
                     &icx,
@@ -1811,10 +1812,13 @@ fn fn_sig(tcx: TyCtxt<'_>, def_id: DefId) -> ty::PolyFnSig<'_> {
             let ty = tcx.type_of(tcx.hir().get_parent_did(hir_id).to_def_id());
             let inputs =
                 data.fields().iter().map(|f| tcx.type_of(tcx.hir().local_def_id(f.hir_id)));
-            ty::Binder::bind(
-                tcx.mk_fn_sig(inputs, ty, false, hir::Unsafety::Normal, abi::Abi::Rust),
-                tcx,
-            )
+            ty::Binder::dummy(tcx.mk_fn_sig(
+                inputs,
+                ty,
+                false,
+                hir::Unsafety::Normal,
+                abi::Abi::Rust,
+            ))
         }
 
         Expr(&hir::Expr { kind: hir::ExprKind::Closure(..), .. }) => {
@@ -2098,7 +2102,7 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericP
                 param.bounds.iter().for_each(|bound| match bound {
                     hir::GenericBound::Outlives(lt) => {
                         let bound = <dyn AstConv<'_>>::ast_region_to_region(&icx, &lt, None);
-                        let outlives = ty::Binder::bind(ty::OutlivesPredicate(region, bound), tcx);
+                        let outlives = ty::Binder::dummy(ty::OutlivesPredicate(region, bound));
                         predicates.insert((outlives.to_predicate(tcx), lt.span));
                     }
                     _ => bug!(),
diff --git a/src/test/ui/const-generics/issues/issue-83765.rs b/src/test/ui/const-generics/issues/issue-83765.rs
new file mode 100644
index 00000000000..f34badc693e
--- /dev/null
+++ b/src/test/ui/const-generics/issues/issue-83765.rs
@@ -0,0 +1,38 @@
+#![feature(const_generics, const_evaluatable_checked)]
+#![allow(incomplete_features)]
+
+trait TensorDimension {
+    const DIM: usize;
+}
+
+trait TensorSize: TensorDimension {
+    fn size(&self) -> [usize; Self::DIM];
+}
+
+trait Broadcastable: TensorSize + Sized {
+    type Element;
+    fn lazy_updim<const NEWDIM: usize>(&self, size: [usize; NEWDIM]) {}
+}
+
+struct BMap<'a, R, T: Broadcastable, F: Fn(T::Element) -> R, const DIM: usize> {
+    reference: &'a T,
+    closure: F,
+}
+
+impl<'a, R, T: Broadcastable, F: Fn(T::Element) -> R, const DIM: usize> TensorDimension
+    for BMap<'a, R, T, F, DIM>
+{
+    const DIM: usize = DIM;
+}
+impl<'a, R, T: Broadcastable, F: Fn(T::Element) -> R, const DIM: usize> TensorSize
+    for BMap<'a, R, T, F, DIM>
+{
+    fn size(&self) -> [usize; DIM] {
+        //~^ ERROR: method not compatible with trait [E0308]
+        self.reference.size()
+        //~^ ERROR: unconstrained generic constant
+        //~| ERROR: mismatched types
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/const-generics/issues/issue-83765.stderr b/src/test/ui/const-generics/issues/issue-83765.stderr
new file mode 100644
index 00000000000..ef785bf07eb
--- /dev/null
+++ b/src/test/ui/const-generics/issues/issue-83765.stderr
@@ -0,0 +1,29 @@
+error[E0308]: method not compatible with trait
+  --> $DIR/issue-83765.rs:30:5
+   |
+LL |     fn size(&self) -> [usize; DIM] {
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `Self::DIM`, found `DIM`
+   |
+   = note: expected type `Self::DIM`
+              found type `DIM`
+
+error: unconstrained generic constant
+  --> $DIR/issue-83765.rs:32:24
+   |
+LL |         self.reference.size()
+   |                        ^^^^
+   |
+   = help: try adding a `where` bound using this expression: `where [(); Self::DIM]:`
+
+error[E0308]: mismatched types
+  --> $DIR/issue-83765.rs:32:9
+   |
+LL |         self.reference.size()
+   |         ^^^^^^^^^^^^^^^^^^^^^ expected `DIM`, found `Self::DIM`
+   |
+   = note: expected type `DIM`
+              found type `Self::DIM`
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/const-generics/issues/issue-85848.rs b/src/test/ui/const-generics/issues/issue-85848.rs
new file mode 100644
index 00000000000..478719869b2
--- /dev/null
+++ b/src/test/ui/const-generics/issues/issue-85848.rs
@@ -0,0 +1,31 @@
+#![feature(const_generics, const_fn_trait_bound, const_evaluatable_checked)]
+#![allow(incomplete_features)]
+
+trait _Contains<T> {
+    const does_contain: bool;
+}
+
+trait Contains<T, const Satisfied: bool> {}
+
+trait Delegates<T> {}
+
+impl<T, U> Delegates<U> for T where T: Contains<U, true> {}
+
+const fn contains<A, B>() -> bool
+where
+    A: _Contains<B>,
+{
+    A::does_contain
+}
+
+impl<T, U> Contains<T, { contains::<T, U>() }> for U where T: _Contains<U> {}
+
+fn writes_to_path<C>(cap: &C) {
+    writes_to_specific_path(&cap);
+    //~^ ERROR: the trait bound `(): _Contains<&C>` is not satisfied [E0277]
+    //~| ERROR: unconstrained generic constant
+}
+
+fn writes_to_specific_path<C: Delegates<()>>(cap: &C) {}
+
+fn main() {}
diff --git a/src/test/ui/const-generics/issues/issue-85848.stderr b/src/test/ui/const-generics/issues/issue-85848.stderr
new file mode 100644
index 00000000000..5e65136a6bc
--- /dev/null
+++ b/src/test/ui/const-generics/issues/issue-85848.stderr
@@ -0,0 +1,44 @@
+error[E0277]: the trait bound `(): _Contains<&C>` is not satisfied
+  --> $DIR/issue-85848.rs:24:5
+   |
+LL |     writes_to_specific_path(&cap);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^ the trait `_Contains<&C>` is not implemented for `()`
+...
+LL | fn writes_to_specific_path<C: Delegates<()>>(cap: &C) {}
+   |                               ------------- required by this bound in `writes_to_specific_path`
+   |
+note: required because of the requirements on the impl of `Contains<(), true>` for `&C`
+  --> $DIR/issue-85848.rs:21:12
+   |
+LL | impl<T, U> Contains<T, { contains::<T, U>() }> for U where T: _Contains<U> {}
+   |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^     ^
+note: required because of the requirements on the impl of `Delegates<()>` for `&C`
+  --> $DIR/issue-85848.rs:12:12
+   |
+LL | impl<T, U> Delegates<U> for T where T: Contains<U, true> {}
+   |            ^^^^^^^^^^^^     ^
+
+error: unconstrained generic constant
+  --> $DIR/issue-85848.rs:24:5
+   |
+LL |     writes_to_specific_path(&cap);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^
+...
+LL | fn writes_to_specific_path<C: Delegates<()>>(cap: &C) {}
+   |                               ------------- required by this bound in `writes_to_specific_path`
+   |
+   = help: try adding a `where` bound using this expression: `where [(); { contains::<T, U>() }]:`
+note: required because of the requirements on the impl of `Contains<(), true>` for `&C`
+  --> $DIR/issue-85848.rs:21:12
+   |
+LL | impl<T, U> Contains<T, { contains::<T, U>() }> for U where T: _Contains<U> {}
+   |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^     ^
+note: required because of the requirements on the impl of `Delegates<()>` for `&C`
+  --> $DIR/issue-85848.rs:12:12
+   |
+LL | impl<T, U> Delegates<U> for T where T: Contains<U, true> {}
+   |            ^^^^^^^^^^^^     ^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0277`.