eddyb's changes for DST coercions
+ lots of rebasing
This commit is contained in:
parent
c2b30b86df
commit
843db01bd9
40 changed files with 1019 additions and 514 deletions
|
|
@ -807,6 +807,9 @@ register_diagnostics! {
|
|||
E0017,
|
||||
E0019,
|
||||
E0022,
|
||||
E0038,
|
||||
E0079, // enum variant: expected signed integer constant
|
||||
E0080, // enum variant: constant evaluation error
|
||||
E0109,
|
||||
E0110,
|
||||
E0134,
|
||||
|
|
|
|||
|
|
@ -259,3 +259,5 @@ pub const tag_codemap_filemap: usize = 0xa2;
|
|||
pub const tag_item_super_predicates: usize = 0xa3;
|
||||
|
||||
pub const tag_defaulted_trait: usize = 0xa4;
|
||||
|
||||
pub const tag_impl_coerce_unsized_kind: usize = 0xa5;
|
||||
|
|
|
|||
|
|
@ -279,6 +279,14 @@ pub fn get_impl_polarity<'tcx>(tcx: &ty::ctxt<'tcx>,
|
|||
decoder::get_impl_polarity(&*cdata, def.node)
|
||||
}
|
||||
|
||||
pub fn get_custom_coerce_unsized_kind<'tcx>(tcx: &ty::ctxt<'tcx>,
|
||||
def: ast::DefId)
|
||||
-> Option<ty::CustomCoerceUnsized> {
|
||||
let cstore = &tcx.sess.cstore;
|
||||
let cdata = cstore.get_crate_data(def.krate);
|
||||
decoder::get_custom_coerce_unsized_kind(&*cdata, def.node)
|
||||
}
|
||||
|
||||
// Given a def_id for an impl, return the trait it implements,
|
||||
// if there is one.
|
||||
pub fn get_impl_trait<'tcx>(tcx: &ty::ctxt<'tcx>,
|
||||
|
|
|
|||
|
|
@ -489,6 +489,16 @@ pub fn get_impl_polarity<'tcx>(cdata: Cmd,
|
|||
}
|
||||
}
|
||||
|
||||
pub fn get_custom_coerce_unsized_kind<'tcx>(cdata: Cmd,
|
||||
id: ast::NodeId)
|
||||
-> Option<ty::CustomCoerceUnsized> {
|
||||
let item_doc = lookup_item(id, cdata.data());
|
||||
reader::maybe_get_doc(item_doc, tag_impl_coerce_unsized_kind).map(|kind_doc| {
|
||||
let mut decoder = reader::Decoder::new(kind_doc);
|
||||
Decodable::decode(&mut decoder).unwrap()
|
||||
})
|
||||
}
|
||||
|
||||
pub fn get_impl_trait<'tcx>(cdata: Cmd,
|
||||
id: ast::NodeId,
|
||||
tcx: &ty::ctxt<'tcx>)
|
||||
|
|
|
|||
|
|
@ -1219,6 +1219,16 @@ fn encode_info_for_item(ecx: &EncodeContext,
|
|||
encode_attributes(rbml_w, &item.attrs);
|
||||
encode_unsafety(rbml_w, unsafety);
|
||||
encode_polarity(rbml_w, polarity);
|
||||
|
||||
match tcx.custom_coerce_unsized_kinds.borrow().get(&local_def(item.id)) {
|
||||
Some(&kind) => {
|
||||
rbml_w.start_tag(tag_impl_coerce_unsized_kind);
|
||||
kind.encode(rbml_w);
|
||||
rbml_w.end_tag();
|
||||
}
|
||||
None => {}
|
||||
}
|
||||
|
||||
match ty.node {
|
||||
ast::TyPath(None, ref path) if path.segments.len() == 1 => {
|
||||
let name = path.segments.last().unwrap().identifier.name;
|
||||
|
|
|
|||
|
|
@ -890,10 +890,6 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,'tcx,TYPER> {
|
|||
}
|
||||
};
|
||||
|
||||
debug!("walk_autoref: expr.id={} cmt_base={}",
|
||||
expr.id,
|
||||
cmt_base.repr(self.tcx()));
|
||||
|
||||
match *autoref {
|
||||
ty::AutoPtr(r, m) => {
|
||||
self.delegate.borrow(expr.id,
|
||||
|
|
|
|||
|
|
@ -261,11 +261,14 @@ lets_do_this! {
|
|||
|
||||
SendTraitLangItem, "send", send_trait;
|
||||
SizedTraitLangItem, "sized", sized_trait;
|
||||
UnsizeTraitLangItem, "unsize", unsize_trait;
|
||||
CopyTraitLangItem, "copy", copy_trait;
|
||||
SyncTraitLangItem, "sync", sync_trait;
|
||||
|
||||
DropTraitLangItem, "drop", drop_trait;
|
||||
|
||||
CoerceUnsizedTraitLangItem, "coerce_unsized", coerce_unsized_trait;
|
||||
|
||||
AddTraitLangItem, "add", add_trait;
|
||||
SubTraitLangItem, "sub", sub_trait;
|
||||
MulTraitLangItem, "mul", mul_trait;
|
||||
|
|
|
|||
|
|
@ -15,8 +15,12 @@ use super::{
|
|||
Obligation,
|
||||
ObligationCauseCode,
|
||||
OutputTypeParameterMismatch,
|
||||
TraitNotObjectSafe,
|
||||
PredicateObligation,
|
||||
SelectionError,
|
||||
ObjectSafetyViolation,
|
||||
MethodViolationCode,
|
||||
object_safety_violations,
|
||||
};
|
||||
|
||||
use fmt_macros::{Parser, Piece, Position};
|
||||
|
|
@ -252,6 +256,54 @@ pub fn report_selection_error<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
|
|||
note_obligation_cause(infcx, obligation);
|
||||
}
|
||||
}
|
||||
|
||||
TraitNotObjectSafe(did) => {
|
||||
span_err!(infcx.tcx.sess, obligation.cause.span, E0038,
|
||||
"cannot convert to a trait object because trait `{}` is not object-safe",
|
||||
ty::item_path_str(infcx.tcx, did));
|
||||
|
||||
for violation in object_safety_violations(infcx.tcx, did) {
|
||||
match violation {
|
||||
ObjectSafetyViolation::SizedSelf => {
|
||||
infcx.tcx.sess.span_note(
|
||||
obligation.cause.span,
|
||||
"the trait cannot require that `Self : Sized`");
|
||||
}
|
||||
|
||||
ObjectSafetyViolation::SupertraitSelf => {
|
||||
infcx.tcx.sess.span_note(
|
||||
obligation.cause.span,
|
||||
"the trait cannot use `Self` as a type parameter \
|
||||
in the supertrait listing");
|
||||
}
|
||||
|
||||
ObjectSafetyViolation::Method(method,
|
||||
MethodViolationCode::StaticMethod) => {
|
||||
infcx.tcx.sess.span_note(
|
||||
obligation.cause.span,
|
||||
&format!("method `{}` has no receiver",
|
||||
method.name.user_string(infcx.tcx)));
|
||||
}
|
||||
|
||||
ObjectSafetyViolation::Method(method,
|
||||
MethodViolationCode::ReferencesSelf) => {
|
||||
infcx.tcx.sess.span_note(
|
||||
obligation.cause.span,
|
||||
&format!("method `{}` references the `Self` type \
|
||||
in its arguments or return type",
|
||||
method.name.user_string(infcx.tcx)));
|
||||
}
|
||||
|
||||
ObjectSafetyViolation::Method(method,
|
||||
MethodViolationCode::Generic) => {
|
||||
infcx.tcx.sess.span_note(
|
||||
obligation.cause.span,
|
||||
&format!("method `{}` has generic type parameters",
|
||||
method.name.user_string(infcx.tcx)));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -403,10 +455,6 @@ fn note_obligation_cause_code<'a, 'tcx, T>(infcx: &InferCtxt<'a, 'tcx>,
|
|||
"only the last field of a struct or enum variant \
|
||||
may have a dynamically sized type")
|
||||
}
|
||||
ObligationCauseCode::ObjectSized => {
|
||||
span_note!(tcx.sess, cause_span,
|
||||
"only sized types can be made into objects");
|
||||
}
|
||||
ObligationCauseCode::SharedStatic => {
|
||||
span_note!(tcx.sess, cause_span,
|
||||
"shared static variables must have a type that implements `Sync`");
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@ use util::ppaux::Repr;
|
|||
|
||||
pub use self::error_reporting::report_fulfillment_errors;
|
||||
pub use self::error_reporting::report_overflow_error;
|
||||
pub use self::error_reporting::report_selection_error;
|
||||
pub use self::error_reporting::suggest_new_overflow_limit;
|
||||
pub use self::coherence::orphan_check;
|
||||
pub use self::coherence::overlapping_impls;
|
||||
|
|
@ -48,6 +49,7 @@ pub use self::select::{MethodMatchedData}; // intentionally don't export variant
|
|||
pub use self::util::elaborate_predicates;
|
||||
pub use self::util::get_vtable_index_of_object_method;
|
||||
pub use self::util::trait_ref_for_builtin_bound;
|
||||
pub use self::util::predicate_for_trait_def;
|
||||
pub use self::util::supertraits;
|
||||
pub use self::util::Supertraits;
|
||||
pub use self::util::supertrait_def_ids;
|
||||
|
|
@ -121,9 +123,6 @@ pub enum ObligationCauseCode<'tcx> {
|
|||
// Types of fields (other than the last) in a struct must be sized.
|
||||
FieldSized,
|
||||
|
||||
// Only Sized types can be made into objects
|
||||
ObjectSized,
|
||||
|
||||
// static items must have `Sync` type
|
||||
SharedStatic,
|
||||
|
||||
|
|
@ -159,6 +158,7 @@ pub enum SelectionError<'tcx> {
|
|||
OutputTypeParameterMismatch(ty::PolyTraitRef<'tcx>,
|
||||
ty::PolyTraitRef<'tcx>,
|
||||
ty::type_err<'tcx>),
|
||||
TraitNotObjectSafe(ast::DefId),
|
||||
}
|
||||
|
||||
pub struct FulfillmentError<'tcx> {
|
||||
|
|
@ -536,7 +536,9 @@ impl<'tcx, N> Vtable<'tcx, N> {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn map_nested<M, F>(&self, op: F) -> Vtable<'tcx, M> where F: FnMut(&N) -> M {
|
||||
pub fn map_nested<M, F>(&self, op: F) -> Vtable<'tcx, M> where
|
||||
F: FnMut(&N) -> M,
|
||||
{
|
||||
match *self {
|
||||
VtableImpl(ref i) => VtableImpl(i.map_nested(op)),
|
||||
VtableDefaultImpl(ref t) => VtableDefaultImpl(t.map_nested(op)),
|
||||
|
|
|
|||
|
|
@ -25,6 +25,8 @@ use super::{PredicateObligation, TraitObligation, ObligationCause};
|
|||
use super::report_overflow_error;
|
||||
use super::{ObligationCauseCode, BuiltinDerivedObligation, ImplDerivedObligation};
|
||||
use super::{SelectionError, Unimplemented, OutputTypeParameterMismatch};
|
||||
use super::{ObjectCastObligation, Obligation};
|
||||
use super::TraitNotObjectSafe;
|
||||
use super::Selection;
|
||||
use super::SelectionResult;
|
||||
use super::{VtableBuiltin, VtableImpl, VtableParam, VtableClosure,
|
||||
|
|
@ -35,7 +37,7 @@ use super::util;
|
|||
|
||||
use middle::fast_reject;
|
||||
use middle::subst::{Subst, Substs, TypeSpace, VecPerParamSpace};
|
||||
use middle::ty::{self, RegionEscape, ToPolyTraitRef, Ty};
|
||||
use middle::ty::{self, AsPredicate, RegionEscape, ToPolyTraitRef, Ty};
|
||||
use middle::infer;
|
||||
use middle::infer::{InferCtxt, TypeFreshener};
|
||||
use middle::ty_fold::TypeFoldable;
|
||||
|
|
@ -207,6 +209,8 @@ enum SelectionCandidate<'tcx> {
|
|||
|
||||
BuiltinObjectCandidate,
|
||||
|
||||
BuiltinUnsizeCandidate,
|
||||
|
||||
ErrorCandidate,
|
||||
}
|
||||
|
||||
|
|
@ -904,6 +908,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
|||
try!(self.assemble_builtin_bound_candidates(bound, stack, &mut candidates));
|
||||
}
|
||||
|
||||
None if self.tcx().lang_items.unsize_trait() ==
|
||||
Some(obligation.predicate.def_id()) => {
|
||||
self.assemble_candidates_for_unsizing(obligation, &mut candidates);
|
||||
}
|
||||
|
||||
Some(ty::BoundSend) |
|
||||
Some(ty::BoundSync) |
|
||||
None => {
|
||||
|
|
@ -1356,6 +1365,64 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
|||
}).unwrap();
|
||||
}
|
||||
|
||||
/// Search for unsizing that might apply to `obligation`.
|
||||
fn assemble_candidates_for_unsizing(&mut self,
|
||||
obligation: &TraitObligation<'tcx>,
|
||||
candidates: &mut SelectionCandidateSet<'tcx>) {
|
||||
// TODO is it Ok to skip the binder here?
|
||||
let source = self.infcx.shallow_resolve(*obligation.self_ty().skip_binder());
|
||||
let target = self.infcx.shallow_resolve(obligation.predicate.0.input_types()[0]);
|
||||
|
||||
debug!("assemble_candidates_for_unsizing(source={}, target={})",
|
||||
source.repr(self.tcx()), target.repr(self.tcx()));
|
||||
|
||||
let may_apply = match (&source.sty, &target.sty) {
|
||||
// Trait+Kx+'a -> Trait+Ky+'b (upcasts).
|
||||
(&ty::ty_trait(ref data_a), &ty::ty_trait(ref data_b)) => {
|
||||
// Upcasts permit two things:
|
||||
//
|
||||
// 1. Dropping builtin bounds, e.g. `Foo+Send` to `Foo`
|
||||
// 2. Tightening the region bound, e.g. `Foo+'a` to `Foo+'b` if `'a : 'b`
|
||||
//
|
||||
// Note that neither of these changes requires any
|
||||
// change at runtime. Eventually this will be
|
||||
// generalized.
|
||||
//
|
||||
// We always upcast when we can because of reason
|
||||
// #2 (region bounds).
|
||||
data_a.principal.def_id() == data_a.principal.def_id() &&
|
||||
data_a.bounds.builtin_bounds.is_superset(&data_b.bounds.builtin_bounds)
|
||||
}
|
||||
|
||||
// T -> Trait.
|
||||
(_, &ty::ty_trait(_)) => true,
|
||||
|
||||
// Ambiguous handling is below T -> Trait, because inference
|
||||
// variables can still implement Unsize<Trait> and nested
|
||||
// obligations will have the final say (likely deferred).
|
||||
(&ty::ty_infer(ty::TyVar(_)), _) |
|
||||
(_, &ty::ty_infer(ty::TyVar(_))) => {
|
||||
debug!("assemble_candidates_for_unsizing: ambiguous");
|
||||
candidates.ambiguous = true;
|
||||
false
|
||||
}
|
||||
|
||||
// [T; n] -> [T].
|
||||
(&ty::ty_vec(_, Some(_)), &ty::ty_vec(_, None)) => true,
|
||||
|
||||
// Struct<T> -> Struct<U>.
|
||||
(&ty::ty_struct(def_id_a, _), &ty::ty_struct(def_id_b, _)) => {
|
||||
def_id_a == def_id_b
|
||||
}
|
||||
|
||||
_ => false
|
||||
};
|
||||
|
||||
if may_apply {
|
||||
candidates.vec.push(BuiltinUnsizeCandidate);
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// WINNOW
|
||||
//
|
||||
|
|
@ -1427,6 +1494,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
|||
&ClosureCandidate(..) |
|
||||
&FnPointerCandidate(..) |
|
||||
&BuiltinObjectCandidate(..) |
|
||||
&&BuiltinUnsizeCandidate(..) |
|
||||
&DefaultImplObjectCandidate(..) |
|
||||
&BuiltinCandidate(..) => {
|
||||
// We have a where-clause so don't go around looking
|
||||
|
|
@ -1855,11 +1923,12 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
|||
obligation.recursion_depth + 1,
|
||||
&skol_ty);
|
||||
let skol_obligation =
|
||||
try!(util::predicate_for_trait_def(self.tcx(),
|
||||
derived_cause.clone(),
|
||||
trait_def_id,
|
||||
obligation.recursion_depth + 1,
|
||||
normalized_ty));
|
||||
util::predicate_for_trait_def(self.tcx(),
|
||||
derived_cause.clone(),
|
||||
trait_def_id,
|
||||
obligation.recursion_depth + 1,
|
||||
normalized_ty,
|
||||
vec![]);
|
||||
obligations.push(skol_obligation);
|
||||
Ok(self.infcx().plug_leaks(skol_map, snapshot, &obligations))
|
||||
})
|
||||
|
|
@ -1949,6 +2018,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
|||
self.confirm_projection_candidate(obligation);
|
||||
Ok(VtableParam(Vec::new()))
|
||||
}
|
||||
|
||||
BuiltinUnsizeCandidate => {
|
||||
let data = try!(self.confirm_builtin_unsize_candidate(obligation));
|
||||
Ok(VtableBuiltin(data))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -2322,6 +2396,159 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
fn confirm_builtin_unsize_candidate(&mut self,
|
||||
obligation: &TraitObligation<'tcx>,)
|
||||
-> Result<VtableBuiltinData<PredicateObligation<'tcx>>,
|
||||
SelectionError<'tcx>> {
|
||||
let tcx = self.tcx();
|
||||
|
||||
// TODO is this skip_binder Ok?
|
||||
let source = self.infcx.shallow_resolve(*obligation.self_ty().skip_binder());
|
||||
let target = self.infcx.shallow_resolve(obligation.predicate.0.input_types()[0]);
|
||||
|
||||
debug!("confirm_builtin_unsize_candidate(source={}, target={})",
|
||||
source.repr(tcx), target.repr(tcx));
|
||||
|
||||
let mut nested = vec![];
|
||||
match (&source.sty, &target.sty) {
|
||||
// Trait+Kx+'a -> Trait+Ky+'b (upcasts).
|
||||
(&ty::ty_trait(ref data_a), &ty::ty_trait(ref data_b)) => {
|
||||
// See assemble_candidates_for_unsizing for more info.
|
||||
let bounds = ty::ExistentialBounds {
|
||||
region_bound: data_b.bounds.region_bound,
|
||||
builtin_bounds: data_b.bounds.builtin_bounds,
|
||||
projection_bounds: data_a.bounds.projection_bounds.clone(),
|
||||
};
|
||||
|
||||
let new_trait = ty::mk_trait(tcx, data_a.principal.clone(), bounds);
|
||||
let origin = infer::Misc(obligation.cause.span);
|
||||
if self.infcx.sub_types(false, origin, new_trait, target).is_err() {
|
||||
return Err(Unimplemented);
|
||||
}
|
||||
|
||||
// Register one obligation for 'a: 'b.
|
||||
let cause = ObligationCause::new(obligation.cause.span,
|
||||
obligation.cause.body_id,
|
||||
ObjectCastObligation(target));
|
||||
let outlives = ty::OutlivesPredicate(data_a.bounds.region_bound,
|
||||
data_b.bounds.region_bound);
|
||||
nested.push(Obligation::with_depth(cause,
|
||||
obligation.recursion_depth + 1,
|
||||
ty::Binder(outlives).as_predicate()));
|
||||
}
|
||||
|
||||
// T -> Trait.
|
||||
(_, &ty::ty_trait(ref data)) => {
|
||||
let object_did = data.principal_def_id();
|
||||
if !object_safety::is_object_safe(tcx, object_did) {
|
||||
return Err(TraitNotObjectSafe(object_did));
|
||||
}
|
||||
|
||||
let cause = ObligationCause::new(obligation.cause.span,
|
||||
obligation.cause.body_id,
|
||||
ObjectCastObligation(target));
|
||||
let mut push = |predicate| {
|
||||
nested.push(Obligation::with_depth(cause.clone(),
|
||||
obligation.recursion_depth + 1,
|
||||
predicate));
|
||||
};
|
||||
|
||||
// Create the obligation for casting from T to Trait.
|
||||
push(data.principal_trait_ref_with_self_ty(tcx, source).as_predicate());
|
||||
|
||||
// We can only make objects from sized types.
|
||||
let mut builtin_bounds = data.bounds.builtin_bounds;
|
||||
builtin_bounds.insert(ty::BoundSized);
|
||||
|
||||
// Create additional obligations for all the various builtin
|
||||
// bounds attached to the object cast. (In other words, if the
|
||||
// object type is Foo+Send, this would create an obligation
|
||||
// for the Send check.)
|
||||
for bound in &builtin_bounds {
|
||||
if let Ok(tr) = util::trait_ref_for_builtin_bound(tcx, bound, source) {
|
||||
push(tr.as_predicate());
|
||||
} else {
|
||||
return Err(Unimplemented);
|
||||
}
|
||||
}
|
||||
|
||||
// Create obligations for the projection predicates.
|
||||
for bound in data.projection_bounds_with_self_ty(tcx, source) {
|
||||
push(bound.as_predicate());
|
||||
}
|
||||
|
||||
// If the type is `Foo+'a`, ensures that the type
|
||||
// being cast to `Foo+'a` outlives `'a`:
|
||||
let outlives = ty::OutlivesPredicate(source,
|
||||
data.bounds.region_bound);
|
||||
push(ty::Binder(outlives).as_predicate());
|
||||
}
|
||||
|
||||
// [T; n] -> [T].
|
||||
(&ty::ty_vec(a, Some(_)), &ty::ty_vec(b, None)) => {
|
||||
let origin = infer::Misc(obligation.cause.span);
|
||||
if self.infcx.sub_types(false, origin, a, b).is_err() {
|
||||
return Err(Unimplemented);
|
||||
}
|
||||
}
|
||||
|
||||
// Struct<T> -> Struct<U>.
|
||||
(&ty::ty_struct(def_id, substs_a), &ty::ty_struct(_, substs_b)) => {
|
||||
let fields = ty::lookup_struct_fields(tcx, def_id).iter().map(|f| {
|
||||
ty::lookup_field_type_unsubstituted(tcx, def_id, f.id)
|
||||
}).collect::<Vec<_>>();
|
||||
|
||||
// The last field of the structure has to exist and be a
|
||||
// type parameter (for now, to avoid tracking edge cases).
|
||||
let i = if let Some(&ty::ty_param(p)) = fields.last().map(|ty| &ty.sty) {
|
||||
assert!(p.space == TypeSpace);
|
||||
p.idx as usize
|
||||
} else {
|
||||
return Err(Unimplemented);
|
||||
};
|
||||
|
||||
// Replace the type parameter chosen for unsizing with
|
||||
// ty_err and ensure it does not affect any other fields.
|
||||
// This could be checked after type collection for any struct
|
||||
// with a potentially unsized trailing field.
|
||||
let mut new_substs = substs_a.clone();
|
||||
new_substs.types.get_mut_slice(TypeSpace)[i] = tcx.types.err;
|
||||
for &ty in fields.init() {
|
||||
if ty::type_is_error(ty.subst(tcx, &new_substs)) {
|
||||
return Err(Unimplemented);
|
||||
}
|
||||
}
|
||||
|
||||
// Extract T and U from Struct<T> and Struct<U>.
|
||||
let inner_source = *substs_a.types.get(TypeSpace, i);
|
||||
let inner_target = *substs_b.types.get(TypeSpace, i);
|
||||
|
||||
// Check that all the source structure with the unsized
|
||||
// type parameter is a subtype of the target.
|
||||
new_substs.types.get_mut_slice(TypeSpace)[i] = inner_target;
|
||||
let new_struct = ty::mk_struct(tcx, def_id, tcx.mk_substs(new_substs));
|
||||
let origin = infer::Misc(obligation.cause.span);
|
||||
if self.infcx.sub_types(false, origin, new_struct, target).is_err() {
|
||||
return Err(Unimplemented);
|
||||
}
|
||||
|
||||
// Construct the nested T: Unsize<U> predicate.
|
||||
nested.push(util::predicate_for_trait_def(tcx,
|
||||
obligation.cause.clone(),
|
||||
obligation.predicate.def_id(),
|
||||
obligation.recursion_depth + 1,
|
||||
inner_source,
|
||||
vec![inner_target]));
|
||||
}
|
||||
|
||||
_ => unreachable!()
|
||||
};
|
||||
|
||||
Ok(VtableBuiltinData {
|
||||
nested: VecPerParamSpace::new(nested, vec![], vec![])
|
||||
})
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Matching
|
||||
//
|
||||
|
|
@ -2683,6 +2910,7 @@ impl<'tcx> Repr<'tcx> for SelectionCandidate<'tcx> {
|
|||
ErrorCandidate => format!("ErrorCandidate"),
|
||||
BuiltinCandidate(b) => format!("BuiltinCandidate({:?})", b),
|
||||
BuiltinObjectCandidate => format!("BuiltinObjectCandidate"),
|
||||
BuiltinUnsizeCandidate => format!("BuiltinUnsizeCandidate"),
|
||||
ParamCandidate(ref a) => format!("ParamCandidate({})", a.repr(tcx)),
|
||||
ImplCandidate(a) => format!("ImplCandidate({})", a.repr(tcx)),
|
||||
DefaultImplCandidate(t) => format!("DefaultImplCandidate({:?})", t),
|
||||
|
|
@ -2756,7 +2984,8 @@ impl<'tcx> EvaluationResult<'tcx> {
|
|||
match *self {
|
||||
EvaluatedToOk |
|
||||
EvaluatedToAmbig |
|
||||
EvaluatedToErr(OutputTypeParameterMismatch(..)) =>
|
||||
EvaluatedToErr(OutputTypeParameterMismatch(..)) |
|
||||
EvaluatedToErr(TraitNotObjectSafe(_)) =>
|
||||
true,
|
||||
|
||||
EvaluatedToErr(Unimplemented) =>
|
||||
|
|
|
|||
|
|
@ -356,13 +356,13 @@ pub fn predicate_for_trait_ref<'tcx>(
|
|||
cause: ObligationCause<'tcx>,
|
||||
trait_ref: ty::TraitRef<'tcx>,
|
||||
recursion_depth: usize)
|
||||
-> Result<PredicateObligation<'tcx>, ErrorReported>
|
||||
-> PredicateObligation<'tcx>
|
||||
{
|
||||
Ok(Obligation {
|
||||
Obligation {
|
||||
cause: cause,
|
||||
recursion_depth: recursion_depth,
|
||||
predicate: trait_ref.as_predicate(),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
pub fn predicate_for_trait_def<'tcx>(
|
||||
|
|
@ -370,13 +370,14 @@ pub fn predicate_for_trait_def<'tcx>(
|
|||
cause: ObligationCause<'tcx>,
|
||||
trait_def_id: ast::DefId,
|
||||
recursion_depth: usize,
|
||||
param_ty: Ty<'tcx>)
|
||||
-> Result<PredicateObligation<'tcx>, ErrorReported>
|
||||
param_ty: Ty<'tcx>,
|
||||
ty_params: Vec<Ty<'tcx>>)
|
||||
-> PredicateObligation<'tcx>
|
||||
{
|
||||
let trait_ref = ty::TraitRef {
|
||||
def_id: trait_def_id,
|
||||
substs: tcx.mk_substs(Substs::empty().with_self_ty(param_ty))
|
||||
};
|
||||
substs: tcx.mk_substs(Substs::new_trait(ty_params, vec![], param_ty))
|
||||
});
|
||||
predicate_for_trait_ref(cause, trait_ref, recursion_depth)
|
||||
}
|
||||
|
||||
|
|
@ -389,7 +390,7 @@ pub fn predicate_for_builtin_bound<'tcx>(
|
|||
-> Result<PredicateObligation<'tcx>, ErrorReported>
|
||||
{
|
||||
let trait_ref = try!(trait_ref_for_builtin_bound(tcx, builtin_bound, param_ty));
|
||||
predicate_for_trait_ref(cause, trait_ref, recursion_depth)
|
||||
Ok(predicate_for_trait_ref(cause, trait_ref, recursion_depth))
|
||||
}
|
||||
|
||||
/// Cast a trait reference into a reference to one of its super
|
||||
|
|
@ -561,6 +562,10 @@ impl<'tcx> Repr<'tcx> for super::SelectionError<'tcx> {
|
|||
a.repr(tcx),
|
||||
b.repr(tcx),
|
||||
c.repr(tcx)),
|
||||
|
||||
super::TraitNotObjectSafe(ref tr) =>
|
||||
format!("TraitNotObjectSafe({})",
|
||||
tr.repr(tcx))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -404,6 +404,12 @@ pub enum AutoRef<'tcx> {
|
|||
AutoUnsafe(ast::Mutability),
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, RustcEncodable, RustcDecodable, Debug)]
|
||||
pub enum CustomCoerceUnsized {
|
||||
/// Records the index of the field being coerced.
|
||||
Struct(usize)
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, RustcEncodable, RustcDecodable, PartialEq, PartialOrd, Debug)]
|
||||
pub struct param_index {
|
||||
pub space: subst::ParamSpace,
|
||||
|
|
@ -818,6 +824,9 @@ pub struct ctxt<'tcx> {
|
|||
|
||||
/// Maps Expr NodeId's to their constant qualification.
|
||||
pub const_qualif_map: RefCell<NodeMap<check_const::ConstQualif>>,
|
||||
|
||||
/// Caches CoerceUnsized kinds for impls on custom types.
|
||||
pub custom_coerce_unsized_kinds: RefCell<DefIdMap<CustomCoerceUnsized>>,
|
||||
}
|
||||
|
||||
impl<'tcx> ctxt<'tcx> {
|
||||
|
|
@ -2809,6 +2818,7 @@ pub fn mk_ctxt<'tcx>(s: Session,
|
|||
type_impls_copy_cache: RefCell::new(HashMap::new()),
|
||||
type_impls_sized_cache: RefCell::new(HashMap::new()),
|
||||
const_qualif_map: RefCell::new(NodeMap()),
|
||||
custom_coerce_unsized_kinds: RefCell::new(DefIdMap()),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -5351,6 +5361,26 @@ pub fn trait_impl_polarity<'tcx>(cx: &ctxt<'tcx>, id: ast::DefId)
|
|||
}
|
||||
}
|
||||
|
||||
pub fn custom_coerce_unsized_kind<'tcx>(cx: &ctxt<'tcx>, did: ast::DefId)
|
||||
-> CustomCoerceUnsized {
|
||||
memoized(&cx.custom_coerce_unsized_kinds, did, |did: DefId| {
|
||||
let (kind, src) = if did.krate != ast::LOCAL_CRATE {
|
||||
(csearch::get_custom_coerce_unsized_kind(cx, did), "external")
|
||||
} else {
|
||||
(None, "local")
|
||||
};
|
||||
|
||||
match kind {
|
||||
Some(kind) => kind,
|
||||
None => {
|
||||
cx.sess.bug(&format!("custom_coerce_unsized_kind: \
|
||||
{} impl `{}` is missing its kind",
|
||||
src, item_path_str(cx, did)));
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
pub fn impl_or_trait_item<'tcx>(cx: &ctxt<'tcx>, id: ast::DefId)
|
||||
-> ImplOrTraitItem<'tcx> {
|
||||
lookup_locally_or_in_crate_store("impl_or_trait_items",
|
||||
|
|
@ -6012,6 +6042,20 @@ pub fn lookup_repr_hints(tcx: &ctxt, did: DefId) -> Rc<Vec<attr::ReprAttr>> {
|
|||
})
|
||||
}
|
||||
|
||||
// Look up a field ID, whether or not it's local
|
||||
pub fn lookup_field_type_unsubstituted<'tcx>(tcx: &ctxt<'tcx>,
|
||||
struct_id: DefId,
|
||||
id: DefId)
|
||||
-> Ty<'tcx> {
|
||||
if id.krate == ast::LOCAL_CRATE {
|
||||
node_id_to_type(tcx, id.node)
|
||||
} else {
|
||||
let mut tcache = tcx.tcache.borrow_mut();
|
||||
tcache.entry(id).or_insert_with(|| csearch::get_field_type(tcx, struct_id, id)).ty
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Look up a field ID, whether or not it's local
|
||||
// Takes a list of type substs in case the struct is generic
|
||||
pub fn lookup_field_type<'tcx>(tcx: &ctxt<'tcx>,
|
||||
|
|
@ -6019,13 +6063,7 @@ pub fn lookup_field_type<'tcx>(tcx: &ctxt<'tcx>,
|
|||
id: DefId,
|
||||
substs: &Substs<'tcx>)
|
||||
-> Ty<'tcx> {
|
||||
let ty = if id.krate == ast::LOCAL_CRATE {
|
||||
node_id_to_type(tcx, id.node)
|
||||
} else {
|
||||
let mut tcache = tcx.tcache.borrow_mut();
|
||||
tcache.entry(id).or_insert_with(|| csearch::get_field_type(tcx, struct_id, id)).ty
|
||||
};
|
||||
ty.subst(tcx, substs)
|
||||
lookup_field_type_unsubstituted(tcx, struct_id, id).subst(tcx, substs)
|
||||
}
|
||||
|
||||
// Look up the list of field names and IDs for a given struct.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue