Skip to content

Commit 1834665

Browse files
committed
Add unsize impls for arrays
1 parent 66b4a08 commit 1834665

File tree

2 files changed

+88
-0
lines changed

2 files changed

+88
-0
lines changed

src/librustc_traits/chalk_context/program_clauses/builtin.rs

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,82 @@ use rustc::hir::def_id::DefId;
1010
use crate::lowering::Lower;
1111
use crate::generic_types;
1212

13+
crate fn assemble_builtin_unsize_impls<'tcx>(
14+
tcx: ty::TyCtxt<'_, '_, 'tcx>,
15+
unsize_def_id: DefId,
16+
source: ty::Ty<'tcx>,
17+
target: ty::Ty<'tcx>,
18+
clauses: &mut Vec<Clause<'tcx>>
19+
) {
20+
match (&source.sty, &target.sty) {
21+
(ty::Dynamic(data_a, ..), ty::Dynamic(data_b, ..)) => {
22+
if data_a.principal_def_id() != data_b.principal_def_id()
23+
|| data_b.auto_traits().any(|b| data_a.auto_traits().all(|a| a != b))
24+
{
25+
return;
26+
}
27+
28+
// FIXME: rules for trait upcast
29+
}
30+
31+
(_, &ty::Dynamic(..)) => {
32+
// FIXME: basically, we should have something like:
33+
// ```
34+
// forall<T> {
35+
// Implemented(T: Unsize< for<...> dyn Trait<...> >) :-
36+
// for<...> Implemented(T: Trait<...>).
37+
// }
38+
// ```
39+
// The question is: how to correctly handle the higher-ranked
40+
// `for<...>` binder in order to have a generic rule?
41+
// (Having generic rules is useful for caching, as we may be able
42+
// to turn this function and others into tcx queries later on).
43+
}
44+
45+
(ty::Array(_, length), ty::Slice(_)) => {
46+
let ty_param = generic_types::bound(tcx, 0);
47+
let array_ty = tcx.mk_ty(ty::Array(ty_param, length));
48+
let slice_ty = tcx.mk_ty(ty::Slice(ty_param));
49+
50+
// `forall<T> { Implemented([T; N]: Unsize<[T]>). }`
51+
let clause = ProgramClause {
52+
goal: ty::TraitPredicate {
53+
trait_ref: ty::TraitRef {
54+
def_id: unsize_def_id,
55+
substs: tcx.mk_substs_trait(array_ty, &[slice_ty.into()])
56+
},
57+
}.lower(),
58+
hypotheses: ty::List::empty(),
59+
category: ProgramClauseCategory::Other,
60+
};
61+
62+
clauses.push(Clause::ForAll(ty::Binder::bind(clause)));
63+
}
64+
65+
(ty::Infer(ty::TyVar(_)), _) | (_, ty::Infer(ty::TyVar(_))) => {
66+
// FIXME: ambiguous
67+
}
68+
69+
(ty::Adt(def_id_a, ..), ty::Adt(def_id_b, ..)) => {
70+
if def_id_a != def_id_b {
71+
return;
72+
}
73+
74+
// FIXME: rules for struct unsizing
75+
}
76+
77+
(&ty::Tuple(tys_a), &ty::Tuple(tys_b)) => {
78+
if tys_a.len() != tys_b.len() {
79+
return;
80+
}
81+
82+
// FIXME: rules for tuple unsizing
83+
}
84+
85+
_ => (),
86+
}
87+
}
88+
1389
crate fn assemble_builtin_sized_impls<'tcx>(
1490
tcx: ty::TyCtxt<'_, '_, 'tcx>,
1591
sized_def_id: DefId,

src/librustc_traits/chalk_context/program_clauses/mod.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,18 @@ impl ChalkInferenceContext<'cx, 'gcx, 'tcx> {
8484
);
8585
}
8686

87+
if Some(trait_predicate.def_id()) == self.infcx.tcx.lang_items().unsize_trait() {
88+
let source = trait_predicate.self_ty();
89+
let target = trait_predicate.trait_ref.substs.type_at(1);
90+
assemble_builtin_unsize_impls(
91+
self.infcx.tcx,
92+
trait_predicate.def_id(),
93+
source,
94+
target,
95+
&mut clauses
96+
);
97+
}
98+
8799
// FIXME: we need to add special rules for other builtin impls:
88100
// * `Copy` / `Clone`
89101
// * `Generator`

0 commit comments

Comments
 (0)