Skip to content

Commit

Permalink
Add unsize impls for arrays
Browse files Browse the repository at this point in the history
  • Loading branch information
scalexm committed Mar 20, 2019
1 parent 66b4a08 commit 1834665
Show file tree
Hide file tree
Showing 2 changed files with 88 additions and 0 deletions.
76 changes: 76 additions & 0 deletions src/librustc_traits/chalk_context/program_clauses/builtin.rs
Expand Up @@ -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,
Expand Down
12 changes: 12 additions & 0 deletions src/librustc_traits/chalk_context/program_clauses/mod.rs
Expand Up @@ -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`
Expand Down

0 comments on commit 1834665

Please sign in to comment.