Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor TraitObject to Slice<ExistentialPredicate> #37965

Merged
merged 7 commits into from
Nov 30, 2016
2 changes: 1 addition & 1 deletion mk/crates.mk
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,7 @@ DEPS_rustc_trans := arena flate getopts graphviz libc rustc rustc_back \
DEPS_rustc_incremental := rustc syntax_pos serialize rustc_data_structures
DEPS_rustc_save_analysis := rustc log syntax syntax_pos serialize
DEPS_rustc_typeck := rustc syntax syntax_pos rustc_platform_intrinsics rustc_const_math \
rustc_const_eval rustc_errors
rustc_const_eval rustc_errors rustc_data_structures

DEPS_rustdoc := rustc rustc_driver native:hoedown serialize getopts test \
rustc_lint rustc_const_eval syntax_pos rustc_data_structures
Expand Down
2 changes: 1 addition & 1 deletion src/librustc/infer/freshen.rs
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,7 @@ impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for TypeFreshener<'a, 'gcx, 'tcx> {
ty::TyRef(..) |
ty::TyFnDef(..) |
ty::TyFnPtr(_) |
ty::TyTrait(..) |
ty::TyDynamic(..) |
ty::TyClosure(..) |
ty::TyNever |
ty::TyTuple(..) |
Expand Down
5 changes: 4 additions & 1 deletion src/librustc/infer/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -1492,11 +1493,13 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
}
}

let copy_def_id = self.tcx.require_lang_item(lang_items::CopyTraitLangItem);

// 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)
Expand Down
1 change: 0 additions & 1 deletion src/librustc/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)]
Expand Down
33 changes: 8 additions & 25 deletions src/librustc/middle/lang_items.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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),
Expand Down Expand Up @@ -381,3 +356,11 @@ language_item_table! {

DebugTraitLangItem, "debug_trait", debug_trait;
}

impl<'a, 'tcx, 'gcx> ty::TyCtxt<'a, 'tcx, 'gcx> {
pub fn require_lang_item(&self, lang_item: LangItem) -> DefId {
self.lang_items.require(lang_item).unwrap_or_else(|msg| {
self.sess.fatal(&msg)
})
}
}
18 changes: 8 additions & 10 deletions src/librustc/traits/coherence.rs
Original file line number Diff line number Diff line change
Expand Up @@ -225,14 +225,12 @@ fn ty_is_local(tcx: TyCtxt, ty: Ty, infer_is_local: InferIsLocal) -> bool {

fn fundamental_ty(tcx: TyCtxt, ty: Ty) -> bool {
match ty.sty {
ty::TyBox(..) | ty::TyRef(..) =>
true,
ty::TyAdt(def, _) =>
def.is_fundamental(),
ty::TyTrait(ref data) =>
tcx.has_attr(data.principal.def_id(), "fundamental"),
_ =>
false
ty::TyBox(..) | ty::TyRef(..) => true,
ty::TyAdt(def, _) => def.is_fundamental(),
ty::TyDynamic(ref data, ..) => {
data.principal().map_or(false, |p| tcx.has_attr(p.def_id(), "fundamental"))
}
_ => false
}
}

Expand Down Expand Up @@ -272,8 +270,8 @@ fn ty_is_local_constructor(tcx: TyCtxt, ty: Ty, infer_is_local: InferIsLocal)->
krate == Some(LOCAL_CRATE)
}

ty::TyTrait(ref tt) => {
tt.principal.def_id().is_local()
ty::TyDynamic(ref tt, ..) => {
tt.principal().map_or(false, |p| p.def_id().is_local())
}

ty::TyError => {
Expand Down
12 changes: 1 addition & 11 deletions src/librustc/traits/error_reporting.rs
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
ty::TyBox(..) | ty::TyRef(..) | ty::TyRawPtr(..) => Some(5),
ty::TyArray(..) | ty::TySlice(..) => Some(6),
ty::TyFnDef(..) | ty::TyFnPtr(..) => Some(7),
ty::TyTrait(..) => Some(8),
ty::TyDynamic(..) => Some(8),
ty::TyClosure(..) => Some(9),
ty::TyTuple(..) => Some(10),
ty::TyProjection(..) => Some(11),
Expand Down Expand Up @@ -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");
}
Expand Down
27 changes: 15 additions & 12 deletions src/librustc/traits/fulfill.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -230,18 +230,21 @@ impl<'a, 'gcx, 'tcx> FulfillmentContext<'tcx> {
normalized.value
}

pub fn register_builtin_bound(&mut self,
infcx: &InferCtxt<'a, 'gcx, 'tcx>,
ty: Ty<'tcx>,
builtin_bound: ty::BuiltinBound,
cause: ObligationCause<'tcx>)
pub fn register_bound(&mut self,
infcx: &InferCtxt<'a, 'gcx, 'tcx>,
ty: Ty<'tcx>,
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,
Expand Down
51 changes: 25 additions & 26 deletions src/librustc/traits/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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,

Expand Down Expand Up @@ -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>,
ty: Ty<'tcx>,
bound: ty::BuiltinBound,
span: Span)
-> bool
pub fn type_known_to_meet_bound<'a, 'gcx, 'tcx>(infcx: &InferCtxt<'a, 'gcx, 'tcx>,
ty: Ty<'tcx>,
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
Expand All @@ -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
}
Expand Down
4 changes: 2 additions & 2 deletions src/librustc/traits/project.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1123,15 +1123,15 @@ fn confirm_object_candidate<'cx, 'gcx, 'tcx>(
debug!("confirm_object_candidate(object_ty={:?})",
object_ty);
let data = match object_ty.sty {
ty::TyTrait(ref data) => data,
ty::TyDynamic(ref data, ..) => data,
_ => {
span_bug!(
obligation.cause.span,
"confirm_object_candidate called with non-object: {:?}",
object_ty)
}
};
let env_predicates = data.projection_bounds.iter().map(|p| {
let env_predicates = data.projection_bounds().map(|p| {
p.with_self_ty(selcx.tcx(), object_ty).to_predicate()
}).collect();
let env_predicate = {
Expand Down
Loading