Skip to content

Commit dfcad82

Browse files
committed
Add builtin impls for Sized in chalk_context::program_clauses
1 parent 6f488b9 commit dfcad82

File tree

2 files changed

+150
-1
lines changed

2 files changed

+150
-1
lines changed

src/librustc_traits/chalk_context/program_clauses.rs

Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ use rustc::traits::{
1010
Environment,
1111
};
1212
use rustc::ty;
13+
use rustc::ty::subst::{Substs, Subst};
1314
use rustc::hir;
1415
use rustc::hir::def_id::DefId;
1516
use rustc_target::spec::abi;
@@ -48,6 +49,126 @@ fn assemble_clauses_from_assoc_ty_values<'tcx>(
4849
});
4950
}
5051

52+
fn assemble_builtin_sized_impls<'tcx>(
53+
tcx: ty::TyCtxt<'_, '_, 'tcx>,
54+
sized_def_id: DefId,
55+
ty: ty::Ty<'tcx>,
56+
clauses: &mut Vec<Clause<'tcx>>
57+
) {
58+
let mut push_builtin_impl = |ty: ty::Ty<'tcx>, nested: &[ty::Ty<'tcx>]| {
59+
let clause = ProgramClause {
60+
goal: ty::TraitPredicate {
61+
trait_ref: ty::TraitRef {
62+
def_id: sized_def_id,
63+
substs: tcx.mk_substs_trait(ty, &[]),
64+
},
65+
}.lower(),
66+
hypotheses: tcx.mk_goals(
67+
nested.iter()
68+
.cloned()
69+
.map(|nested_ty| ty::TraitRef {
70+
def_id: sized_def_id,
71+
substs: tcx.mk_substs_trait(nested_ty, &[]),
72+
})
73+
.map(|trait_ref| ty::TraitPredicate { trait_ref })
74+
.map(|pred| GoalKind::DomainGoal(pred.lower()))
75+
.map(|goal_kind| tcx.mk_goal(goal_kind))
76+
),
77+
category: ProgramClauseCategory::Other,
78+
};
79+
// Bind innermost bound vars that may exist in `ty` and `nested`.
80+
clauses.push(Clause::ForAll(ty::Binder::bind(clause)));
81+
};
82+
83+
match &ty.sty {
84+
// Non parametric primitive types.
85+
ty::Bool |
86+
ty::Char |
87+
ty::Int(..) |
88+
ty::Uint(..) |
89+
ty::Float(..) |
90+
ty::Error |
91+
ty::Never => push_builtin_impl(ty, &[]),
92+
93+
// These ones are always `Sized`.
94+
&ty::Array(_, length) => {
95+
push_builtin_impl(tcx.mk_ty(ty::Array(generic_types::bound(tcx, 0), length)), &[]);
96+
}
97+
ty::RawPtr(ptr) => {
98+
push_builtin_impl(generic_types::raw_ptr(tcx, ptr.mutbl), &[]);
99+
}
100+
&ty::Ref(_, _, mutbl) => {
101+
push_builtin_impl(generic_types::ref_ty(tcx, mutbl), &[]);
102+
}
103+
ty::FnPtr(fn_ptr) => {
104+
let fn_ptr = fn_ptr.skip_binder();
105+
let fn_ptr = generic_types::fn_ptr(
106+
tcx,
107+
fn_ptr.inputs_and_output.len(),
108+
fn_ptr.variadic,
109+
fn_ptr.unsafety,
110+
fn_ptr.abi
111+
);
112+
push_builtin_impl(fn_ptr, &[]);
113+
}
114+
&ty::FnDef(def_id, ..) => {
115+
push_builtin_impl(generic_types::fn_def(tcx, def_id), &[]);
116+
}
117+
&ty::Closure(def_id, ..) => {
118+
push_builtin_impl(generic_types::closure(tcx, def_id), &[]);
119+
}
120+
&ty::Generator(def_id, ..) => {
121+
push_builtin_impl(generic_types::generator(tcx, def_id), &[]);
122+
}
123+
124+
// `Sized` if the last type is `Sized` (because else we will get a WF error anyway).
125+
&ty::Tuple(type_list) => {
126+
let type_list = generic_types::type_list(tcx, type_list.len());
127+
push_builtin_impl(tcx.mk_ty(ty::Tuple(type_list)), &**type_list);
128+
}
129+
130+
// Struct def
131+
ty::Adt(adt_def, _) => {
132+
let substs = Substs::bound_vars_for_item(tcx, adt_def.did);
133+
let adt = tcx.mk_ty(ty::Adt(adt_def, substs));
134+
let sized_constraint = adt_def.sized_constraint(tcx)
135+
.iter()
136+
.map(|ty| ty.subst(tcx, substs))
137+
.collect::<Vec<_>>();
138+
push_builtin_impl(adt, &sized_constraint);
139+
}
140+
141+
// Artificially trigger an ambiguity.
142+
ty::Infer(..) => {
143+
// Everybody can find at least two types to unify against:
144+
// general ty vars, int vars and float vars.
145+
push_builtin_impl(tcx.types.i32, &[]);
146+
push_builtin_impl(tcx.types.u32, &[]);
147+
push_builtin_impl(tcx.types.f32, &[]);
148+
push_builtin_impl(tcx.types.f64, &[]);
149+
}
150+
151+
ty::Projection(_projection_ty) => {
152+
// FIXME: add builtin impls from the associated type values found in
153+
// trait impls of `projection_ty.trait_ref(tcx)`.
154+
}
155+
156+
// The `Sized` bound can only come from the environment.
157+
ty::Param(..) |
158+
ty::Placeholder(..) |
159+
ty::UnnormalizedProjection(..) => (),
160+
161+
// Definitely not `Sized`.
162+
ty::Foreign(..) |
163+
ty::Str |
164+
ty::Slice(..) |
165+
ty::Dynamic(..) |
166+
ty::Opaque(..) => (),
167+
168+
ty::Bound(..) |
169+
ty::GeneratorWitness(..) => bug!("unexpected type {:?}", ty),
170+
}
171+
}
51172

