diff --git a/src/librustc_traits/chalk_context/program_clauses.rs b/src/librustc_traits/chalk_context/program_clauses.rs index 2b4970124e3..e660e0df747 100644 --- a/src/librustc_traits/chalk_context/program_clauses.rs +++ b/src/librustc_traits/chalk_context/program_clauses.rs @@ -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 { 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 diff --git a/src/librustc_traits/generic_types.rs b/src/librustc_traits/generic_types.rs new file mode 100644 index 00000000000..15d6d6c5168 --- /dev/null +++ b/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> { + 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, + }) +} diff --git a/src/librustc_traits/lib.rs b/src/librustc_traits/lib.rs index c05a017554a..d4548efdb63 100644 --- a/src/librustc_traits/lib.rs +++ b/src/librustc_traits/lib.rs @@ -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; diff --git a/src/librustc_traits/lowering/environment.rs b/src/librustc_traits/lowering/environment.rs index e21428acf63..abd776fab86 100644 --- a/src/librustc_traits/lowering/environment.rs +++ b/src/librustc_traits/lowering/environment.rs @@ -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 {