Add builtin impls for Sized
in chalk_context::program_clauses
This commit is contained in:
parent
6f488b945e
commit
dfcad82509
@ -10,6 +10,7 @@ use rustc::traits::{
|
||||
Environment,
|
||||
};
|
||||
use rustc::ty;
|
||||
use rustc::ty::subst::{Substs, Subst};
|
||||
use rustc::hir;
|
||||
use rustc::hir::def_id::DefId;
|
||||
use rustc_target::spec::abi;
|
||||
@ -48,6 +49,126 @@ fn assemble_clauses_from_assoc_ty_values<'tcx>(
|
||||
});
|
||||
}
|
||||
|
||||
fn assemble_builtin_sized_impls<'tcx>(
|
||||
tcx: ty::TyCtxt<'_, '_, 'tcx>,
|
||||
sized_def_id: DefId,
|
||||
ty: ty::Ty<'tcx>,
|
||||
clauses: &mut Vec<Clause<'tcx>>
|
||||
) {
|
||||
let mut push_builtin_impl = |ty: ty::Ty<'tcx>, nested: &[ty::Ty<'tcx>]| {
|
||||
let clause = ProgramClause {
|
||||
goal: ty::TraitPredicate {
|
||||
trait_ref: ty::TraitRef {
|
||||
def_id: sized_def_id,
|
||||
substs: tcx.mk_substs_trait(ty, &[]),
|
||||
},
|
||||
}.lower(),
|
||||
hypotheses: tcx.mk_goals(
|
||||
nested.iter()
|
||||
.cloned()
|
||||
.map(|nested_ty| ty::TraitRef {
|
||||
def_id: sized_def_id,
|
||||
substs: tcx.mk_substs_trait(nested_ty, &[]),
|
||||
})
|
||||
.map(|trait_ref| ty::TraitPredicate { trait_ref })
|
||||
.map(|pred| GoalKind::DomainGoal(pred.lower()))
|
||||
.map(|goal_kind| tcx.mk_goal(goal_kind))
|
||||
),
|
||||
category: ProgramClauseCategory::Other,
|
||||
};
|
||||
// Bind innermost bound vars that may exist in `ty` and `nested`.
|
||||
clauses.push(Clause::ForAll(ty::Binder::bind(clause)));
|
||||
};
|
||||
|
||||
match &ty.sty {
|
||||
// Non parametric primitive types.
|
||||
ty::Bool |
|
||||
ty::Char |
|
||||
ty::Int(..) |
|
||||
ty::Uint(..) |
|
||||
ty::Float(..) |
|
||||
ty::Error |
|
||||
ty::Never => push_builtin_impl(ty, &[]),
|
||||
|
||||
// These ones are always `Sized`.
|
||||
&ty::Array(_, length) => {
|
||||
push_builtin_impl(tcx.mk_ty(ty::Array(generic_types::bound(tcx, 0), length)), &[]);
|
||||
}
|
||||
ty::RawPtr(ptr) => {
|
||||
push_builtin_impl(generic_types::raw_ptr(tcx, ptr.mutbl), &[]);
|
||||
}
|
||||
&ty::Ref(_, _, mutbl) => {
|
||||
push_builtin_impl(generic_types::ref_ty(tcx, mutbl), &[]);
|
||||
}
|
||||
ty::FnPtr(fn_ptr) => {
|
||||
let fn_ptr = fn_ptr.skip_binder();
|
||||
let fn_ptr = generic_types::fn_ptr(
|
||||
tcx,
|
||||
fn_ptr.inputs_and_output.len(),
|
||||
fn_ptr.variadic,
|
||||
fn_ptr.unsafety,
|
||||
fn_ptr.abi
|
||||
);
|
||||
push_builtin_impl(fn_ptr, &[]);
|
||||
}
|
||||
&ty::FnDef(def_id, ..) => {
|
||||
push_builtin_impl(generic_types::fn_def(tcx, def_id), &[]);
|
||||
}
|
||||
&ty::Closure(def_id, ..) => {
|
||||
push_builtin_impl(generic_types::closure(tcx, def_id), &[]);
|
||||
}
|
||||
&ty::Generator(def_id, ..) => {
|
||||
push_builtin_impl(generic_types::generator(tcx, def_id), &[]);
|
||||
}
|
||||
|
||||
// `Sized` if the last type is `Sized` (because else we will get a WF error anyway).
|
||||
&ty::Tuple(type_list) => {
|
||||
let type_list = generic_types::type_list(tcx, type_list.len());
|
||||
push_builtin_impl(tcx.mk_ty(ty::Tuple(type_list)), &**type_list);
|
||||
}
|
||||
|
||||
// Struct def
|
||||
ty::Adt(adt_def, _) => {
|
||||
let substs = Substs::bound_vars_for_item(tcx, adt_def.did);
|
||||
let adt = tcx.mk_ty(ty::Adt(adt_def, substs));
|
||||
let sized_constraint = adt_def.sized_constraint(tcx)
|
||||
.iter()
|
||||
.map(|ty| ty.subst(tcx, substs))
|
||||
.collect::<Vec<_>>();
|
||||
push_builtin_impl(adt, &sized_constraint);
|
||||
}
|
||||
|
||||
// Artificially trigger an ambiguity.
|
||||
ty::Infer(..) => {
|
||||
// Everybody can find at least two types to unify against:
|
||||
// general ty vars, int vars and float vars.
|
||||
push_builtin_impl(tcx.types.i32, &[]);
|
||||
push_builtin_impl(tcx.types.u32, &[]);
|
||||
push_builtin_impl(tcx.types.f32, &[]);
|
||||
push_builtin_impl(tcx.types.f64, &[]);
|
||||
}
|
||||
|
||||
ty::Projection(_projection_ty) => {
|
||||
// FIXME: add builtin impls from the associated type values found in
|
||||
// trait impls of `projection_ty.trait_ref(tcx)`.
|
||||
}
|
||||
|
||||
// The `Sized` bound can only come from the environment.
|
||||
ty::Param(..) |
|
||||
ty::Placeholder(..) |
|
||||
ty::UnnormalizedProjection(..) => (),
|
||||
|
||||
// Definitely not `Sized`.
|
||||
ty::Foreign(..) |
|
||||
ty::Str |
|
||||
ty::Slice(..) |
|
||||
ty::Dynamic(..) |
|
||||
ty::Opaque(..) => (),
|
||||
|
||||
ty::Bound(..) |
|
||||
ty::GeneratorWitness(..) => bug!("unexpected type {:?}", ty),
|
||||
}
|
||||
}
|
||||
|
||||
fn wf_clause_for_raw_ptr<'tcx>(
|
||||
tcx: ty::TyCtxt<'_, '_, 'tcx>,
|
||||
@ -236,12 +357,22 @@ impl ChalkInferenceContext<'cx, 'gcx, 'tcx> {
|
||||
// * the trait decl (rule `Implemented-From-Env`)
|
||||
|
||||
let mut clauses = vec![];
|
||||
|
||||
assemble_clauses_from_impls(
|
||||
self.infcx.tcx,
|
||||
trait_predicate.def_id(),
|
||||
&mut clauses
|
||||
);
|
||||
|
||||
if Some(trait_predicate.def_id()) == self.infcx.tcx.lang_items().sized_trait() {
|
||||
assemble_builtin_sized_impls(
|
||||
self.infcx.tcx,
|
||||
trait_predicate.def_id(),
|
||||
trait_predicate.self_ty(),
|
||||
&mut clauses
|
||||
);
|
||||
}
|
||||
|
||||
// FIXME: we need to add special rules for builtin impls:
|
||||
// * `Copy` / `Clone`
|
||||
// * `Sized`
|
||||
|
@ -1,7 +1,9 @@
|
||||
//! Utilities for creating generic types with bound vars in place of parameter values.
|
||||
|
||||
use rustc::ty::{self, Ty, TyCtxt};
|
||||
use rustc::ty::subst::Substs;
|
||||
use rustc::hir;
|
||||
use rustc::hir::def_id::DefId;
|
||||
use rustc_target::spec::abi;
|
||||
|
||||
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
|
||||
)
|
||||
}
|
||||
|
||||
crate fn _ref_ty(tcx: ty::TyCtxt<'_, '_, 'tcx>, mutbl: hir::Mutability) -> Ty<'tcx> {
|
||||
crate fn ref_ty(tcx: ty::TyCtxt<'_, '_, 'tcx>, mutbl: hir::Mutability) -> Ty<'tcx> {
|
||||
let region = tcx.mk_region(
|
||||
ty::ReLateBound(ty::INNERMOST, ty::BoundRegion::BrAnon(0))
|
||||
);
|
||||
@ -60,3 +62,19 @@ crate fn _ref_ty(tcx: ty::TyCtxt<'_, '_, 'tcx>, mutbl: hir::Mutability) -> Ty<'t
|
||||
mutbl,
|
||||
})
|
||||
}
|
||||
|
||||
crate fn fn_def(tcx: ty::TyCtxt<'_, '_, 'tcx>, def_id: DefId) -> Ty<'tcx> {
|
||||
tcx.mk_ty(ty::FnDef(def_id, Substs::bound_vars_for_item(tcx, def_id)))
|
||||
}
|
||||
|
||||
crate fn closure(tcx: ty::TyCtxt<'_, '_, 'tcx>, def_id: DefId) -> Ty<'tcx> {
|
||||
tcx.mk_closure(def_id, ty::ClosureSubsts {
|
||||
substs: Substs::bound_vars_for_item(tcx, def_id),
|
||||
})
|
||||
}
|
||||
|
||||
crate fn generator(tcx: ty::TyCtxt<'_, '_, 'tcx>, def_id: DefId) -> Ty<'tcx> {
|
||||
tcx.mk_generator(def_id, ty::GeneratorSubsts {
|
||||
substs: Substs::bound_vars_for_item(tcx, def_id),
|
||||
}, hir::GeneratorMovability::Movable)
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user