From 183466550808dbce73709a2202d5f84fdfb8ddc1 Mon Sep 17 00:00:00 2001 From: scalexm Date: Fri, 8 Feb 2019 13:10:52 +0100 Subject: [PATCH] Add unsize impls for arrays --- .../chalk_context/program_clauses/builtin.rs | 76 +++++++++++++++++++ .../chalk_context/program_clauses/mod.rs | 12 +++ 2 files changed, 88 insertions(+) diff --git a/src/librustc_traits/chalk_context/program_clauses/builtin.rs b/src/librustc_traits/chalk_context/program_clauses/builtin.rs index 3622cacbb012..ae9f1a27b942 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> +) { + 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 { + // 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 { 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 b6fb70b05777..80fbd97c5876 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`