1
Fork 0

more through normalization in typeck & trans

Fixes #27901.
Fixes #28828.
Fixes #38135.
Fixes #39363.
This commit is contained in:
Ariel Ben-Yehuda 2017-03-01 01:30:41 +02:00
parent e1cb9ba221
commit ca8708273b
14 changed files with 121 additions and 110 deletions

View file

@ -596,10 +596,7 @@ pub fn trans_instance<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, instance: Instance
// release builds. // release builds.
info!("trans_instance({})", instance); info!("trans_instance({})", instance);
let fn_ty = ccx.tcx().item_type(instance.def); let fn_ty = common::def_ty(ccx.shared(), instance.def, instance.substs);
let fn_ty = ccx.tcx().erase_regions(&fn_ty);
let fn_ty = monomorphize::apply_param_substs(ccx.shared(), instance.substs, &fn_ty);
let sig = common::ty_fn_sig(ccx, fn_ty); let sig = common::ty_fn_sig(ccx, fn_ty);
let sig = ccx.tcx().erase_late_bound_regions_and_normalize(&sig); let sig = ccx.tcx().erase_late_bound_regions_and_normalize(&sig);
@ -626,9 +623,7 @@ pub fn trans_ctor_shim<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
attributes::inline(llfn, attributes::InlineAttr::Hint); attributes::inline(llfn, attributes::InlineAttr::Hint);
attributes::set_frame_pointer_elimination(ccx, llfn); attributes::set_frame_pointer_elimination(ccx, llfn);
let ctor_ty = ccx.tcx().item_type(def_id); let ctor_ty = common::def_ty(ccx.shared(), def_id, substs);
let ctor_ty = monomorphize::apply_param_substs(ccx.shared(), substs, &ctor_ty);
let sig = ccx.tcx().erase_late_bound_regions_and_normalize(&ctor_ty.fn_sig()); let sig = ccx.tcx().erase_late_bound_regions_and_normalize(&ctor_ty.fn_sig());
let fn_ty = FnType::new(ccx, sig, &[]); let fn_ty = FnType::new(ccx, sig, &[]);

View file