52173
fn wf_clause_for_raw_ptr<'tcx>(
53174
tcx: ty::TyCtxt<'_, '_, 'tcx>,
@@ -236,12 +357,22 @@ impl ChalkInferenceContext<'cx, 'gcx, 'tcx> {
236357
// * the trait decl (rule `Implemented-From-Env`)
237358

238359
let mut clauses = vec![];
360+
239361
assemble_clauses_from_impls(
240362
self.infcx.tcx,
241363
trait_predicate.def_id(),
242364
&mut clauses
243365
);
244366

367+
if Some(trait_predicate.def_id()) == self.infcx.tcx.lang_items().sized_trait() {
368+
assemble_builtin_sized_impls(
369+
self.infcx.tcx,
370+
trait_predicate.def_id(),
371+
trait_predicate.self_ty(),
372+
&mut clauses
373+
);
374+
}
375+
245376
// FIXME: we need to add special rules for builtin impls:
246377
// * `Copy` / `Clone`
247378
// * `Sized`

src/librustc_traits/generic_types.rs

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
//! Utilities for creating generic types with bound vars in place of parameter values.
22
33
use rustc::ty::{self, Ty, TyCtxt};
4+
use rustc::ty::subst::Substs;
45
use rustc::hir;
6+
use rustc::hir::def_id::DefId;
57
use rustc_target::spec::abi;
68

79
crate fn bound(tcx: ty::TyCtxt<'_, '_, 'tcx>, index: u32) -> Ty<'tcx> {
@@ -50,7 +52,7 @@ crate fn type_list(tcx: ty::TyCtxt<'_, '_, 'tcx>, arity: usize) -> &'tcx ty::Lis
5052
)
5153
}
5254

53-
crate fn _ref_ty(tcx: ty::TyCtxt<'_, '_, 'tcx>, mutbl: hir::Mutability) -> Ty<'tcx> {
55+
crate fn ref_ty(tcx: ty::TyCtxt<'_, '_, 'tcx>, mutbl: hir::Mutability) -> Ty<'tcx> {
5456
let region = tcx.mk_region(
5557
ty::ReLateBound(ty::INNERMOST, ty::BoundRegion::BrAnon(0))
5658
);
@@ -60,3 +62,19 @@ crate fn _ref_ty(tcx: ty::TyCtxt<'_, '_, 'tcx>, mutbl: hir::Mutability) -> Ty<'t
6062
mutbl,
6163
})
6264
}
65+
66+
crate fn fn_def(tcx: ty::TyCtxt<'_, '_, 'tcx>, def_id: DefId) -> Ty<'tcx> {
67+
tcx.mk_ty(ty::FnDef(def_id, Substs::bound_vars_for_item(tcx, def_id)))
68+
}
69+
70+
crate fn closure(tcx: ty::TyCtxt<'_, '_, 'tcx>, def_id: DefId) -> Ty<'tcx> {
71+
tcx.mk_closure(def_id, ty::ClosureSubsts {
72+
substs: Substs::bound_vars_for_item(tcx, def_id),
73+
})
74+
}
75+
76+
crate fn generator(tcx: ty::TyCtxt<'_, '_, 'tcx>, def_id: DefId) -> Ty<'tcx> {
77+
tcx.mk_generator(def_id, ty::GeneratorSubsts {
78+
substs: Substs::bound_vars_for_item(tcx, def_id),
79+
}, hir::GeneratorMovability::Movable)
80+
}

0 commit comments

Comments
 (0)