Add utilities for creating generic types
This commit is contained in:
parent
ec7362442c
commit
7b8da7908f
4 changed files with 87 additions and 59 deletions
|
@ -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
|
||||||
|
|
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_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;
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue