Remove BuiltinBound and BuiltinBounds.

This commit is contained in:
Mark-Simulacrum 2016-11-13 19:42:15 -07:00
parent 607af7218b
commit 64e97d9b33
31 changed files with 137 additions and 332 deletions

View file

@ -24,6 +24,7 @@ use middle::free_region::FreeRegionMap;
use middle::mem_categorization as mc;
use middle::mem_categorization::McResult;
use middle::region::CodeExtent;
use middle::lang_items;
use mir::tcx::LvalueTy;
use ty::subst::{Kind, Subst, Substs};
use ty::adjustment;
@ -1492,11 +1493,14 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
}
}
let copy_def_id = self.tcx.lang_items.require(lang_items::CopyTraitLangItem)
.unwrap_or_else(|msg| self.tcx.sess.fatal(&msg[..]));
// this can get called from typeck (by euv), and moves_by_default
// rightly refuses to work with inference variables, but
// moves_by_default has a cache, which we want to use in other
// cases.
!traits::type_known_to_meet_builtin_bound(self, ty, ty::BoundCopy, span)
!traits::type_known_to_meet_bound(self, ty, copy_def_id, span)
}
pub fn node_method_ty(&self, method_call: ty::MethodCall)

View file

@ -32,7 +32,6 @@
#![feature(const_fn)]
#![feature(core_intrinsics)]
#![cfg_attr(stage0, feature(dotdot_in_tuple_patterns))]
#![feature(enumset)]
#![cfg_attr(stage0, feature(item_like_imports))]
#![feature(libc)]
#![feature(nonzero)]

View file

