Skip to content

Commit

Permalink
Add utilities for creating generic types
Browse files Browse the repository at this point in the history
  • Loading branch information
scalexm committed Dec 27, 2018
1 parent ec73624 commit 7b8da79
Show file tree
Hide file tree
Showing 4 changed files with 87 additions and 59 deletions.
70 changes: 19 additions & 51 deletions src/librustc_traits/chalk_context/program_clauses.rs
Expand Up @@ -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>(
Expand Down Expand Up @@ -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))
Expand All @@ -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)),
Expand All @@ -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() {
Expand Down Expand Up @@ -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() {
Expand Down Expand Up @@ -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() {
Expand Down Expand Up @@ -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();
Expand Down Expand Up @@ -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) => {
Expand All @@ -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
Expand Down
62 changes: 62 additions & 0 deletions src/librustc_traits/generic_types.rs
@@ -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,
})
}
1 change: 1 addition & 0 deletions src/librustc_traits/lib.rs
Expand Up @@ -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;
Expand Down
13 changes: 5 additions & 8 deletions src/librustc_traits/lowering/environment.rs
Expand Up @@ -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> {
Expand Down Expand Up @@ -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 {
Expand Down

0 comments on commit 7b8da79

Please sign in to comment.