]> git.lizzy.rs Git - rust.git/commitdiff
Fix chalk_ir assertion
authorFlorian Diebold <flodiebold@gmail.com>
Wed, 24 Mar 2021 22:07:54 +0000 (23:07 +0100)
committerFlorian Diebold <flodiebold@gmail.com>
Wed, 24 Mar 2021 22:10:13 +0000 (23:10 +0100)
Fixes #8150.

crates/hir_ty/src/lib.rs
crates/hir_ty/src/lower.rs
crates/hir_ty/src/traits/chalk.rs
crates/hir_ty/src/utils.rs

index 0f49dd39b5d6a715f34229f50888e0b7420f6de4..69265286f5f8caaf2a51244a992bf7dcb4d1dcb0 100644 (file)
@@ -538,12 +538,6 @@ pub fn subst(self, subst: &Substitution) -> T {
         assert_eq!(subst.len(), self.num_binders);
         self.value.subst_bound_vars(subst)
     }
-
-    /// Substitutes just a prefix of the variables (shifting the rest).
-    pub fn subst_prefix(self, subst: &Substitution) -> Binders<T> {
-        assert!(subst.len() < self.num_binders);
-        Binders::new(self.num_binders - subst.len(), self.value.subst_bound_vars(subst))
-    }
 }
 
 impl<T: TypeWalk> TypeWalk for Binders<T> {
@@ -698,7 +692,15 @@ pub fn from_params_and_return(mut params: Vec<Ty>, ret: Ty, is_varargs: bool) ->
 
     pub fn from_fn_ptr(fn_ptr: &FnPointer) -> CallableSig {
         CallableSig {
-            params_and_return: fn_ptr.substs.interned(&Interner).iter().cloned().collect(),
+            // FIXME: what to do about lifetime params?
+            params_and_return: fn_ptr
+                .substs
+                .clone()
+                .shift_bound_vars_out(DebruijnIndex::ONE)
+                .interned(&Interner)
+                .iter()
+                .cloned()
+                .collect(),
             is_varargs: fn_ptr.sig.variadic,
         }
     }
@@ -1131,6 +1133,23 @@ fn shift_bound_vars(self, n: DebruijnIndex) -> Self
             DebruijnIndex::INNERMOST,
         )
     }