@ -90,31 +90,6 @@ impl LanguageItems {
self.require(OwnedBoxLangItem)
}
pub fn from_builtin_kind(&self, bound: ty::BuiltinBound)
-> Result<DefId, String>
{
match bound {
ty::BoundSend => self.require(SendTraitLangItem),
ty::BoundSized => self.require(SizedTraitLangItem),
ty::BoundCopy => self.require(CopyTraitLangItem),
ty::BoundSync => self.require(SyncTraitLangItem),
}
}
pub fn to_builtin_kind(&self, id: DefId) -> Option<ty::BuiltinBound> {
if Some(id) == self.send_trait() {
Some(ty::BoundSend)
} else if Some(id) == self.sized_trait() {
Some(ty::BoundSized)
} else if Some(id) == self.copy_trait() {
Some(ty::BoundCopy)
} else if Some(id) == self.sync_trait() {
Some(ty::BoundSync)
} else {
None
}
}
pub fn fn_trait_kind(&self, id: DefId) -> Option<ty::ClosureKind> {
let def_id_kinds = [
(self.fn_trait(), ty::ClosureKind::Fn),

View file

@ -905,16 +905,6 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
ObligationCauseCode::StructInitializerSized => {
err.note("structs must have a statically known size to be initialized");
}
ObligationCauseCode::ClosureCapture(var_id, _, builtin_bound) => {
let def_id = tcx.lang_items.from_builtin_kind(builtin_bound).unwrap();
let trait_name = tcx.item_path_str(def_id);
let name = tcx.local_var_name_str(var_id);
err.note(
&format!("the closure that captures `{}` requires that all captured variables \
implement the trait `{}`",
name,
trait_name));
}
ObligationCauseCode::FieldSized => {
err.note("only the last field of a struct may have a dynamically sized type");
}

View file

@ -17,8 +17,8 @@ use rustc_data_structures::obligation_forest::{ForestObligation, ObligationProce
use std::marker::PhantomData;
use std::mem;
use syntax::ast;
use util::common::ErrorReported;
use util::nodemap::{FxHashSet, NodeMap};
use hir::def_id::DefId;
use super::CodeAmbiguity;
use super::CodeProjectionError;
@ -230,18 +230,21 @@ impl<'a, 'gcx, 'tcx> FulfillmentContext<'tcx> {
normalized.value
}
pub fn register_builtin_bound(&mut self,
pub fn register_bound(&mut self,
infcx: &InferCtxt<'a, 'gcx, 'tcx>,
ty: Ty<'tcx>,
builtin_bound: ty::BuiltinBound,
def_id: DefId,
cause: ObligationCause<'tcx>)
{
match infcx.tcx.predicate_for_builtin_bound(cause, builtin_bound, 0, ty) {
Ok(predicate) => {
self.register_predicate_obligation(infcx, predicate);
}
Err(ErrorReported) => { }
}
let trait_ref = ty::TraitRef {
def_id: def_id,
substs: infcx.tcx.mk_substs_trait(ty, &[]),
};
self.register_predicate_obligation(infcx, Obligation {
cause: cause,
recursion_depth: 0,
predicate: trait_ref.to_predicate()
});
}
pub fn register_region_obligation(&mut self,

View file

@ -19,7 +19,7 @@ use hir;
use hir::def_id::DefId;
use middle::free_region::FreeRegionMap;
use ty::subst::Substs;
use ty::{self, Ty, TyCtxt, TypeFoldable};
use ty::{self, Ty, TyCtxt, TypeFoldable, ToPredicate};
use infer::InferCtxt;
use std::rc::Rc;
@ -125,10 +125,6 @@ pub enum ObligationCauseCode<'tcx> {
ReturnType, // Return type must be Sized
RepeatVec, // [T,..n] --> T must be Copy
// Captures of variable the given id by a closure (span is the
// span of the closure)
ClosureCapture(ast::NodeId, Span, ty::BuiltinBound),
// Types of fields (other than the last) in a struct must be sized.
FieldSized,
@ -369,27 +365,30 @@ pub fn predicates_for_generics<'tcx>(cause: ObligationCause<'tcx>,
/// `bound` or is not known to meet bound (note that this is
/// conservative towards *no impl*, which is the opposite of the
/// `evaluate` methods).
pub fn type_known_to_meet_builtin_bound<'a, 'gcx, 'tcx>(infcx: &InferCtxt<'a, 'gcx, 'tcx>,
pub fn type_known_to_meet_bound<'a, 'gcx, 'tcx>(infcx: &InferCtxt<'a, 'gcx, 'tcx>,
ty: Ty<'tcx>,
bound: ty::BuiltinBound,
def_id: DefId,
span: Span)
-> bool
{
debug!("type_known_to_meet_builtin_bound(ty={:?}, bound={:?})",
debug!("type_known_to_meet_bound(ty={:?}, bound={:?})",
ty,
bound);
infcx.tcx.item_path_str(def_id));
let cause = ObligationCause::misc(span, ast::DUMMY_NODE_ID);
let obligation =
infcx.tcx.predicate_for_builtin_bound(cause, bound, 0, ty);
let obligation = match obligation {
Ok(o) => o,
Err(..) => return false
let trait_ref = ty::TraitRef {
def_id: def_id,
substs: infcx.tcx.mk_substs_trait(ty, &[]),
};
let obligation = Obligation {
cause: ObligationCause::misc(span, ast::DUMMY_NODE_ID),
recursion_depth: 0,
predicate: trait_ref.to_predicate(),
};
let result = SelectionContext::new(infcx)
.evaluate_obligation_conservatively(&obligation);
debug!("type_known_to_meet_builtin_bound: ty={:?} bound={:?} => {:?}",
ty, bound, result);
debug!("type_known_to_meet_ty={:?} bound={} => {:?}",
ty, infcx.tcx.item_path_str(def_id), result);
if result && (ty.has_infer_types() || ty.has_closure_types()) {
// Because of inference "guessing", selection can sometimes claim
@ -404,22 +403,22 @@ pub fn type_known_to_meet_builtin_bound<'a, 'gcx, 'tcx>(infcx: &InferCtxt<'a, 'g
// anyhow).
let cause = ObligationCause::misc(span, ast::DUMMY_NODE_ID);
fulfill_cx.register_builtin_bound(infcx, ty, bound, cause);
fulfill_cx.register_bound(infcx, ty, def_id, cause);
// Note: we only assume something is `Copy` if we can
// *definitively* show that it implements `Copy`. Otherwise,
// assume it is move; linear is always ok.
match fulfill_cx.select_all_or_error(infcx) {
Ok(()) => {
debug!("type_known_to_meet_builtin_bound: ty={:?} bound={:?} success",
debug!("type_known_to_meet_bound: ty={:?} bound={} success",
ty,
bound);
infcx.tcx.item_path_str(def_id));
true
}
Err(e) => {
debug!("type_known_to_meet_builtin_bound: ty={:?} bound={:?} errors={:?}",
debug!("type_known_to_meet_bound: ty={:?} bound={} errors={:?}",
ty,
bound,
infcx.tcx.item_path_str(def_id),
e);
false
}

View file

@ -1093,8 +1093,9 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
// Other bounds. Consider both in-scope bounds from fn decl
// and applicable impls. There is a certain set of precedence rules here.
match self.tcx().lang_items.to_builtin_kind(obligation.predicate.def_id()) {
Some(ty::BoundCopy) => {
let def_id = obligation.predicate.def_id();
match obligation.predicate.def_id() {
_ if self.tcx().lang_items.copy_trait() == Some(def_id) => {
debug!("obligation self ty is {:?}",
obligation.predicate.0.self_ty());
@ -1106,7 +1107,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
let copy_conditions = self.copy_conditions(obligation);
self.assemble_builtin_bound_candidates(copy_conditions, &mut candidates)?;
}
Some(ty::BoundSized) => {
_ if self.tcx().lang_items.sized_trait() == Some(def_id) => {
// Sized is never implementable by end-users, it is
// always automatically computed.
let sized_conditions = self.sized_conditions(obligation);
@ -1114,14 +1115,12 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
&mut candidates)?;
}
None if self.tcx().lang_items.unsize_trait() ==
Some(obligation.predicate.def_id()) => {
_ if self.tcx().lang_items.unsize_trait() == Some(def_id) => {
self.assemble_candidates_for_unsizing(obligation, &mut candidates);
}
Some(ty::BoundSend) |
Some(ty::BoundSync) |
None => {
// For non-builtins and Send/Sync
_ => {
self.assemble_closure_candidates(obligation, &mut candidates)?;
self.assemble_fn_pointer_candidates(obligation, &mut candidates)?;
self.assemble_candidates_from_impls(obligation, &mut candidates)?;
@ -2483,7 +2482,6 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
data_b.auto_traits().collect(),
data_a.projection_bounds.clone(),
));
let origin = TypeOrigin::Misc(obligation.cause.span);
let InferOk { obligations, .. } =
self.infcx.sub_types(false, &obligation.cause, new_trait, target)
.map_err(|_| Unimplemented)?;

View file

@ -190,9 +190,6 @@ impl<'a, 'tcx> Lift<'tcx> for traits::ObligationCauseCode<'a> {
super::VariableType(id) => Some(super::VariableType(id)),
super::ReturnType => Some(super::ReturnType),
super::RepeatVec => Some(super::RepeatVec),
super::ClosureCapture(node_id, span, bound) => {
Some(super::ClosureCapture(node_id, span, bound))
}
super::FieldSized => Some(super::FieldSized),
super::ConstSized => Some(super::ConstSized),
super::SharedStatic => Some(super::SharedStatic),
@ -507,7 +504,6 @@ impl<'tcx> TypeFoldable<'tcx> for traits::ObligationCauseCode<'tcx> {
super::VariableType(_) |
super::ReturnType |
super::RepeatVec |
super::ClosureCapture(..) |
super::FieldSized |
super::ConstSized |
super::SharedStatic |
@ -552,7 +548,6 @@ impl<'tcx> TypeFoldable<'tcx> for traits::ObligationCauseCode<'tcx> {
super::VariableType(_) |
super::ReturnType |
super::RepeatVec |
super::ClosureCapture(..) |
super::FieldSized |
super::ConstSized |
super::SharedStatic |

View file

@ -12,7 +12,6 @@ use hir::def_id::DefId;
use ty::subst::{Subst, Substs};
use ty::{self, Ty, TyCtxt, ToPredicate, ToPolyTraitRef};
use ty::outlives::Component;
use util::common::ErrorReported;
use util::nodemap::FxHashSet;
use super::{Obligation, ObligationCause, PredicateObligation, SelectionContext, Normalized};
@ -408,25 +407,6 @@ pub fn predicate_for_trait_ref<'tcx>(
}
impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
pub fn trait_ref_for_builtin_bound(self,
builtin_bound: ty::BuiltinBound,
param_ty: Ty<'tcx>)
-> Result<ty::TraitRef<'tcx>, ErrorReported>
{
match self.lang_items.from_builtin_kind(builtin_bound) {
Ok(def_id) => {
Ok(ty::TraitRef {
def_id: def_id,
substs: self.mk_substs_trait(param_ty, &[])
})
}
Err(e) => {
self.sess.err(&e);
Err(ErrorReported)
}
}
}
pub fn predicate_for_trait_def(self,
cause: ObligationCause<'tcx>,
trait_def_id: DefId,
@ -442,17 +422,6 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
predicate_for_trait_ref(cause, trait_ref, recursion_depth)
}
pub fn predicate_for_builtin_bound(self,
cause: ObligationCause<'tcx>,
builtin_bound: ty::BuiltinBound,
recursion_depth: usize,
param_ty: Ty<'tcx>)
-> Result<PredicateObligation<'tcx>, ErrorReported>
{
let trait_ref = self.trait_ref_for_builtin_bound(builtin_bound, param_ty)?;
Ok(predicate_for_trait_ref(cause, trait_ref, recursion_depth))
}
/// Cast a trait reference into a reference to one of its super
/// traits; returns `None` if `target_trait_def_id` is not a
/// supertrait.

View file

@ -45,7 +45,6 @@ pub enum TypeError<'tcx> {
IntMismatch(ExpectedFound<ty::IntVarValue>),
FloatMismatch(ExpectedFound<ast::FloatTy>),
Traits(ExpectedFound<DefId>),
BuiltinBoundsMismatch(ExpectedFound<ty::BuiltinBounds>),
VariadicMismatch(ExpectedFound<bool>),
CyclicTy,
ProjectionNameMismatched(ExpectedFound<Name>),
@ -135,19 +134,6 @@ impl<'tcx> fmt::Display for TypeError<'tcx> {
format!("trait `{}`",
tcx.item_path_str(values.found)))
}),
BuiltinBoundsMismatch(values) => {
if values.expected.is_empty() {
write!(f, "expected no bounds, found `{}`",
values.found)
} else if values.found.is_empty() {
write!(f, "expected bounds `{}`, found no bounds",
values.expected)
} else {
write!(f, "expected bounds `{}`, found bounds `{}`",
values.expected,
values.found)
}
}
IntMismatch(ref values) => {
write!(f, "expected `{:?}`, found `{:?}`",
values.expected,

View file

@ -53,7 +53,6 @@ use hir;
use hir::itemlikevisit::ItemLikeVisitor;
pub use self::sty::{Binder, DebruijnIndex};
pub use self::sty::{BuiltinBound, BuiltinBounds};
pub use self::sty::{BareFnTy, FnSig, PolyFnSig};
pub use self::sty::{ClosureTy, InferTy, ParamTy, ProjectionTy, TraitObject};
pub use self::sty::{ClosureSubsts, TypeAndMut};
@ -68,11 +67,6 @@ pub use self::sty::InferTy::*;
pub use self::sty::Region::*;
pub use self::sty::TypeVariants::*;
pub use self::sty::BuiltinBound::Send as BoundSend;
pub use self::sty::BuiltinBound::Sized as BoundSized;
pub use self::sty::BuiltinBound::Copy as BoundCopy;
pub use self::sty::BuiltinBound::Sync as BoundSync;
pub use self::contents::TypeContents;
pub use self::context::{TyCtxt, tls};
pub use self::context::{CtxtArenas, Lift, Tables};

View file

@ -302,23 +302,6 @@ impl<'tcx> Relate<'tcx> for Vec<ty::PolyExistentialProjection<'tcx>> {
}
}
impl<'tcx> Relate<'tcx> for ty::BuiltinBounds {
fn relate<'a, 'gcx, R>(relation: &mut R,
a: &ty::BuiltinBounds,
b: &ty::BuiltinBounds)
-> RelateResult<'tcx, ty::BuiltinBounds>
where R: TypeRelation<'a, 'gcx, 'tcx>, 'gcx: 'a+'tcx, 'tcx: 'a
{
// Two sets of builtin bounds are only relatable if they are
// precisely the same (but see the coercion code).
if a != b {
Err(TypeError::BuiltinBoundsMismatch(expected_found(relation, a, b)))
} else {
Ok(*a)
}
}
}
impl<'tcx> Relate<'tcx> for ty::TraitRef<'tcx> {
fn relate<'a, 'gcx, R>(relation: &mut R,
a: &ty::TraitRef<'tcx>,

View file

@ -315,7 +315,6 @@ impl<'a, 'tcx> Lift<'tcx> for ty::error::TypeError<'a> {
IntMismatch(x) => IntMismatch(x),
FloatMismatch(x) => FloatMismatch(x),
Traits(x) => Traits(x),
BuiltinBoundsMismatch(x) => BuiltinBoundsMismatch(x),
VariadicMismatch(x) => VariadicMismatch(x),
CyclicTy => CyclicTy,
ProjectionNameMismatched(x) => ProjectionNameMismatched(x),
@ -703,16 +702,6 @@ impl<'tcx> TypeFoldable<'tcx> for ty::adjustment::AutoBorrow<'tcx> {
}
}
impl<'tcx> TypeFoldable<'tcx> for ty::BuiltinBounds {
fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, _folder: &mut F) -> Self {
*self
}
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, _visitor: &mut V) -> bool {
false
}
}
impl<'tcx> TypeFoldable<'tcx> for ty::TypeParameterDef<'tcx> {
fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self {
ty::TypeParameterDef {

View file

@ -14,13 +14,10 @@ use hir::def_id::DefId;
use middle::region;
use ty::subst::Substs;
use ty::{self, AdtDef, ToPredicate, TypeFlags, Ty, TyCtxt, TypeFoldable};
use ty::{self, AdtDef, TypeFlags, Ty, TyCtxt, TypeFoldable};
use ty::{Slice, TyS};
use util::common::ErrorReported;
use collections::enum_set::{self, EnumSet, CLike};
use std::fmt;
use std::ops;
use syntax::abi;
use syntax::ast::{self, Name, NodeId};
use syntax::symbol::{keywords, InternedString};
@ -770,71 +767,6 @@ impl<'a, 'tcx, 'gcx> PolyExistentialProjection<'tcx> {
}
}
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, RustcEncodable, RustcDecodable)]
pub struct BuiltinBounds(EnumSet<BuiltinBound>);
impl<'a, 'gcx, 'tcx> BuiltinBounds {
pub fn empty() -> BuiltinBounds {
BuiltinBounds(EnumSet::new())
}
pub fn iter(&self) -> enum_set::Iter<BuiltinBound> {
self.into_iter()
}
pub fn to_predicates(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>,
self_ty: Ty<'tcx>)
-> Vec<ty::Predicate<'tcx>> {
self.iter().filter_map(|builtin_bound|
match tcx.trait_ref_for_builtin_bound(builtin_bound, self_ty) {
Ok(trait_ref) => Some(trait_ref.to_predicate()),
Err(ErrorReported) => { None }
}
).collect()
}
}
impl ops::Deref for BuiltinBounds {
type Target = EnumSet<BuiltinBound>;
fn deref(&self) -> &Self::Target { &self.0 }
}
impl ops::DerefMut for BuiltinBounds {
fn deref_mut(&mut self) -> &mut Self::Target { &mut self.0 }
}
impl<'a> IntoIterator for &'a BuiltinBounds {
type Item = BuiltinBound;
type IntoIter = enum_set::Iter<BuiltinBound>;
fn into_iter(self) -> Self::IntoIter {
(**self).into_iter()
}
}
#[derive(Clone, RustcEncodable, PartialEq, Eq, RustcDecodable, Hash,
Debug, Copy)]
pub enum BuiltinBound {
Send = 0,
Sized = 1,
Copy = 2,
Sync = 3,
}
impl CLike for BuiltinBound {
fn to_usize(&self) -> usize {
*self as usize
}
fn from_usize(v: usize) -> BuiltinBound {
match v {
0 => BuiltinBound::Send,
1 => BuiltinBound::Sized,
2 => BuiltinBound::Copy,
3 => BuiltinBound::Sync,
_ => bug!("{} is not a valid BuiltinBound", v)
}
}
}
impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
pub fn try_add_builtin_trait(self,
id: DefId,

View file

@ -21,6 +21,7 @@ use ty::fold::TypeVisitor;
use ty::layout::{Layout, LayoutError};
use ty::TypeVariants::*;
use util::nodemap::FxHashMap;
use middle::lang_items;
use rustc_const_math::{ConstInt, ConstIsize, ConstUsize};
@ -599,7 +600,7 @@ impl<'a, 'gcx, 'tcx, H: Hasher> TypeVisitor<'tcx> for TypeIdHasher<'a, 'gcx, 'tc
impl<'a, 'tcx> ty::TyS<'tcx> {
fn impls_bound(&'tcx self, tcx: TyCtxt<'a, 'tcx, 'tcx>,
param_env: &ParameterEnvironment<'tcx>,
bound: ty::BuiltinBound,
def_id: DefId,
cache: &RefCell<FxHashMap<Ty<'tcx>, bool>>,
span: Span) -> bool
{
@ -611,7 +612,7 @@ impl<'a, 'tcx> ty::TyS<'tcx> {
let result =
tcx.infer_ctxt(None, Some(param_env.clone()), Reveal::ExactMatch)
.enter(|infcx| {
traits::type_known_to_meet_builtin_bound(&infcx, self, bound, span)
traits::type_known_to_meet_bound(&infcx, self, def_id, span)
});
if self.has_param_types() || self.has_self_ty() {
cache.borrow_mut().insert(self, result);
@ -644,8 +645,10 @@ impl<'a, 'tcx> ty::TyS<'tcx> {
TyClosure(..) | TyAdt(..) | TyAnon(..) |
TyProjection(..) | TyParam(..) | TyInfer(..) | TyError => None
}.unwrap_or_else(|| {
!self.impls_bound(tcx, param_env, ty::BoundCopy, &param_env.is_copy_cache, span)
});
!self.impls_bound(tcx, param_env,
tcx.lang_items.require(lang_items::CopyTraitLangItem)
.unwrap_or_else(|msg| tcx.sess.fatal(&msg[..])),
&param_env.is_copy_cache, span) });
if !self.has_param_types() && !self.has_self_ty() {
self.flags.set(self.flags.get() | if result {
@ -686,8 +689,9 @@ impl<'a, 'tcx> ty::TyS<'tcx> {
TyAdt(..) | TyProjection(..) | TyParam(..) |
TyInfer(..) | TyAnon(..) | TyError => None
}.unwrap_or_else(|| {
self.impls_bound(tcx, param_env, ty::BoundSized, &param_env.is_sized_cache, span)
});
self.impls_bound(tcx, param_env, tcx.lang_items.require(lang_items::SizedTraitLangItem)
.unwrap_or_else(|msg| tcx.sess.fatal(&msg[..])),
&param_env.is_copy_cache, span) });
if !self.has_param_types() && !self.has_self_ty() {
self.flags.set(self.flags.get() | if result {

View file

@ -17,7 +17,7 @@ use ty::{self, ToPredicate, Ty, TyCtxt, TypeFoldable};
use std::iter::once;
use syntax::ast;
use syntax_pos::Span;
use util::common::ErrorReported;
use middle::lang_items;
/// Returns the set of obligations needed to make `ty` well-formed.
/// If `ty` contains unresolved inference variables, this may include
@ -282,14 +282,12 @@ impl<'a, 'gcx, 'tcx> WfPredicates<'a, 'gcx, 'tcx> {
fn require_sized(&mut self, subty: Ty<'tcx>, cause: traits::ObligationCauseCode<'tcx>) {
if !subty.has_escaping_regions() {
let cause = self.cause(cause);
match self.infcx.tcx.trait_ref_for_builtin_bound(ty::BoundSized, subty) {
Ok(trait_ref) => {
self.out.push(
traits::Obligation::new(cause,
trait_ref.to_predicate()));
}
Err(ErrorReported) => { }
}
let trait_ref = ty::TraitRef {
def_id: self.infcx.tcx.lang_items.require(lang_items::SizedTraitLangItem)
.unwrap_or_else(|msg| self.infcx.tcx.sess.fatal(&msg[..])),
substs: self.infcx.tcx.mk_substs_trait(subty, &[]),
};
self.out.push(traits::Obligation::new(cause, trait_ref.to_predicate()));
}
}

View file

@ -683,19 +683,6 @@ impl<'tcx> fmt::Display for ty::FnSig<'tcx> {
}
}
impl fmt::Display for ty::BuiltinBounds {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let mut bounds = self.iter();
if let Some(bound) = bounds.next() {
write!(f, "{:?}", bound)?;
for bound in bounds {
write!(f, " + {:?}", bound)?;
}
}
Ok(())
}
}
impl fmt::Debug for ty::TyVid {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "_#{}t", self.index)

View file

@ -29,6 +29,7 @@ use rustc::mir::traversal::ReversePostorder;
use rustc::mir::transform::{Pass, MirPass, MirSource};
use rustc::mir::visit::{LvalueContext, Visitor};
use rustc::util::nodemap::DefIdMap;
use rustc::middle::lang_items;
use syntax::abi::Abi;
use syntax::feature_gate::UnstableFeatures;
use syntax_pos::Span;
@ -1046,7 +1047,11 @@ impl<'tcx> MirPass<'tcx> for QualifyAndPromoteConstants {
tcx.infer_ctxt(None, None, Reveal::NotSpecializable).enter(|infcx| {
let cause = traits::ObligationCause::new(mir.span, id, traits::SharedStatic);
let mut fulfillment_cx = traits::FulfillmentContext::new();
fulfillment_cx.register_builtin_bound(&infcx, ty, ty::BoundSync, cause);
fulfillment_cx.register_bound(&infcx, ty,
tcx.lang_items
.require(lang_items::SyncTraitLangItem)
.unwrap_or_else(|msg| tcx.sess.fatal(&msg[..])),
cause);
if let Err(err) = fulfillment_cx.select_all_or_error(&infcx) {
infcx.report_fulfillment_errors(&err);
}

View file

@ -46,6 +46,7 @@ use rustc::hir;
use rustc::traits;
use rustc::ty::{self, Ty, TypeFoldable};
use rustc::ty::cast::{CastKind, CastTy};
use rustc::middle::lang_items;
use syntax::ast;
use syntax_pos::Span;
use util::common::ErrorReported;
@ -543,6 +544,8 @@ impl<'a, 'gcx, 'tcx> CastCheck<'tcx> {
impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
fn type_is_known_to_be_sized(&self, ty: Ty<'tcx>, span: Span) -> bool {
traits::type_known_to_meet_builtin_bound(self, ty, ty::BoundSized, span)
let lang_item = self.tcx.lang_items.require(lang_items::SizedTraitLangItem)
.unwrap_or_else(|msg| self.tcx.sess.fatal(&msg[..]));
traits::type_known_to_meet_bound(self, ty, lang_item, span)
}
}

View file

@ -119,7 +119,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
self.deduce_sig_from_projection(&pb)
})
.next();
let kind = self.tcx.lang_items.fn_trait_kind(object_type.principal().unwrap().def_id());
let kind =
self.tcx.lang_items.fn_trait_kind(object_type.principal().unwrap().def_id());
(sig, kind)
}
ty::TyInfer(ty::TyVar(vid)) => self.deduce_expectations_from_obligations(vid),

View file

@ -379,7 +379,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
match ty.sty {
ty::TyAdt(def, _) => def.did.is_local(),
ty::TyTrait(ref tr) => tr.principal().map(|p| p.def_id().is_local()).unwrap_or(false),
ty::TyTrait(ref tr) => tr.principal().map(|p|
p.def_id().is_local()).unwrap_or(false),
ty::TyParam(_) => true,

View file

@ -123,6 +123,7 @@ use rustc::hir::intravisit::{self, Visitor};
use rustc::hir::itemlikevisit::ItemLikeVisitor;
use rustc::hir::{self, PatKind};
use rustc::hir::print as pprust;
use rustc::middle::lang_items;
use rustc_back::slice;
use rustc_const_eval::eval_length;
@ -1805,11 +1806,11 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
ty: Ty<'tcx>,
span: Span,
code: traits::ObligationCauseCode<'tcx>,
bound: ty::BuiltinBound)
def_id: DefId)
{
self.register_builtin_bound(
self.register_bound(
ty,
bound,
def_id,
traits::ObligationCause::new(span, self.body_id, code));
}
@ -1818,16 +1819,18 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
span: Span,
code: traits::ObligationCauseCode<'tcx>)
{
self.require_type_meets(ty, span, code, ty::BoundSized);
let lang_item = self.tcx.lang_items.require(lang_items::SizedTraitLangItem)
.unwrap_or_else(|msg| self.tcx.sess.fatal(&msg[..]));
self.require_type_meets(ty, span, code, lang_item);
}
pub fn register_builtin_bound(&self,
pub fn register_bound(&self,
ty: Ty<'tcx>,
builtin_bound: ty::BuiltinBound,
def_id: DefId,
cause: traits::ObligationCause<'tcx>)
{
self.fulfillment_cx.borrow_mut()
.register_builtin_bound(self, ty, builtin_bound, cause);
.register_bound(self, ty, def_id, cause);
}
pub fn register_predicate(&self,
@ -3899,7 +3902,9 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
if count > 1 {
// For [foo, ..n] where n > 1, `foo` must have
// Copy type:
self.require_type_meets(t, expr.span, traits::RepeatVec, ty::BoundCopy);
let lang_item = self.tcx.lang_items.require(lang_items::CopyTraitLangItem)
.unwrap_or_else(|msg| self.tcx.sess.fatal(&msg[..]));
self.require_type_meets(t, expr.span, traits::RepeatVec, lang_item);
}
if element_ty.references_error() {

View file

@ -18,6 +18,7 @@ use middle::region::{CodeExtent};
use rustc::traits::{self, ObligationCauseCode};
use rustc::ty::{self, Ty, TyCtxt};
use rustc::util::nodemap::{FxHashSet, FxHashMap};
use rustc::middle::lang_items;
use syntax::ast;
use syntax_pos::Span;
@ -118,12 +119,13 @@ impl<'ccx, 'gcx> CheckTypeWellFormedVisitor<'ccx, 'gcx> {
let trait_ref = ccx.tcx.impl_trait_ref(ccx.tcx.map.local_def_id(item.id)).unwrap();
ccx.tcx.populate_implementations_for_trait_if_necessary(trait_ref.def_id);
match ccx.tcx.lang_items.to_builtin_kind(trait_ref.def_id) {
Some(ty::BoundSend) | Some(ty::BoundSync) => {}
Some(_) | None => {
if !ccx.tcx.trait_has_default_impl(trait_ref.def_id) {
error_192(ccx, item.span);
}
let sync_trait = ccx.tcx.lang_items.require(lang_items::SyncTraitLangItem)
.unwrap_or_else(|msg| ccx.tcx.sess.fatal(&msg[..]));
let send_trait = ccx.tcx.lang_items.require(lang_items::SendTraitLangItem)
.unwrap_or_else(|msg| ccx.tcx.sess.fatal(&msg[..]));
if trait_ref.def_id != sync_trait && trait_ref.def_id != send_trait {
if !ccx.tcx.trait_has_default_impl(trait_ref.def_id) {
error_192(ccx, item.span);
}
}
}
@ -241,9 +243,10 @@ impl<'ccx, 'gcx> CheckTypeWellFormedVisitor<'ccx, 'gcx> {
// For DST, all intermediate types must be sized.
let unsized_len = if all_sized || variant.fields.is_empty() { 0 } else { 1 };
for field in &variant.fields[..variant.fields.len() - unsized_len] {
fcx.register_builtin_bound(
fcx.register_bound(
field.ty,
ty::BoundSized,
fcx.tcx.lang_items.require(lang_items::SizedTraitLangItem)
.unwrap_or_else(|msg| fcx.tcx.sess.fatal(&msg[..])),
traits::ObligationCause::new(field.span,
fcx.body_id,
traits::FieldSized));

View file

@ -182,14 +182,16 @@ impl<'cx, 'tcx, 'v> ItemLikeVisitor<'v> for OverlapChecker<'cx, 'tcx> {
// This is something like impl Trait1 for Trait2. Illegal
// if Trait1 is a supertrait of Trait2 or Trait2 is not object safe.
if data.principal().is_none() || !self.tcx.is_object_safe(data.principal().unwrap().def_id()) {
if data.principal().is_none() ||
!self.tcx.is_object_safe(data.principal().unwrap().def_id()) {
// This is an error, but it will be
// reported by wfcheck. Ignore it
// here. This is tested by
// `coherence-impl-trait-for-trait-object-safe.rs`.
} else {
let mut supertrait_def_ids =
traits::supertrait_def_ids(self.tcx, data.principal().unwrap().def_id());
traits::supertrait_def_ids(self.tcx,
data.principal().unwrap().def_id());
if supertrait_def_ids.any(|d| d == trait_def_id) {
span_err!(self.tcx.sess,
item.span,

View file

@ -376,7 +376,8 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
let contra = self.contravariant(variance);
self.add_constraints_from_region(generics, data.region_bound, contra);
let poly_trait_ref = data.principal().unwrap().with_self_ty(self.tcx(), self.tcx().types.err);
let poly_trait_ref = data.principal().unwrap().with_self_ty(self.tcx(),
self.tcx().types.err);
self.add_constraints_from_trait_ref(generics, poly_trait_ref.0, variance);
for projection in &data.projection_bounds {

View file

@ -30,6 +30,7 @@ use syntax_pos::{self, DUMMY_SP, Pos};
use rustc_trans::back::link;
use rustc::middle::privacy::AccessLevels;
use rustc::middle::resolve_lifetime::DefRegion::*;
use rustc::middle::lang_items;
use rustc::hir::def::{Def, CtorKind};
use rustc::hir::def_id::{self, DefId, DefIndex, CRATE_DEF_INDEX};
use rustc::hir::print as pprust;
@ -593,12 +594,21 @@ pub enum TyParamBound {
impl TyParamBound {
fn maybe_sized(cx: &DocContext) -> TyParamBound {
use rustc::hir::TraitBoundModifier as TBM;
let mut sized_bound = ty::BoundSized.clean(cx);
if let TyParamBound::TraitBound(_, ref mut tbm) = sized_bound {
*tbm = TBM::Maybe
};
sized_bound
let did = cx.tcx().lang_items.require(lang_items::SizedTraitLangItem)
.unwrap_or_else(|msg| cx.tcx().sess.fatal(&msg[..]));
let empty = cx.tcx().intern_substs(&[]);
let path = external_path(cx, &cx.tcx().item_name(did).as_str(),
Some(did), false, vec![], empty);
inline::record_extern_fqn(cx, did, TypeKind::Trait);
TraitBound(PolyTrait {
trait_: ResolvedPath {
path: path,
typarams: None,
did: did,
is_generic: false,
},
lifetimes: vec![]
}, hir::TraitBoundModifier::Maybe)
}
fn is_sized_bound(&self, cx: &DocContext) -> bool {
@ -675,37 +685,6 @@ fn external_path(cx: &DocContext, name: &str, trait_did: Option<DefId>, has_self
}
}
impl Clean<TyParamBound> for ty::BuiltinBound {
fn clean(&self, cx: &DocContext) -> TyParamBound {
let tcx = cx.tcx;
let empty = tcx.intern_substs(&[]);
let (did, path) = match *self {
ty::BoundSend =>
(tcx.lang_items.send_trait().unwrap(),
external_path(cx, "Send", None, false, vec![], empty)),
ty::BoundSized =>
(tcx.lang_items.sized_trait().unwrap(),
external_path(cx, "Sized", None, false, vec![], empty)),
ty::BoundCopy =>
(tcx.lang_items.copy_trait().unwrap(),
external_path(cx, "Copy", None, false, vec![], empty)),
ty::BoundSync =>
(tcx.lang_items.sync_trait().unwrap(),
external_path(cx, "Sync", None, false, vec![], empty)),
};
inline::record_extern_fqn(cx, did, TypeKind::Trait);
TraitBound(PolyTrait {
trait_: ResolvedPath {
path: path,
typarams: None,
did: did,
is_generic: false,
},
lifetimes: vec![]
}, hir::TraitBoundModifier::None)
}
}
impl<'tcx> Clean<TyParamBound> for ty::TraitRef<'tcx> {
fn clean(&self, cx: &DocContext) -> TyParamBound {
inline::record_extern_fqn(cx, self.def_id, TypeKind::Trait);
@ -1915,8 +1894,8 @@ impl<'tcx> Clean<Type> for ty::Ty<'tcx> {
});
}
let path = external_path(cx, &cx.tcx.item_name(did).as_str(),
Some(did), false, bindings, obj.principal.0.substs);
let path = external_path(cx, &cx.tcx().item_name(did).as_str(), Some(did),
false, bindings, principal.0.substs);
ResolvedPath {
path: path,
typarams: Some(typarams),

View file

@ -12,8 +12,8 @@ trait Trait {}
pub fn main() {
let x: Vec<Trait + Sized> = Vec::new();
//~^ ERROR `Trait + Sized: std::marker::Sized` is not satisfied
//~^ ERROR the trait bound `Trait + std::marker::Sized: std::marker::Sized` is not satisfied
//~| ERROR the trait `std::marker::Sized` cannot be made into an object
//~| ERROR `Trait + Sized: std::marker::Sized` is not satisfied
//~| ERROR the trait bound `Trait + std::marker::Sized: std::marker::Sized` is not satisfied
//~| ERROR the trait `std::marker::Sized` cannot be made into an object
}

View file

@ -11,8 +11,8 @@
use std::fmt::Debug;
const CONST_0: Debug+Sync = *(&0 as &(Debug+Sync));
//~^ ERROR `std::fmt::Debug + Sync + 'static: std::marker::Sized` is not satisfied
//~| NOTE the trait `std::marker::Sized` is not implemented for `std::fmt::Debug + Sync + 'static`
//~^ ERROR `std::fmt::Debug + std::marker::Sync + 'static: std::marker::Sized` is not satisfied
//~| NOTE the trait `std::marker::Sized` is not implemented for `std::fmt::Debug + std::marker::Syn
//~| NOTE does not have a constant size known at compile-time
//~| NOTE constant expressions must have a statically known size
@ -23,8 +23,8 @@ const CONST_FOO: str = *"foo";
//~| NOTE constant expressions must have a statically known size
static STATIC_1: Debug+Sync = *(&1 as &(Debug+Sync));
//~^ ERROR `std::fmt::Debug + Sync + 'static: std::marker::Sized` is not satisfied
//~| NOTE the trait `std::marker::Sized` is not implemented for `std::fmt::Debug + Sync + 'static`
//~^ ERROR `std::fmt::Debug + std::marker::Sync + 'static: std::marker::Sized` is not satisfied
//~| NOTE the trait `std::marker::Sized` is not implemented for `std::fmt::Debug + std::marker::Syn
//~| NOTE does not have a constant size known at compile-time
//~| NOTE constant expressions must have a statically known size

View file

@ -16,6 +16,6 @@ fn size_of_copy<T: Copy+?Sized>() -> usize { mem::size_of::<T>() }
fn main() {
size_of_copy::<Misc+Copy>();
//~^ ERROR `Misc + Copy: std::marker::Copy` is not satisfied
//~^ ERROR the trait bound `Misc + std::marker::Copy: std::marker::Copy` is not satisfied
//~| ERROR the trait `std::marker::Copy` cannot be made into an object
}

View file

@ -21,10 +21,10 @@ fn c(x: Box<Foo+Sync+Send>) {
}
fn d(x: Box<Foo>) {
a(x); //~ ERROR mismatched types
//~| expected type `Box<Foo + Send + 'static>`
//~| found type `Box<Foo + 'static>`
//~| expected bounds `Send`, found no bounds
a(x); //~ ERROR mismatched types [E0308]
//~| NOTE expected type `Box<Foo + std::marker::Send + 'static>`
//~| NOTE found type `Box<Foo + 'static>`
//~| NOTE expected trait Foo, found a different trait Foo
}
fn main() { }

View file

@ -15,7 +15,7 @@ trait Foo {
// This should emit the less confusing error, not the more confusing one.
fn foo(_x: Foo + Send) {
//~^ ERROR `Foo + Send + 'static: std::marker::Sized` is not satisfied
//~^ ERROR the trait bound `Foo + std::marker::Send + 'static: std::marker::Sized` is not
}
fn main() { }