Add utilities for creating generic types
This commit is contained in:
parent
ec7362442c
commit
7b8da7908f
@ -15,6 +15,7 @@ use rustc::hir::def_id::DefId;
|
||||
use rustc_target::spec::abi;
|
||||
use super::ChalkInferenceContext;
|
||||
use crate::lowering::Lower;
|
||||
use crate::generic_types;
|
||||
use std::iter;
|
||||
|
||||
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 {
|
||||
ty,
|
||||
mutbl: hir::Mutability::MutImmutable,
|
||||
});
|
||||
fn program_clauses_for_raw_ptr<'tcx>(
|
||||
tcx: ty::TyCtxt<'_, '_, 'tcx>,
|
||||
mutbl: hir::Mutability
|
||||
) -> Clauses<'tcx> {
|
||||
let ptr_ty = generic_types::raw_ptr(tcx, mutbl);
|
||||
|
||||
let wf_clause = ProgramClause {
|
||||
goal: DomainGoal::WellFormed(WellFormed::Ty(ptr_ty)),
|
||||
hypotheses: ty::List::empty(),
|
||||
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). }`
|
||||
tcx.mk_clauses(iter::once(wf_clause))
|
||||
@ -77,20 +73,7 @@ fn program_clauses_for_fn_ptr<'tcx>(
|
||||
unsafety: hir::Unsafety,
|
||||
abi: abi::Abi
|
||||
) -> Clauses<'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,
|
||||
});
|
||||
let fn_ptr = tcx.mk_fn_ptr(fn_sig);
|
||||
let fn_ptr = generic_types::fn_ptr(tcx, arity_and_output, variadic, unsafety, abi);
|
||||
|
||||
let wf_clause = ProgramClause {
|
||||
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> {
|
||||
let ty = ty::Bound(
|
||||
ty::INNERMOST,
|
||||
ty::BoundVar::from_u32(0).into()
|
||||
);
|
||||
let ty = tcx.mk_ty(ty);
|
||||
|
||||
let ty = generic_types::bound(tcx, 0);
|
||||
let slice_ty = tcx.mk_slice(ty);
|
||||
|
||||
let sized_trait = match tcx.lang_items().sized_trait() {
|
||||
@ -142,12 +120,7 @@ fn program_clauses_for_array<'tcx>(
|
||||
tcx: ty::TyCtxt<'_, '_, 'tcx>,
|
||||
length: &'tcx ty::Const<'tcx>
|
||||
) -> Clauses<'tcx> {
|
||||
let ty = ty::Bound(
|
||||
ty::INNERMOST,
|
||||
ty::BoundVar::from_u32(0).into()
|
||||
);
|
||||
let ty = tcx.mk_ty(ty);
|
||||
|
||||
let ty = generic_types::bound(tcx, 0);
|
||||
let array_ty = tcx.mk_ty(ty::Array(ty, length));
|
||||
|
||||
let sized_trait = match tcx.lang_items().sized_trait() {
|
||||
@ -179,12 +152,7 @@ fn program_clauses_for_tuple<'tcx>(
|
||||
tcx: ty::TyCtxt<'_, '_, 'tcx>,
|
||||
arity: usize
|
||||
) -> Clauses<'tcx> {
|
||||
let type_list = 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())))
|
||||
);
|
||||
|
||||
let type_list = generic_types::type_list(tcx, arity);
|
||||
let tuple_ty = tcx.mk_ty(ty::Tuple(type_list));
|
||||
|
||||
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))
|
||||
}
|
||||
|
||||
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(
|
||||
ty::ReLateBound(ty::INNERMOST, ty::BoundRegion::BrAnon(0))
|
||||
);
|
||||
let ty = tcx.mk_ty(
|
||||
ty::Bound(ty::INNERMOST, ty::BoundVar::from_u32(1).into())
|
||||
);
|
||||
|
||||
let ty = generic_types::bound(tcx, 1);
|
||||
let ref_ty = tcx.mk_ref(region, ty::TypeAndMut {
|
||||
ty,
|
||||
mutbl: hir::Mutability::MutImmutable,
|
||||
mutbl,
|
||||
});
|
||||
|
||||
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).
|
||||
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).
|
||||
ty::FnPtr(fn_ptr) => {
|
||||
@ -394,7 +362,7 @@ impl ChalkInferenceContext<'cx, 'gcx, 'tcx> {
|
||||
),
|
||||
|
||||
// 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(..) => {
|
||||
// FIXME: no rules yet for trait objects
|
||||
|
62
src/librustc_traits/generic_types.rs
Normal file
62
src/librustc_traits/generic_types.rs
Normal 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,
|
||||
})
|
||||
}
|
@ -25,6 +25,7 @@ mod implied_outlives_bounds;
|
||||
mod normalize_projection_ty;
|
||||
mod normalize_erasing_regions;
|
||||
pub mod lowering;
|
||||
mod generic_types;
|
||||
mod type_op;
|
||||
|
||||
use rustc::ty::query::Providers;
|
||||
|
@ -11,6 +11,7 @@ use rustc::ty::{self, TyCtxt, Ty};
|
||||
use rustc::hir::def_id::DefId;
|
||||
use rustc_data_structures::fx::FxHashSet;
|
||||
use super::Lower;
|
||||
use crate::generic_types;
|
||||
use std::iter;
|
||||
|
||||
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)` }
|
||||
ty::Ref(..) => {
|
||||
use rustc::hir;
|
||||
|
||||
ty::Ref(_, _, mutbl) => {
|
||||
let region = self.tcx.mk_region(
|
||||
ty::ReLateBound(ty::INNERMOST, ty::BoundRegion::BrAnon(0))
|
||||
);
|
||||
let ty = self.tcx.mk_ty(
|
||||
ty::Bound(ty::INNERMOST, ty::BoundVar::from_u32(1).into())
|
||||
);
|
||||
|
||||
let ty = generic_types::bound(self.tcx, 1);
|
||||
let ref_ty = self.tcx.mk_ref(region, ty::TypeAndMut {
|
||||
ty,
|
||||
mutbl: hir::Mutability::MutImmutable,
|
||||
mutbl,
|
||||
});
|
||||
|
||||
let from_env = DomainGoal::FromEnv(FromEnv::Ty(ref_ty));
|
||||
|
||||
let clause = ProgramClause {
|
||||
|
Loading…
Reference in New Issue
Block a user