1
Fork 0

Add utilities for creating generic types

This commit is contained in:
scalexm 2018-11-23 22:43:59 +01:00
parent ec7362442c
commit 7b8da7908f
4 changed files with 87 additions and 59 deletions

View file

@ -15,6 +15,7 @@ use rustc::hir::def_id::DefId;
use rustc_target::spec::abi; use rustc_target::spec::abi;
use super::ChalkInferenceContext; use super::ChalkInferenceContext;
use crate::lowering::Lower; use crate::lowering::Lower;
use crate::generic_types;
use std::iter; use std::iter;
fn assemble_clauses_from_impls<'tcx>( fn assemble_clauses_from_impls<'tcx>(
@ -47,24 +48,19 @@ fn assemble_clauses_from_assoc_ty_values<'tcx>(
}); });
} }
fn program_clauses_for_raw_ptr<'tcx>(tcx: ty::TyCtxt<'_, '_, 'tcx>) -> Clauses<'tcx> {
let ty = ty::Bound(
ty::INNERMOST,
ty::BoundVar::from_u32(0).into()
);
let ty = tcx.mk_ty(ty);
let ptr_ty = tcx.mk_ptr(ty::TypeAndMut { fn program_clauses_for_raw_ptr<'tcx>(
ty, tcx: ty::TyCtxt<'_, '_, 'tcx>,
mutbl: hir::Mutability::MutImmutable, mutbl: hir::Mutability
}); ) -> Clauses<'tcx> {
let ptr_ty = generic_types::raw_ptr(tcx, mutbl);
let wf_clause = ProgramClause { let wf_clause = ProgramClause {
goal: DomainGoal::WellFormed(WellFormed::Ty(ptr_ty)), goal: DomainGoal::WellFormed(WellFormed::Ty(ptr_ty)),
hypotheses: ty::List::empty(), hypotheses: ty::List::empty(),
category: ProgramClauseCategory::WellFormed, category: ProgramClauseCategory::WellFormed,
}; };
let wf_clause = Clause::ForAll(ty::Binder::bind(wf_clause)); let wf_clause = Clause::Implies(wf_clause);
// `forall<T> { WellFormed(*const T). }` // `forall<T> { WellFormed(*const T). }`
tcx.mk_clauses(iter::once(wf_clause)) tcx.mk_clauses(iter::once(wf_clause))
@ -77,20 +73,7 @@ fn program_clauses_for_fn_ptr<'tcx>(
unsafety: hir::Unsafety, unsafety: hir::Unsafety,
abi: abi::Abi abi: abi::Abi
) -> Clauses<'tcx> { ) -> Clauses<'tcx> {
let inputs_and_output = tcx.mk_type_list( let fn_ptr = generic_types::fn_ptr(tcx, arity_and_output, variadic, unsafety, abi);
(0..arity_and_output).into_iter()
.map(|i| ty::BoundVar::from(i))
// DebruijnIndex(1) because we are going to inject these in a `PolyFnSig`
.map(|var| tcx.mk_ty(ty::Bound(ty::DebruijnIndex::from(1usize), var.into())))
);
let fn_sig = ty::Binder::bind(ty::FnSig {
inputs_and_output,
variadic,
unsafety,
abi,
});
let fn_ptr = tcx.mk_fn_ptr(fn_sig);
let wf_clause = ProgramClause { let wf_clause = ProgramClause {
goal: DomainGoal::WellFormed(WellFormed::Ty(fn_ptr)), goal: DomainGoal::WellFormed(WellFormed::Ty(fn_ptr)),
@ -105,12 +88,7 @@ fn program_clauses_for_fn_ptr<'tcx>(
} }
fn program_clauses_for_slice<'tcx>(tcx: ty::TyCtxt<'_, '_, 'tcx>) -> Clauses<'tcx> { fn program_clauses_for_slice<'tcx>(tcx: ty::TyCtxt<'_, '_, 'tcx>) -> Clauses<'tcx> {
let ty = ty::Bound( let ty = generic_types::bound(tcx, 0);
ty::INNERMOST,
ty::BoundVar::from_u32(0).into()
);
let ty = tcx.mk_ty(ty);
let slice_ty = tcx.mk_slice(ty); let slice_ty = tcx.mk_slice(ty);
let sized_trait = match tcx.lang_items().sized_trait() { let sized_trait = match tcx.lang_items().sized_trait() {
@ -142,12 +120,7 @@ fn program_clauses_for_array<'tcx>(
tcx: ty::TyCtxt<'_, '_, 'tcx>, tcx: ty::TyCtxt<'_, '_, 'tcx>,
length: &'tcx ty::Const<'tcx> length: &'tcx ty::Const<'tcx>
) -> Clauses<'tcx> { ) -> Clauses<'tcx> {
let ty = ty::Bound( let ty = generic_types::bound(tcx, 0);
ty::INNERMOST,
ty::BoundVar::from_u32(0).into()
);
let ty = tcx.mk_ty(ty);
let array_ty = tcx.mk_ty(ty::Array(ty, length)); let array_ty = tcx.mk_ty(ty::Array(ty, length));
let sized_trait = match tcx.lang_items().sized_trait() { let sized_trait = match tcx.lang_items().sized_trait() {
@ -179,12 +152,7 @@ fn program_clauses_for_tuple<'tcx>(
tcx: ty::TyCtxt<'_, '_, 'tcx>, tcx: ty::TyCtxt<'_, '_, 'tcx>,
arity: usize arity: usize
) -> Clauses<'tcx> { ) -> Clauses<'tcx> {
let type_list = tcx.mk_type_list( let type_list = generic_types::type_list(tcx, arity);
(0..arity).into_iter()
.map(|i| ty::BoundVar::from(i))
.map(|var| tcx.mk_ty(ty::Bound(ty::INNERMOST, var.into())))
);
let tuple_ty = tcx.mk_ty(ty::Tuple(type_list)); let tuple_ty = tcx.mk_ty(ty::Tuple(type_list));
let sized_trait = match tcx.lang_items().sized_trait() { let sized_trait = match tcx.lang_items().sized_trait() {
@ -221,17 +189,17 @@ fn program_clauses_for_tuple<'tcx>(
tcx.mk_clauses(iter::once(wf_clause)) tcx.mk_clauses(iter::once(wf_clause))
} }
fn program_clauses_for_ref<'tcx>(tcx: ty::TyCtxt<'_, '_, 'tcx>) -> Clauses<'tcx> { fn program_clauses_for_ref<'tcx>(
tcx: ty::TyCtxt<'_, '_, 'tcx>,
mutbl: hir::Mutability
) -> Clauses<'tcx> {
let region = tcx.mk_region( let region = tcx.mk_region(
ty::ReLateBound(ty::INNERMOST, ty::BoundRegion::BrAnon(0)) ty::ReLateBound(ty::INNERMOST, ty::BoundRegion::BrAnon(0))
); );
let ty = tcx.mk_ty( let ty = generic_types::bound(tcx, 1);
ty::Bound(ty::INNERMOST, ty::BoundVar::from_u32(1).into())
);
let ref_ty = tcx.mk_ref(region, ty::TypeAndMut { let ref_ty = tcx.mk_ref(region, ty::TypeAndMut {
ty, ty,
mutbl: hir::Mutability::MutImmutable, mutbl,
}); });
let outlives: DomainGoal = ty::OutlivesPredicate(ty, region).lower(); let outlives: DomainGoal = ty::OutlivesPredicate(ty, region).lower();
@ -367,7 +335,7 @@ impl ChalkInferenceContext<'cx, 'gcx, 'tcx> {
} }
// Always WF (recall that we do not check for parameters to be WF). // Always WF (recall that we do not check for parameters to be WF).
ty::RawPtr(..) => program_clauses_for_raw_ptr(self.infcx.tcx), ty::RawPtr(ptr) => program_clauses_for_raw_ptr(self.infcx.tcx, ptr.mutbl),
// Always WF (recall that we do not check for parameters to be WF). // Always WF (recall that we do not check for parameters to be WF).
ty::FnPtr(fn_ptr) => { ty::FnPtr(fn_ptr) => {
@ -394,7 +362,7 @@ impl ChalkInferenceContext<'cx, 'gcx, 'tcx> {
), ),
// WF if `sub_ty` outlives `region`. // WF if `sub_ty` outlives `region`.
ty::Ref(..) => program_clauses_for_ref(self.infcx.tcx), ty::Ref(_, _, mutbl) => program_clauses_for_ref(self.infcx.tcx, mutbl),
ty::Dynamic(..) => { ty::Dynamic(..) => {
// FIXME: no rules yet for trait objects // FIXME: no rules yet for trait objects

View file

@ -0,0 +1,62 @@
//! Utilities for creating generic types with bound vars in place of parameter values.
use rustc::ty::{self, Ty, TyCtxt};
use rustc::hir;
use rustc_target::spec::abi;
crate fn bound(tcx: ty::TyCtxt<'_, '_, 'tcx>, index: u32) -> Ty<'tcx> {
let ty = ty::Bound(
ty::INNERMOST,
ty::BoundVar::from_u32(index).into()
);
tcx.mk_ty(ty)
}
crate fn raw_ptr(tcx: TyCtxt<'_, '_, 'tcx>, mutbl: hir::Mutability) -> Ty<'tcx> {
tcx.mk_ptr(ty::TypeAndMut {
ty: bound(tcx, 0),
mutbl,
})
}
crate fn fn_ptr(
tcx: ty::TyCtxt<'_, '_, 'tcx>,
arity_and_output: usize,
variadic: bool,
unsafety: hir::Unsafety,
abi: abi::Abi
) -> Ty<'tcx> {
let inputs_and_output = tcx.mk_type_list(
(0..arity_and_output).into_iter()
.map(|i| ty::BoundVar::from(i))
// DebruijnIndex(1) because we are going to inject these in a `PolyFnSig`
.map(|var| tcx.mk_ty(ty::Bound(ty::DebruijnIndex::from(1usize), var.into())))
);
let fn_sig = ty::Binder::bind(ty::FnSig {
inputs_and_output,
variadic,
unsafety,
abi,
});
tcx.mk_fn_ptr(fn_sig)
}
crate fn type_list(tcx: ty::TyCtxt<'_, '_, 'tcx>, arity: usize) -> &'tcx ty::List<Ty<'tcx>> {
tcx.mk_type_list(
(0..arity).into_iter()
.map(|i| ty::BoundVar::from(i))
.map(|var| tcx.mk_ty(ty::Bound(ty::INNERMOST, var.into())))
)
}
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))
);
tcx.mk_ref(region, ty::TypeAndMut {
ty: bound(tcx, 1),
mutbl,
})
}

View file

@ -25,6 +25,7 @@ mod implied_outlives_bounds;
mod normalize_projection_ty; mod normalize_projection_ty;
mod normalize_erasing_regions; mod normalize_erasing_regions;
pub mod lowering; pub mod lowering;
mod generic_types;
mod type_op; mod type_op;
use rustc::ty::query::Providers; use rustc::ty::query::Providers;

View file

@ -11,6 +11,7 @@ use rustc::ty::{self, TyCtxt, Ty};
use rustc::hir::def_id::DefId; use rustc::hir::def_id::DefId;
use rustc_data_structures::fx::FxHashSet; use rustc_data_structures::fx::FxHashSet;
use super::Lower; use super::Lower;
use crate::generic_types;
use std::iter; use std::iter;
struct ClauseVisitor<'set, 'a, 'tcx: 'a + 'set> { struct ClauseVisitor<'set, 'a, 'tcx: 'a + 'set> {
@ -38,20 +39,16 @@ impl ClauseVisitor<'set, 'a, 'tcx> {
} }
// forall<'a, T> { `Outlives(T: 'a) :- FromEnv(&'a T)` } // forall<'a, T> { `Outlives(T: 'a) :- FromEnv(&'a T)` }
ty::Ref(..) => { ty::Ref(_, _, mutbl) => {
use rustc::hir;
let region = self.tcx.mk_region( let region = self.tcx.mk_region(
ty::ReLateBound(ty::INNERMOST, ty::BoundRegion::BrAnon(0)) ty::ReLateBound(ty::INNERMOST, ty::BoundRegion::BrAnon(0))
); );
let ty = self.tcx.mk_ty( let ty = generic_types::bound(self.tcx, 1);
ty::Bound(ty::INNERMOST, ty::BoundVar::from_u32(1).into())
);
let ref_ty = self.tcx.mk_ref(region, ty::TypeAndMut { let ref_ty = self.tcx.mk_ref(region, ty::TypeAndMut {
ty, ty,
mutbl: hir::Mutability::MutImmutable, mutbl,
}); });
let from_env = DomainGoal::FromEnv(FromEnv::Ty(ref_ty)); let from_env = DomainGoal::FromEnv(FromEnv::Ty(ref_ty));
let clause = ProgramClause { let clause = ProgramClause {