+
+    /// Shifts debruijn indices of `TyKind::Bound` vars out (down) by `n`.
+    fn shift_bound_vars_out(self, n: DebruijnIndex) -> Self
+    where
+        Self: Sized + std::fmt::Debug,
+    {
+        self.fold_binders(
+            &mut |ty, binders| match ty.interned(&Interner) {
+                TyKind::BoundVar(bound) if bound.debruijn >= binders => {
+                    TyKind::BoundVar(bound.shifted_out_to(n).unwrap_or(bound.clone()))
+                        .intern(&Interner)
+                }
+                _ => ty,
+            },
+            DebruijnIndex::INNERMOST,
+        )
+    }
 }
 
 impl TypeWalk for Ty {
index 3153b5b74ff7a8eade36bfc059465f65474a93c5..c87789d45bdaa1d6fb8e72c1d1533bf88b5a051f 100644 (file)
@@ -828,14 +828,18 @@ pub fn associated_type_shorthand_candidates<R>(
     let traits_from_env: Vec<_> = match res {
         TypeNs::SelfType(impl_id) => match db.impl_trait(impl_id) {
             None => vec![],
-            Some(trait_ref) => vec![trait_ref.value],
+            // FIXME: how to correctly handle higher-ranked bounds here?
+            Some(trait_ref) => vec![trait_ref.value.shift_bound_vars_out(DebruijnIndex::ONE)],
         },
         TypeNs::GenericParam(param_id) => {
             let predicates = db.generic_predicates_for_param(param_id);
             let mut traits_: Vec<_> = predicates
                 .iter()
                 .filter_map(|pred| match &pred.value.value {
-                    WhereClause::Implemented(tr) => Some(tr.clone()),
+                    // FIXME: how to correctly handle higher-ranked bounds here?
+                    WhereClause::Implemented(tr) => {
+                        Some(tr.clone().shift_bound_vars_out(DebruijnIndex::ONE))
+                    }
                     _ => None,
                 })
                 .collect();
@@ -1156,10 +1160,9 @@ fn type_for_type_alias(db: &dyn HirDatabase, t: TypeAliasId) -> Binders<Ty> {
     if db.type_alias_data(t).is_extern {
         Binders::new(0, TyKind::ForeignType(crate::to_foreign_def_id(t)).intern(&Interner))
     } else {
-        let substs = Substitution::bound_vars(&generics, DebruijnIndex::INNERMOST);
         let type_ref = &db.type_alias_data(t).type_ref;
         let inner = ctx.lower_ty(type_ref.as_ref().unwrap_or(&TypeRef::Error));
-        Binders::new(substs.len(), inner)
+        Binders::new(generics.len(), inner)
     }
 }
 
index 4019fdf173112b12f76f58720d0785bdd7543ef0..011bef6f69324afe6627bbfea602b2223511fae0 100644 (file)
@@ -21,8 +21,8 @@
     method_resolution::{TyFingerprint, ALL_FLOAT_FPS, ALL_INT_FPS},
     to_assoc_type_id, to_chalk_trait_id,
     utils::generics,
-    AliasEq, AliasTy, BoundVar, CallableDefId, CallableSig, DebruijnIndex, FnDefId, ProjectionTy,
-    Substitution, TraitRef, Ty, TyKind, WhereClause,
+    AliasEq, AliasTy, BoundVar, CallableDefId, DebruijnIndex, FnDefId, ProjectionTy, Substitution,
+    TraitRef, Ty, TyKind, WhereClause,
 };
 use mapping::{
     convert_where_clauses, generic_predicate_to_inline_bound, make_binders, TypeAliasAsValue,
@@ -288,9 +288,7 @@ fn closure_inputs_and_output(
     ) -> chalk_ir::Binders<rust_ir::FnDefInputsAndOutputDatum<Interner>> {
         let sig_ty: Ty =
             from_chalk(self.db, substs.at(&Interner, 0).assert_ty_ref(&Interner).clone());
-        let sig = CallableSig::from_substs(
-            &sig_ty.substs().expect("first closure param should be fn ptr"),
-        );
+        let sig = &sig_ty.callable_sig(self.db).expect("first closure param should be fn ptr");
         let io = rust_ir::FnDefInputsAndOutputDatum {
             argument_types: sig.params().iter().map(|ty| ty.clone().to_chalk(self.db)).collect(),
             return_type: sig.ret().clone().to_chalk(self.db),
index 19874e42b130d0171edf0fd94ffc4101ee65774d..42d7af146542410ead4e77ff70946c3380170598 100644 (file)
@@ -2,6 +2,7 @@
 //! query, but can't be computed directly from `*Data` (ie, which need a `db`).
 use std::sync::Arc;
 
+use chalk_ir::DebruijnIndex;
 use hir_def::{
     adt::VariantData,
     db::DefDatabase,
@@ -15,7 +16,7 @@
 };
 use hir_expand::name::{name, Name};
 
-use crate::{db::HirDatabase, TraitRef, WhereClause};
+use crate::{db::HirDatabase, TraitRef, TypeWalk, WhereClause};
 
 fn direct_super_traits(db: &dyn DefDatabase, trait_: TraitId) -> Vec<TraitId> {
     let resolver = trait_.resolver(db);
@@ -64,7 +65,10 @@ fn direct_super_trait_refs(db: &dyn HirDatabase, trait_ref: &TraitRef) -> Vec<Tr
         .iter()
         .filter_map(|pred| {
             pred.as_ref().filter_map(|pred| match pred.skip_binders() {
-                WhereClause::Implemented(tr) => Some(tr.clone()),
+                // FIXME: how to correctly handle higher-ranked bounds here?
+                WhereClause::Implemented(tr) => {
+                    Some(tr.clone().shift_bound_vars_out(DebruijnIndex::ONE))
+                }
                 _ => None,
             })
         })