diff options
| author | scalexm <alexandre@scalexm.fr> | 2019-02-08 13:10:52 +0100 |
|---|---|---|
| committer | scalexm <alexandre@scalexm.fr> | 2019-03-20 20:09:26 +0100 |
| commit | 183466550808dbce73709a2202d5f84fdfb8ddc1 (patch) | |
| tree | 2d0c0586ea92e8498090d9ccdf5315b2c795b098 | |
| parent | 66b4a0852d4726dc9b4836e50cf7e23662c47ae2 (diff) | |
| download | rust-183466550808dbce73709a2202d5f84fdfb8ddc1.tar.gz rust-183466550808dbce73709a2202d5f84fdfb8ddc1.zip | |
Add unsize impls for arrays
| -rw-r--r-- | src/librustc_traits/chalk_context/program_clauses/builtin.rs | 76 | ||||
| -rw-r--r-- | src/librustc_traits/chalk_context/program_clauses/mod.rs | 12 |
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` |
