diff --git a/src/librustc/infer/mod.rs b/src/librustc/infer/mod.rs index 6ae104d79122b..9c63eac34e440 100644 --- a/src/librustc/infer/mod.rs +++ b/src/librustc/infer/mod.rs @@ -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) diff --git a/src/librustc/lib.rs b/src/librustc/lib.rs index 0942ce79a6b49..c0ea8d6b1e38b 100644 --- a/src/librustc/lib.rs +++ b/src/librustc/lib.rs @@ -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)] diff --git a/src/librustc/middle/lang_items.rs b/src/librustc/middle/lang_items.rs index 5af9a2f02742e..8d02d63e3a4bb 100644 --- a/src/librustc/middle/lang_items.rs +++ b/src/librustc/middle/lang_items.rs @@ -90,31 +90,6 @@ impl LanguageItems { self.require(OwnedBoxLangItem) } - pub fn from_builtin_kind(&self, bound: ty::BuiltinBound) - -> Result - { - 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 { - 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 { let def_id_kinds = [ (self.fn_trait(), ty::ClosureKind::Fn), diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs index 21009711cb18a..4ac4c31386e71 100644 --- a/src/librustc/traits/error_reporting.rs +++ b/src/librustc/traits/error_reporting.rs @@ -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"); } diff --git a/src/librustc/traits/fulfill.rs b/src/librustc/traits/fulfill.rs index f406580286da9..9ff4048f73e77 100644 --- a/src/librustc/traits/fulfill.rs +++ b/src/librustc/traits/fulfill.rs @@ -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, diff --git a/src/librustc/traits/mod.rs b/src/librustc/traits/mod.rs index a5fdaed971257..bdd0ee75eb195 100644 --- a/src/librustc/traits/mod.rs +++ b/src/librustc/traits/mod.rs @@ -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); - - 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 + infcx.tcx.item_path_str(def_id)); + + 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 } diff --git a/src/librustc/traits/select.rs b/src/librustc/traits/select.rs index 3ae0252e99020..11b23d699de2f 100644 --- a/src/librustc/traits/select.rs +++ b/src/librustc/traits/select.rs @@ -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)?; diff --git a/src/librustc/traits/structural_impls.rs b/src/librustc/traits/structural_impls.rs index d03ba5b0a31f1..dedb126d7ff6d 100644 --- a/src/librustc/traits/structural_impls.rs +++ b/src/librustc/traits/structural_impls.rs @@ -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 | diff --git a/src/librustc/traits/util.rs b/src/librustc/traits/util.rs index b94597d475927..321936fe54be1 100644 --- a/src/librustc/traits/util.rs +++ b/src/librustc/traits/util.rs @@ -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, 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, 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. diff --git a/src/librustc/ty/error.rs b/src/librustc/ty/error.rs index 8bdcc93fa2114..8ef13e62901a6 100644 --- a/src/librustc/ty/error.rs +++ b/src/librustc/ty/error.rs @@ -45,7 +45,6 @@ pub enum TypeError<'tcx> { IntMismatch(ExpectedFound), FloatMismatch(ExpectedFound), Traits(ExpectedFound), - BuiltinBoundsMismatch(ExpectedFound), VariadicMismatch(ExpectedFound), CyclicTy, ProjectionNameMismatched(ExpectedFound), @@ -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, diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index 844fc58cec37b..4544cda0ae9ae 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -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}; diff --git a/src/librustc/ty/relate.rs b/src/librustc/ty/relate.rs index 569791a0776bf..02704e94fee98 100644 --- a/src/librustc/ty/relate.rs +++ b/src/librustc/ty/relate.rs @@ -302,23 +302,6 @@ impl<'tcx> Relate<'tcx> for Vec> { } } -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>, diff --git a/src/librustc/ty/structural_impls.rs b/src/librustc/ty/structural_impls.rs index 3064e337039d5..e890d750a7b50 100644 --- a/src/librustc/ty/structural_impls.rs +++ b/src/librustc/ty/structural_impls.rs @@ -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>(&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 { diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs index 22a7423b17765..e6411ca1e4f68 100644 --- a/src/librustc/ty/sty.rs +++ b/src/librustc/ty/sty.rs @@ -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); - -impl<'a, 'gcx, 'tcx> BuiltinBounds { - pub fn empty() -> BuiltinBounds { - BuiltinBounds(EnumSet::new()) - } - - pub fn iter(&self) -> enum_set::Iter { - self.into_iter() - } - - pub fn to_predicates(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>, - self_ty: Ty<'tcx>) - -> Vec> { - 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; - 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; - 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, diff --git a/src/librustc/ty/util.rs b/src/librustc/ty/util.rs index 7253b88981f1b..350426e7f3e82 100644 --- a/src/librustc/ty/util.rs +++ b/src/librustc/ty/util.rs @@ -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, 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, ¶m_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[..])), + ¶m_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, ¶m_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[..])), + ¶m_env.is_copy_cache, span) }); if !self.has_param_types() && !self.has_self_ty() { self.flags.set(self.flags.get() | if result { diff --git a/src/librustc/ty/wf.rs b/src/librustc/ty/wf.rs index b31046abf86a3..d0bc2f0797705 100644 --- a/src/librustc/ty/wf.rs +++ b/src/librustc/ty/wf.rs @@ -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())); } } diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs index a3fa805699c9e..242342a7f93d6 100644 --- a/src/librustc/util/ppaux.rs +++ b/src/librustc/util/ppaux.rs @@ -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) diff --git a/src/librustc_mir/transform/qualify_consts.rs b/src/librustc_mir/transform/qualify_consts.rs index 4ff2beb3fdb77..9cd92cf1fdcf7 100644 --- a/src/librustc_mir/transform/qualify_consts.rs +++ b/src/librustc_mir/transform/qualify_consts.rs @@ -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); } diff --git a/src/librustc_typeck/check/cast.rs b/src/librustc_typeck/check/cast.rs index 3e1a3c870ca0d..197e7793f4b2a 100644 --- a/src/librustc_typeck/check/cast.rs +++ b/src/librustc_typeck/check/cast.rs @@ -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) } } diff --git a/src/librustc_typeck/check/closure.rs b/src/librustc_typeck/check/closure.rs index 4627c166fc6f3..be6d65bf511fd 100644 --- a/src/librustc_typeck/check/closure.rs +++ b/src/librustc_typeck/check/closure.rs @@ -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), diff --git a/src/librustc_typeck/check/method/suggest.rs b/src/librustc_typeck/check/method/suggest.rs index eb6e84c7922ce..508b0e820cef1 100644 --- a/src/librustc_typeck/check/method/suggest.rs +++ b/src/librustc_typeck/check/method/suggest.rs @@ -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, diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 2babb81bc407a..c921936800b38 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -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() { diff --git a/src/librustc_typeck/check/wfcheck.rs b/src/librustc_typeck/check/wfcheck.rs index 1ad81660f836a..57859f9c84cb6 100644 --- a/src/librustc_typeck/check/wfcheck.rs +++ b/src/librustc_typeck/check/wfcheck.rs @@ -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)); diff --git a/src/librustc_typeck/coherence/overlap.rs b/src/librustc_typeck/coherence/overlap.rs index 305b15caa69a1..5ae233f647939 100644 --- a/src/librustc_typeck/coherence/overlap.rs +++ b/src/librustc_typeck/coherence/overlap.rs @@ -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, diff --git a/src/librustc_typeck/variance/constraints.rs b/src/librustc_typeck/variance/constraints.rs index 77ade4660693a..076d024c1e1bb 100644 --- a/src/librustc_typeck/variance/constraints.rs +++ b/src/librustc_typeck/variance/constraints.rs @@ -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 { diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 6b0f0ae12975c..9d98cdd3f0377 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -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, has_self } } -impl Clean 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 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 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), diff --git a/src/test/compile-fail/bad-sized.rs b/src/test/compile-fail/bad-sized.rs index e9d0b986c1176..59a039057f37f 100644 --- a/src/test/compile-fail/bad-sized.rs +++ b/src/test/compile-fail/bad-sized.rs @@ -12,8 +12,8 @@ trait Trait {} pub fn main() { let x: Vec = 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 } diff --git a/src/test/compile-fail/const-unsized.rs b/src/test/compile-fail/const-unsized.rs index 226b567c546e5..23cff4ac6ad6c 100644 --- a/src/test/compile-fail/const-unsized.rs +++ b/src/test/compile-fail/const-unsized.rs @@ -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 diff --git a/src/test/compile-fail/issue-32963.rs b/src/test/compile-fail/issue-32963.rs index 8ba95d14931e0..14ab0dd5f631c 100644 --- a/src/test/compile-fail/issue-32963.rs +++ b/src/test/compile-fail/issue-32963.rs @@ -16,6 +16,6 @@ fn size_of_copy() -> usize { mem::size_of::() } fn main() { size_of_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 } diff --git a/src/test/compile-fail/trait-bounds-cant-coerce.rs b/src/test/compile-fail/trait-bounds-cant-coerce.rs index 1fff812af5b8d..0bfa328751ac1 100644 --- a/src/test/compile-fail/trait-bounds-cant-coerce.rs +++ b/src/test/compile-fail/trait-bounds-cant-coerce.rs @@ -21,10 +21,10 @@ fn c(x: Box) { } fn d(x: Box) { - a(x); //~ ERROR mismatched types - //~| expected type `Box` - //~| found type `Box` - //~| expected bounds `Send`, found no bounds + a(x); //~ ERROR mismatched types [E0308] + //~| NOTE expected type `Box` + //~| NOTE found type `Box` + //~| NOTE expected trait Foo, found a different trait Foo } fn main() { } diff --git a/src/test/compile-fail/trait-bounds-not-on-bare-trait.rs b/src/test/compile-fail/trait-bounds-not-on-bare-trait.rs index fd46d1a62962c..983c66ec1c40f 100644 --- a/src/test/compile-fail/trait-bounds-not-on-bare-trait.rs +++ b/src/test/compile-fail/trait-bounds-not-on-bare-trait.rs @@ -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() { }