@ -24,14 +24,15 @@ use abi::{Abi, FnType};
use attributes; use attributes;
use base; use base;
use builder::Builder; use builder::Builder;
use common::{self, CrateContext, SharedCrateContext}; use common::{self, CrateContext};
use cleanup::CleanupScope; use cleanup::CleanupScope;
use mir::lvalue::LvalueRef; use mir::lvalue::LvalueRef;
use consts; use consts;
use common::def_ty;
use declare; use declare;
use value::Value; use value::Value;
use meth; use meth;
use monomorphize::{self, Instance}; use monomorphize::Instance;
use trans_item::TransItem; use trans_item::TransItem;
use type_of; use type_of;
use Disr; use Disr;
@ -207,16 +208,6 @@ impl<'tcx> Callee<'tcx> {
} }
} }
/// Given a DefId and some Substs, produces the monomorphic item type.
fn def_ty<'a, 'tcx>(shared: &SharedCrateContext<'a, 'tcx>,
def_id: DefId,
substs: &'tcx Substs<'tcx>)
-> Ty<'tcx> {
let ty = shared.tcx().item_type(def_id);
monomorphize::apply_param_substs(shared, substs, &ty)
}
fn trans_closure_method<'a, 'tcx>(ccx: &'a CrateContext<'a, 'tcx>, fn trans_closure_method<'a, 'tcx>(ccx: &'a CrateContext<'a, 'tcx>,
def_id: DefId, def_id: DefId,
substs: ty::ClosureSubsts<'tcx>, substs: ty::ClosureSubsts<'tcx>,
@ -544,8 +535,7 @@ fn get_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
let substs = tcx.normalize_associated_type(&substs); let substs = tcx.normalize_associated_type(&substs);
let instance = Instance::new(def_id, substs); let instance = Instance::new(def_id, substs);
let item_ty = ccx.tcx().item_type(def_id); let fn_ty = common::def_ty(ccx.shared(), def_id, substs);
let fn_ty = monomorphize::apply_param_substs(ccx.shared(), substs, &item_ty);
if let Some(&llfn) = ccx.instances().borrow().get(&instance) { if let Some(&llfn) = ccx.instances().borrow().get(&instance) {
return (llfn, fn_ty); return (llfn, fn_ty);

View file

@ -207,7 +207,7 @@ use syntax_pos::DUMMY_SP;
use base::custom_coerce_unsize_info; use base::custom_coerce_unsize_info;
use callee::needs_fn_once_adapter_shim; use callee::needs_fn_once_adapter_shim;
use context::SharedCrateContext; use context::SharedCrateContext;
use common::fulfill_obligation; use common::{def_ty, fulfill_obligation};
use glue::{self, DropGlueKind}; use glue::{self, DropGlueKind};
use monomorphize::{self, Instance}; use monomorphize::{self, Instance};
use util::nodemap::{FxHashSet, FxHashMap, DefIdMap}; use util::nodemap::{FxHashSet, FxHashMap, DefIdMap};
@ -341,7 +341,7 @@ fn collect_items_rec<'a, 'tcx: 'a>(scx: &SharedCrateContext<'a, 'tcx>,
// Sanity check whether this ended up being collected accidentally // Sanity check whether this ended up being collected accidentally
debug_assert!(should_trans_locally(scx.tcx(), def_id)); debug_assert!(should_trans_locally(scx.tcx(), def_id));
let ty = scx.tcx().item_type(def_id); let ty = def_ty(scx, def_id, Substs::empty());
let ty = glue::get_drop_glue_type(scx, ty); let ty = glue::get_drop_glue_type(scx, ty);
neighbors.push(TransItem::DropGlue(DropGlueKind::Ty(ty))); neighbors.push(TransItem::DropGlue(DropGlueKind::Ty(ty)));
@ -815,10 +815,7 @@ fn find_drop_glue_neighbors<'a, 'tcx>(scx: &SharedCrateContext<'a, 'tcx>,
} }
ty::TyAdt(def, substs) => { ty::TyAdt(def, substs) => {
for field in def.all_fields() { for field in def.all_fields() {
let field_type = scx.tcx().item_type(field.did); let field_type = def_ty(scx, field.did, substs);
let field_type = monomorphize::apply_param_substs(scx,
substs,
&field_type);
let field_type = glue::get_drop_glue_type(scx, field_type); let field_type = glue::get_drop_glue_type(scx, field_type);
if scx.type_needs_drop(field_type) { if scx.type_needs_drop(field_type) {
@ -1184,7 +1181,7 @@ impl<'b, 'a, 'v> ItemLikeVisitor<'v> for RootCollector<'b, 'a, 'v> {
debug!("RootCollector: ADT drop-glue for {}", debug!("RootCollector: ADT drop-glue for {}",
def_id_to_string(self.scx.tcx(), def_id)); def_id_to_string(self.scx.tcx(), def_id));
let ty = self.scx.tcx().item_type(def_id); let ty = def_ty(self.scx, def_id, Substs::empty());
let ty = glue::get_drop_glue_type(self.scx, ty); let ty = glue::get_drop_glue_type(self.scx, ty);
self.output.push(TransItem::DropGlue(DropGlueKind::Ty(ty))); self.output.push(TransItem::DropGlue(DropGlueKind::Ty(ty)));
} }

View file

@ -29,7 +29,7 @@ use type_::Type;
use value::Value; use value::Value;
use rustc::ty::{self, Ty, TyCtxt}; use rustc::ty::{self, Ty, TyCtxt};
use rustc::ty::layout::Layout; use rustc::ty::layout::Layout;
use rustc::ty::subst::Subst; use rustc::ty::subst::{Subst, Substs};
use rustc::traits::{self, SelectionContext, Reveal}; use rustc::traits::{self, SelectionContext, Reveal};
use rustc::hir; use rustc::hir;
@ -604,3 +604,13 @@ pub fn ty_fn_sig<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
pub fn is_closure(tcx: TyCtxt, def_id: DefId) -> bool { pub fn is_closure(tcx: TyCtxt, def_id: DefId) -> bool {
tcx.def_key(def_id).disambiguated_data.data == DefPathData::ClosureExpr tcx.def_key(def_id).disambiguated_data.data == DefPathData::ClosureExpr
} }
/// Given a DefId and some Substs, produces the monomorphic item type.
pub fn def_ty<'a, 'tcx>(shared: &SharedCrateContext<'a, 'tcx>,
def_id: DefId,
substs: &'tcx Substs<'tcx>)
-> Ty<'tcx>
{
let ty = shared.tcx().item_type(def_id);
monomorphize::apply_param_substs(shared, substs, &ty)
}

View file

@ -18,12 +18,13 @@ use rustc::hir::map as hir_map;
use {debuginfo, machine}; use {debuginfo, machine};
use base; use base;
use trans_item::TransItem; use trans_item::TransItem;
use common::{CrateContext, val_ty}; use common::{self, CrateContext, val_ty};
use declare; use declare;
use monomorphize::{Instance}; use monomorphize::Instance;
use type_::Type; use type_::Type;
use type_of; use type_of;
use rustc::ty; use rustc::ty;
use rustc::ty::subst::Substs;
use rustc::hir; use rustc::hir;
@ -84,7 +85,7 @@ pub fn get_static(ccx: &CrateContext, def_id: DefId) -> ValueRef {
return g; return g;
} }
let ty = ccx.tcx().item_type(def_id); let ty = common::def_ty(ccx.shared(), def_id, Substs::empty());
let g = if let Some(id) = ccx.tcx().hir.as_local_node_id(def_id) { let g = if let Some(id) = ccx.tcx().hir.as_local_node_id(def_id) {
let llty = type_of::type_of(ccx, ty); let llty = type_of::type_of(ccx, ty);
@ -234,7 +235,7 @@ pub fn trans_static<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
v v
}; };
let ty = ccx.tcx().item_type(def_id); let ty = common::def_ty(ccx.shared(), def_id, Substs::empty());
let llty = type_of::type_of(ccx, ty); let llty = type_of::type_of(ccx, ty);
let g = if val_llty == llty { let g = if val_llty == llty {
g g

View file

@ -33,7 +33,7 @@ use rustc::ty::util::TypeIdHasher;
use rustc::hir; use rustc::hir;
use rustc_data_structures::ToHex; use rustc_data_structures::ToHex;
use {type_of, machine, monomorphize}; use {type_of, machine, monomorphize};
use common::CrateContext; use common::{self, CrateContext};
use type_::Type; use type_::Type;
use rustc::ty::{self, AdtKind, Ty, layout}; use rustc::ty::{self, AdtKind, Ty, layout};
use session::config; use session::config;
@ -377,7 +377,7 @@ fn subroutine_type_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
span: Span) span: Span)
-> MetadataCreationResult -> MetadataCreationResult
{ {
let signature = cx.tcx().erase_late_bound_regions(&signature); let signature = cx.tcx().erase_late_bound_regions_and_normalize(&signature);
let mut signature_metadata: Vec<DIType> = Vec::with_capacity(signature.inputs().len() + 1); let mut signature_metadata: Vec<DIType> = Vec::with_capacity(signature.inputs().len() + 1);
@ -1764,7 +1764,7 @@ pub fn create_global_var_metadata(cx: &CrateContext,
}; };
let is_local_to_unit = is_node_local_to_unit(cx, node_id); let is_local_to_unit = is_node_local_to_unit(cx, node_id);
let variable_type = tcx.erase_regions(&tcx.item_type(node_def_id)); let variable_type = common::def_ty(cx.shared(), node_def_id, Substs::empty());
let type_metadata = type_metadata(cx, variable_type, span); let type_metadata = type_metadata(cx, variable_type, span);
let var_name = tcx.item_name(node_def_id).to_string(); let var_name = tcx.item_name(node_def_id).to_string();
let linkage_name = mangled_name_of_item(cx, node_def_id, ""); let linkage_name = mangled_name_of_item(cx, node_def_id, "");
@ -1772,8 +1772,7 @@ pub fn create_global_var_metadata(cx: &CrateContext,
let var_name = CString::new(var_name).unwrap(); let var_name = CString::new(var_name).unwrap();
let linkage_name = CString::new(linkage_name).unwrap(); let linkage_name = CString::new(linkage_name).unwrap();
let ty = cx.tcx().item_type(node_def_id); let global_align = type_of::align_of(cx, variable_type);
let global_align = type_of::align_of(cx, ty);
unsafe { unsafe {
llvm::LLVMRustDIBuilderCreateStaticVariable(DIB(cx), llvm::LLVMRustDIBuilderCreateStaticVariable(DIB(cx),

View file

@ -27,9 +27,9 @@ use rustc::hir::def_id::DefId;
use rustc::ty::subst::Substs; use rustc::ty::subst::Substs;
use abi::Abi; use abi::Abi;
use common::CrateContext; use common::{self, CrateContext};
use builder::Builder; use builder::Builder;
use monomorphize::{self, Instance}; use monomorphize::Instance;
use rustc::ty::{self, Ty}; use rustc::ty::{self, Ty};
use rustc::mir; use rustc::mir;
use session::config::{self, FullDebugInfo, LimitedDebugInfo, NoDebugInfo}; use session::config::{self, FullDebugInfo, LimitedDebugInfo, NoDebugInfo};
@ -397,11 +397,8 @@ pub fn create_function_debug_context<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
let self_type = cx.tcx().impl_of_method(instance.def).and_then(|impl_def_id| { let self_type = cx.tcx().impl_of_method(instance.def).and_then(|impl_def_id| {
// If the method does *not* belong to a trait, proceed // If the method does *not* belong to a trait, proceed
if cx.tcx().trait_id_of_impl(impl_def_id).is_none() { if cx.tcx().trait_id_of_impl(impl_def_id).is_none() {
let impl_self_ty = cx.tcx().item_type(impl_def_id); let impl_self_ty =
let impl_self_ty = cx.tcx().erase_regions(&impl_self_ty); common::def_ty(cx.shared(), impl_def_id, instance.substs);
let impl_self_ty = monomorphize::apply_param_substs(cx.shared(),
instance.substs,
&impl_self_ty);
// Only "class" methods are generally understood by LLVM, // Only "class" methods are generally understood by LLVM,
// so avoid methods on other types (e.g. `<*mut T>::null`). // so avoid methods on other types (e.g. `<*mut T>::null`).

View file

@ -103,9 +103,9 @@
//! inlining, even when they are not marked #[inline]. //! inlining, even when they are not marked #[inline].
use collector::InliningMap; use collector::InliningMap;
use common;
use context::SharedCrateContext; use context::SharedCrateContext;
use llvm; use llvm;
use monomorphize;
use rustc::dep_graph::{DepNode, WorkProductId}; use rustc::dep_graph::{DepNode, WorkProductId};
use rustc::hir::def_id::DefId; use rustc::hir::def_id::DefId;
use rustc::hir::map::DefPathData; use rustc::hir::map::DefPathData;
@ -468,12 +468,7 @@ fn characteristic_def_id_of_trans_item<'a, 'tcx>(scx: &SharedCrateContext<'a, 't
if let Some(impl_def_id) = tcx.impl_of_method(instance.def) { if let Some(impl_def_id) = tcx.impl_of_method(instance.def) {
// This is a method within an inherent impl, find out what the // This is a method within an inherent impl, find out what the
// self-type is: // self-type is:
let impl_self_ty = tcx.item_type(impl_def_id); let impl_self_ty = common::def_ty(scx, impl_def_id, instance.substs);
let impl_self_ty = tcx.erase_regions(&impl_self_ty);
let impl_self_ty = monomorphize::apply_param_substs(scx,
instance.substs,
&impl_self_ty);
if let Some(def_id) = characteristic_def_id_of_type(impl_self_ty) { if let Some(def_id) = characteristic_def_id_of_type(impl_self_ty) {
return Some(def_id); return Some(def_id);
} }

View file

@ -22,7 +22,7 @@ use common;
use declare; use declare;
use glue::DropGlueKind; use glue::DropGlueKind;
use llvm; use llvm;
use monomorphize::{self, Instance}; use monomorphize::Instance;
use rustc::dep_graph::DepNode; use rustc::dep_graph::DepNode;
use rustc::hir; use rustc::hir;
use rustc::hir::def_id::DefId; use rustc::hir::def_id::DefId;
@ -146,7 +146,7 @@ impl<'a, 'tcx> TransItem<'tcx> {
linkage: llvm::Linkage, linkage: llvm::Linkage,
symbol_name: &str) { symbol_name: &str) {
let def_id = ccx.tcx().hir.local_def_id(node_id); let def_id = ccx.tcx().hir.local_def_id(node_id);
let ty = ccx.tcx().item_type(def_id); let ty = common::def_ty(ccx.shared(), def_id, Substs::empty());
let llty = type_of::type_of(ccx, ty); let llty = type_of::type_of(ccx, ty);
let g = declare::define_global(ccx, symbol_name, llty).unwrap_or_else(|| { let g = declare::define_global(ccx, symbol_name, llty).unwrap_or_else(|| {
@ -168,10 +168,7 @@ impl<'a, 'tcx> TransItem<'tcx> {
assert!(!instance.substs.needs_infer() && assert!(!instance.substs.needs_infer() &&
!instance.substs.has_param_types()); !instance.substs.has_param_types());
let item_ty = ccx.tcx().item_type(instance.def); let mono_ty = common::def_ty(ccx.shared(), instance.def, instance.substs);
let item_ty = ccx.tcx().erase_regions(&item_ty);
let mono_ty = monomorphize::apply_param_substs(ccx.shared(), instance.substs, &item_ty);
let attrs = ccx.tcx().get_attrs(instance.def); let attrs = ccx.tcx().get_attrs(instance.def);
let lldecl = declare::declare_fn(ccx, symbol_name, mono_ty); let lldecl = declare::declare_fn(ccx, symbol_name, mono_ty);
unsafe { llvm::LLVMRustSetLinkage(lldecl, linkage) }; unsafe { llvm::LLVMRustSetLinkage(lldecl, linkage) };

View file

@ -79,13 +79,8 @@ pub trait AstConv<'gcx, 'tcx> {
item_name: ast::Name) item_name: ast::Name)
-> Ty<'tcx>; -> Ty<'tcx>;
/// Project an associated type from a non-higher-ranked trait reference. /// Normalize an associated type coming from the user.
/// This is fairly straightforward and can be accommodated in any context. fn normalize_ty(&self, span: Span, ty: Ty<'tcx>) -> Ty<'tcx>;
fn projected_ty(&self,
span: Span,
_trait_ref: ty::TraitRef<'tcx>,
_item_name: ast::Name)
-> Ty<'tcx>;
/// Invoked when we encounter an error from some prior pass /// Invoked when we encounter an error from some prior pass
/// (e.g. resolve) that is translated into a ty-error. This is /// (e.g. resolve) that is translated into a ty-error. This is
@ -310,8 +305,11 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
tcx.types.err tcx.types.err
} else { } else {
// This is a default type parameter. // This is a default type parameter.
ty::queries::ty::get(tcx, span, def.def_id) self.normalize_ty(
.subst_spanned(tcx, substs, Some(span)) span,
ty::queries::ty::get(tcx, span, def.def_id)
.subst_spanned(tcx, substs, Some(span))
)
} }
} else { } else {
// We've already errored above about the mismatch. // We've already errored above about the mismatch.
@ -600,7 +598,10 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
-> Ty<'tcx> -> Ty<'tcx>
{ {
let substs = self.ast_path_substs_for_ty(span, did, item_segment); let substs = self.ast_path_substs_for_ty(span, did, item_segment);
ty::queries::ty::get(self.tcx(), span, did).subst(self.tcx(), substs) self.normalize_ty(
span,
ty::queries::ty::get(self.tcx(), span, did).subst(self.tcx(), substs)
)
} }
/// Transform a PolyTraitRef into a PolyExistentialTraitRef by /// Transform a PolyTraitRef into a PolyExistentialTraitRef by
@ -900,6 +901,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
let trait_did = bound.0.def_id; let trait_did = bound.0.def_id;
let ty = self.projected_ty_from_poly_trait_ref(span, bound, assoc_name); let ty = self.projected_ty_from_poly_trait_ref(span, bound, assoc_name);
let ty = self.normalize_ty(span, ty);
let item = tcx.associated_items(trait_did).find(|i| i.name == assoc_name); let item = tcx.associated_items(trait_did).find(|i| i.name == assoc_name);
let def_id = item.expect("missing associated type").def_id; let def_id = item.expect("missing associated type").def_id;
@ -939,7 +941,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
debug!("qpath_to_ty: trait_ref={:?}", trait_ref); debug!("qpath_to_ty: trait_ref={:?}", trait_ref);
self.projected_ty(span, trait_ref, item_segment.name) self.normalize_ty(span, tcx.mk_projection(trait_ref, item_segment.name))
} }
pub fn prohibit_type_params(&self, segments: &[hir::PathSegment]) { pub fn prohibit_type_params(&self, segments: &[hir::PathSegment]) {

View file

@ -739,8 +739,9 @@ fn typeck_tables<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
check_fn(&inh, fn_sig, decl, id, body) check_fn(&inh, fn_sig, decl, id, body)
} else { } else {
let expected_type = tcx.item_type(def_id);
let fcx = FnCtxt::new(&inh, None, body.value.id); let fcx = FnCtxt::new(&inh, None, body.value.id);
let expected_type = tcx.item_type(def_id);
let expected_type = fcx.normalize_associated_types_in(body.value.span, &expected_type);
fcx.require_type_is_sized(expected_type, body.value.span, traits::ConstSized); fcx.require_type_is_sized(expected_type, body.value.span, traits::ConstSized);
// Gather locals in statics (because of block expressions). // Gather locals in statics (because of block expressions).
@ -1442,16 +1443,15 @@ impl<'a, 'gcx, 'tcx> AstConv<'gcx, 'tcx> for FnCtxt<'a, 'gcx, 'tcx> {
infer::LateBoundRegionConversionTime::AssocTypeProjection(item_name), infer::LateBoundRegionConversionTime::AssocTypeProjection(item_name),
&poly_trait_ref); &poly_trait_ref);
self.normalize_associated_type(span, trait_ref, item_name) self.tcx().mk_projection(trait_ref, item_name)
} }
fn projected_ty(&self, fn normalize_ty(&self, span: Span, ty: Ty<'tcx>) -> Ty<'tcx> {
span: Span, if ty.has_escaping_regions() {
trait_ref: ty::TraitRef<'tcx>, ty // FIXME: normalization and escaping regions
item_name: ast::Name) } else {
-> Ty<'tcx> self.normalize_associated_types_in(span, &ty)
{ }
self.normalize_associated_type(span, trait_ref, item_name)
} }
fn set_tainted_by_errors(&self) { fn set_tainted_by_errors(&self) {
@ -1728,25 +1728,6 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
self.inh.normalize_associated_types_in(span, self.body_id, value) self.inh.normalize_associated_types_in(span, self.body_id, value)
} }
fn normalize_associated_type(&self,
span: Span,
trait_ref: ty::TraitRef<'tcx>,
item_name: ast::Name)
-> Ty<'tcx>
{
let cause = traits::ObligationCause::new(span,
self.body_id,
traits::ObligationCauseCode::MiscObligation);
self.fulfillment_cx
.borrow_mut()
.normalize_projection_type(self,
ty::ProjectionTy {
trait_ref: trait_ref,
item_name: item_name,
},
cause)
}
pub fn write_nil(&self, node_id: ast::NodeId) { pub fn write_nil(&self, node_id: ast::NodeId) {
self.write_ty(node_id, self.tcx.mk_nil()); self.write_ty(node_id, self.tcx.mk_nil());
} }
@ -1777,9 +1758,9 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
} }
pub fn register_bound(&self, pub fn register_bound(&self,
ty: Ty<'tcx>, ty: Ty<'tcx>,
def_id: DefId, def_id: DefId,
cause: traits::ObligationCause<'tcx>) cause: traits::ObligationCause<'tcx>)
{ {
self.fulfillment_cx.borrow_mut() self.fulfillment_cx.borrow_mut()
.register_bound(self, ty, def_id, cause); .register_bound(self, ty, def_id, cause);
@ -1788,8 +1769,11 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
pub fn register_predicate(&self, pub fn register_predicate(&self,
obligation: traits::PredicateObligation<'tcx>) obligation: traits::PredicateObligation<'tcx>)
{ {
debug!("register_predicate({:?})", debug!("register_predicate({:?})", obligation);
obligation); if obligation.has_escaping_regions() {
span_bug!(obligation.cause.span, "escaping regions in predicate {:?}",
obligation);
}
self.fulfillment_cx self.fulfillment_cx
.borrow_mut() .borrow_mut()
.register_predicate_obligation(self, obligation); .register_predicate_obligation(self, obligation);

View file

@ -291,7 +291,7 @@ impl<'a, 'tcx> AstConv<'tcx, 'tcx> for ItemCtxt<'a, 'tcx> {
-> Ty<'tcx> -> Ty<'tcx>
{ {
if let Some(trait_ref) = self.tcx().no_late_bound_regions(&poly_trait_ref) { if let Some(trait_ref) = self.tcx().no_late_bound_regions(&poly_trait_ref) {
self.projected_ty(span, trait_ref, item_name) self.tcx().mk_projection(trait_ref, item_name)
} else { } else {
// no late-bound regions, we can just ignore the binder // no late-bound regions, we can just ignore the binder
span_err!(self.tcx().sess, span, E0212, span_err!(self.tcx().sess, span, E0212,
@ -301,13 +301,10 @@ impl<'a, 'tcx> AstConv<'tcx, 'tcx> for ItemCtxt<'a, 'tcx> {
} }
} }
fn projected_ty(&self, fn normalize_ty(&self, _span: Span, ty: Ty<'tcx>) -> Ty<'tcx> {
_span: Span, // types in item signatures are not normalized, to avoid undue
trait_ref: ty::TraitRef<'tcx>, // dependencies.
item_name: ast::Name) ty
-> Ty<'tcx>
{
self.tcx().mk_projection(trait_ref, item_name)
} }
fn set_tainted_by_errors(&self) { fn set_tainted_by_errors(&self) {

View file

@ -0,0 +1,20 @@
// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
trait Stream { type Item; }
impl<'a> Stream for &'a str { type Item = u8; }
fn f<'s>(s: &'s str) -> (&'s str, <&'s str as Stream>::Item) {
(s, 42)
}
fn main() {
let fx = f as for<'t> fn(&'t str) -> (&'t str, <&'t str as Stream>::Item);
assert_eq!(fx("hi"), ("hi", 42));
}

View file

@ -0,0 +1,27 @@
// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
pub trait Foo {
type Out;
}
impl Foo for () {
type Out = bool;
}
fn main() {
type Bool = <() as Foo>::Out;
let x: Bool = true;
assert!(x);
let y: Option<Bool> = None;
assert_eq!(y, None);
}