Skip to content

Refactor TraitObject to Slice<ExistentialPredicate> #37965

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

Merged
merged 7 commits into from
Nov 30, 2016
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion mk/crates.mk
Original file line number Diff line number Diff line change
@@ -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
2 changes: 1 addition & 1 deletion src/librustc/infer/freshen.rs
Original file line number Diff line number Diff line change
@@ -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(..) |
5 changes: 4 additions & 1 deletion src/librustc/infer/mod.rs
Original file line number Diff line number Diff line change
@@ -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,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)
1 change: 0 additions & 1 deletion src/librustc/lib.rs
Original file line number Diff line number Diff line change
@@ -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)]
33 changes: 8 additions & 25 deletions src/librustc/middle/lang_items.rs
Original file line number Diff line number Diff line change
@@ -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),
@@ -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
@@ -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
}
}

@@ -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 => {
12 changes: 1 addition & 11 deletions src/librustc/traits/error_reporting.rs
Original file line number Diff line number Diff line change
@@ -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),
@@ -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");
}
27 changes: 15 additions & 12 deletions src/librustc/traits/fulfill.rs
Original file line number Diff line number Diff line change
@@ -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,
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,
51 changes: 25 additions & 26 deletions src/librustc/traits/mod.rs
Original file line number Diff line number Diff line change
@@ -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>,
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
@@ -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
}
4 changes: 2 additions & 2 deletions src/librustc/traits/project.rs
Original file line number Diff line number Diff line change
@@ -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 = {
Loading