about summary refs log tree commit diff
diff options
context:
space:
mode:
authorscalexm <alexandre@scalexm.fr>2019-02-08 13:10:52 +0100
committerscalexm <alexandre@scalexm.fr>2019-03-20 20:09:26 +0100
commit183466550808dbce73709a2202d5f84fdfb8ddc1 (patch)
tree2d0c0586ea92e8498090d9ccdf5315b2c795b098
parent66b4a0852d4726dc9b4836e50cf7e23662c47ae2 (diff)
downloadrust-183466550808dbce73709a2202d5f84fdfb8ddc1.tar.gz
rust-183466550808dbce73709a2202d5f84fdfb8ddc1.zip
Add unsize impls for arrays
-rw-r--r--src/librustc_traits/chalk_context/program_clauses/builtin.rs76
-rw-r--r--src/librustc_traits/chalk_context/program_clauses/mod.rs12
2 files changed, 88 insertions, 0 deletions
diff --git a/src/librustc_traits/chalk_context/program_clauses/builtin.rs b/src/librustc_traits/chalk_context/program_clauses/builtin.rs
index 3622cacbb01..ae9f1a27b94 100644
--- a/src/librustc_traits/chalk_context/program_clauses/builtin.rs
+++ b/src/librustc_traits/chalk_context/program_clauses/builtin.rs
@@ -10,6 +10,82 @@ use rustc::hir::def_id::DefId;
 use crate::lowering::Lower;
 use crate::generic_types;
 
+crate fn assemble_builtin_unsize_impls<'tcx>(
+    tcx: ty::TyCtxt<'_, '_, 'tcx>,
+    unsize_def_id: DefId,
+    source: ty::Ty<'tcx>,
+    target: ty::Ty<'tcx>,
+    clauses: &mut Vec<Clause<'tcx>>
+) {
+    match (&source.sty, &target.sty) {
+        (ty::Dynamic(data_a, ..), ty::Dynamic(data_b, ..)) => {
+            if data_a.principal_def_id() != data_b.principal_def_id()
+                || data_b.auto_traits().any(|b| data_a.auto_traits().all(|a| a != b))
+            {
+                return;
+            }
+
+            // FIXME: rules for trait upcast
+        }
+
+        (_, &ty::Dynamic(..)) => {
+            // FIXME: basically, we should have something like:
+            // ```
+            // forall<T> {
+            //     Implemented(T: Unsize< for<...> dyn Trait<...> >) :-
+            //         for<...> Implemented(T: Trait<...>).
+            // }
+            // ```
+            // The question is: how to correctly handle the higher-ranked
+            // `for<...>` binder in order to have a generic rule?
+            // (Having generic rules is useful for caching, as we may be able
+            // to turn this function and others into tcx queries later on).
+        }
+
+        (ty::Array(_, length), ty::Slice(_)) => {
+            let ty_param = generic_types::bound(tcx, 0);
+            let array_ty = tcx.mk_ty(ty::Array(ty_param, length));
+            let slice_ty = tcx.mk_ty(ty::Slice(ty_param));
+
+            // `forall<T> { Implemented([T; N]: Unsize<[T]>). }`
+            let clause = ProgramClause {
+                goal: ty::TraitPredicate {
+                    trait_ref: ty::TraitRef {
+                        def_id: unsize_def_id,
+                        substs: tcx.mk_substs_trait(array_ty, &[slice_ty.into()])
+                    },
+                }.lower(),
+                hypotheses: ty::List::empty(),
+                category: ProgramClauseCategory::Other,
+            };
+
+            clauses.push(Clause::ForAll(ty::Binder::bind(clause)));
+        }
+
+        (ty::Infer(ty::TyVar(_)), _) | (_, ty::Infer(ty::TyVar(_))) => {
+            // FIXME: ambiguous
+        }
+
+        (ty::Adt(def_id_a, ..), ty::Adt(def_id_b, ..)) => {
+            if def_id_a != def_id_b {
+                return;
+            }
+
+            // FIXME: rules for struct unsizing
+        }
+
+        (&ty::Tuple(tys_a), &ty::Tuple(tys_b)) => {
+            if tys_a.len() != tys_b.len() {
+                return;
+            }
+
+            // FIXME: rules for tuple unsizing
+        }
+
+        _ => (),
+    }
+}
+
 crate fn assemble_builtin_sized_impls<'tcx>(
     tcx: ty::TyCtxt<'_, '_, 'tcx>,
     sized_def_id: DefId,
diff --git a/src/librustc_traits/chalk_context/program_clauses/mod.rs b/src/librustc_traits/chalk_context/program_clauses/mod.rs
index b6fb70b0577..80fbd97c587 100644
--- a/src/librustc_traits/chalk_context/program_clauses/mod.rs
+++ b/src/librustc_traits/chalk_context/program_clauses/mod.rs
@@ -84,6 +84,18 @@ impl ChalkInferenceContext<'cx, 'gcx, 'tcx> {
                     );
                 }
 
+                if Some(trait_predicate.def_id()) == self.infcx.tcx.lang_items().unsize_trait() {
+                    let source = trait_predicate.self_ty();
+                    let target = trait_predicate.trait_ref.substs.type_at(1);
+                    assemble_builtin_unsize_impls(
+                        self.infcx.tcx,
+                        trait_predicate.def_id(),
+                        source,
+                        target,
+                        &mut clauses
+                    );
+                }
+
                 // FIXME: we need to add special rules for other builtin impls:
                 // * `Copy` / `Clone`
                 // * `Generator`