add support for principal-less trait object types
should be a pure refactoring.
This commit is contained in:
parent
c0bbc3927e
commit
3aa1503a61
26 changed files with 202 additions and 131 deletions
|
@ -485,7 +485,13 @@ fn ty_is_local_constructor(ty: Ty<'_>, in_crate: InCrate) -> bool {
|
||||||
ty::Adt(def, _) => def_id_is_local(def.did, in_crate),
|
ty::Adt(def, _) => def_id_is_local(def.did, in_crate),
|
||||||
ty::Foreign(did) => def_id_is_local(did, in_crate),
|
ty::Foreign(did) => def_id_is_local(did, in_crate),
|
||||||
|
|
||||||
ty::Dynamic(ref tt, ..) => def_id_is_local(tt.principal().def_id(), in_crate),
|
ty::Dynamic(ref tt, ..) => {
|
||||||
|
if let Some(principal) = tt.principal() {
|
||||||
|
def_id_is_local(principal.def_id(), in_crate)
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ty::Error => true,
|
ty::Error => true,
|
||||||
|
|
||||||
|
|
|
@ -2016,7 +2016,12 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
data.principal().with_self_ty(self.tcx(), self_ty)
|
if let Some(principal) = data.principal() {
|
||||||
|
principal.with_self_ty(self.tcx(), self_ty)
|
||||||
|
} else {
|
||||||
|
// Only auto-trait bounds exist.
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
ty::Infer(ty::TyVar(_)) => {
|
ty::Infer(ty::TyVar(_)) => {
|
||||||
debug!("assemble_candidates_from_object_ty: ambiguous");
|
debug!("assemble_candidates_from_object_ty: ambiguous");
|
||||||
|
@ -2108,7 +2113,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
|
||||||
//
|
//
|
||||||
// We always upcast when we can because of reason
|
// We always upcast when we can because of reason
|
||||||
// #2 (region bounds).
|
// #2 (region bounds).
|
||||||
data_a.principal().def_id() == data_b.principal().def_id()
|
data_a.principal_def_id() == data_b.principal_def_id()
|
||||||
&& data_b.auto_traits()
|
&& data_b.auto_traits()
|
||||||
// All of a's auto traits need to be in b's auto traits.
|
// All of a's auto traits need to be in b's auto traits.
|
||||||
.all(|b| data_a.auto_traits().any(|a| a == b))
|
.all(|b| data_a.auto_traits().any(|a| a == b))
|
||||||
|
@ -2919,7 +2924,10 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
|
||||||
let self_ty = self.infcx
|
let self_ty = self.infcx
|
||||||
.shallow_resolve(*obligation.self_ty().skip_binder());
|
.shallow_resolve(*obligation.self_ty().skip_binder());
|
||||||
let poly_trait_ref = match self_ty.sty {
|
let poly_trait_ref = match self_ty.sty {
|
||||||
ty::Dynamic(ref data, ..) => data.principal().with_self_ty(self.tcx(), self_ty),
|
ty::Dynamic(ref data, ..) =>
|
||||||
|
data.principal().unwrap_or_else(|| {
|
||||||
|
span_bug!(obligation.cause.span, "object candidate with no principal")
|
||||||
|
}).with_self_ty(self.tcx(), self_ty),
|
||||||
_ => span_bug!(obligation.cause.span, "object candidate with non-object"),
|
_ => span_bug!(obligation.cause.span, "object candidate with non-object"),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -3222,8 +3230,9 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
|
||||||
(&ty::Dynamic(ref data_a, r_a), &ty::Dynamic(ref data_b, r_b)) => {
|
(&ty::Dynamic(ref data_a, r_a), &ty::Dynamic(ref data_b, r_b)) => {
|
||||||
// See assemble_candidates_for_unsizing for more info.
|
// See assemble_candidates_for_unsizing for more info.
|
||||||
let existential_predicates = data_a.map_bound(|data_a| {
|
let existential_predicates = data_a.map_bound(|data_a| {
|
||||||
let iter = iter::once(ty::ExistentialPredicate::Trait(data_a.principal()))
|
let iter =
|
||||||
.chain(
|
data_a.principal().map(|x| ty::ExistentialPredicate::Trait(x))
|
||||||
|
.into_iter().chain(
|
||||||
data_a
|
data_a
|
||||||
.projection_bounds()
|
.projection_bounds()
|
||||||
.map(|x| ty::ExistentialPredicate::Projection(x)),
|
.map(|x| ty::ExistentialPredicate::Projection(x)),
|
||||||
|
@ -3260,7 +3269,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
|
||||||
// T -> Trait.
|
// T -> Trait.
|
||||||
(_, &ty::Dynamic(ref data, r)) => {
|
(_, &ty::Dynamic(ref data, r)) => {
|
||||||
let mut object_dids = data.auto_traits()
|
let mut object_dids = data.auto_traits()
|
||||||
.chain(iter::once(data.principal().def_id()));
|
.chain(data.principal_def_id());
|
||||||
if let Some(did) = object_dids.find(|did| !tcx.is_object_safe(*did)) {
|
if let Some(did) = object_dids.find(|did| !tcx.is_object_safe(*did)) {
|
||||||
return Err(TraitNotObjectSafe(did));
|
return Err(TraitNotObjectSafe(did));
|
||||||
}
|
}
|
||||||
|
|
|
@ -183,7 +183,11 @@ impl<'a, 'gcx, 'lcx, 'tcx> ty::TyS<'tcx> {
|
||||||
ty::FnDef(..) => "fn item".into(),
|
ty::FnDef(..) => "fn item".into(),
|
||||||
ty::FnPtr(_) => "fn pointer".into(),
|
ty::FnPtr(_) => "fn pointer".into(),
|
||||||
ty::Dynamic(ref inner, ..) => {
|
ty::Dynamic(ref inner, ..) => {
|
||||||
format!("trait {}", tcx.item_path_str(inner.principal().def_id())).into()
|
if let Some(principal) = inner.principal() {
|
||||||
|
format!("trait {}", tcx.item_path_str(principal.def_id())).into()
|
||||||
|
} else {
|
||||||
|
"trait".into()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
ty::Closure(..) => "closure".into(),
|
ty::Closure(..) => "closure".into(),
|
||||||
ty::Generator(..) => "generator".into(),
|
ty::Generator(..) => "generator".into(),
|
||||||
|
|
|
@ -71,11 +71,11 @@ pub fn simplify_type<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
|
||||||
ty::Array(..) | ty::Slice(_) => Some(ArraySimplifiedType),
|
ty::Array(..) | ty::Slice(_) => Some(ArraySimplifiedType),
|
||||||
ty::RawPtr(_) => Some(PtrSimplifiedType),
|
ty::RawPtr(_) => Some(PtrSimplifiedType),
|
||||||
ty::Dynamic(ref trait_info, ..) => {
|
ty::Dynamic(ref trait_info, ..) => {
|
||||||
let principal_def_id = trait_info.principal().def_id();
|
match trait_info.principal_def_id() {
|
||||||
if tcx.trait_is_auto(principal_def_id) {
|
Some(principal_def_id) if !tcx.trait_is_auto(principal_def_id) => {
|
||||||
Some(MarkerTraitObjectSimplifiedType)
|
Some(TraitSimplifiedType(principal_def_id))
|
||||||
} else {
|
}
|
||||||
Some(TraitSimplifiedType(principal_def_id))
|
_ => Some(MarkerTraitObjectSimplifiedType)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ty::Ref(_, ty, _) => {
|
ty::Ref(_, ty, _) => {
|
||||||
|
@ -140,9 +140,9 @@ impl<D: Copy + Debug + Ord + Eq + Hash> SimplifiedTypeGen<D> {
|
||||||
ArraySimplifiedType => ArraySimplifiedType,
|
ArraySimplifiedType => ArraySimplifiedType,
|
||||||
PtrSimplifiedType => PtrSimplifiedType,
|
PtrSimplifiedType => PtrSimplifiedType,
|
||||||
NeverSimplifiedType => NeverSimplifiedType,
|
NeverSimplifiedType => NeverSimplifiedType,
|
||||||
|
MarkerTraitObjectSimplifiedType => MarkerTraitObjectSimplifiedType,
|
||||||
TupleSimplifiedType(n) => TupleSimplifiedType(n),
|
TupleSimplifiedType(n) => TupleSimplifiedType(n),
|
||||||
TraitSimplifiedType(d) => TraitSimplifiedType(map(d)),
|
TraitSimplifiedType(d) => TraitSimplifiedType(map(d)),
|
||||||
MarkerTraitObjectSimplifiedType => MarkerTraitObjectSimplifiedType,
|
|
||||||
ClosureSimplifiedType(d) => ClosureSimplifiedType(map(d)),
|
ClosureSimplifiedType(d) => ClosureSimplifiedType(map(d)),
|
||||||
GeneratorSimplifiedType(d) => GeneratorSimplifiedType(map(d)),
|
GeneratorSimplifiedType(d) => GeneratorSimplifiedType(map(d)),
|
||||||
GeneratorWitnessSimplifiedType(n) => GeneratorWitnessSimplifiedType(n),
|
GeneratorWitnessSimplifiedType(n) => GeneratorWitnessSimplifiedType(n),
|
||||||
|
|
|
@ -479,7 +479,7 @@ pub fn characteristic_def_id_of_type(ty: Ty<'_>) -> Option<DefId> {
|
||||||
match ty.sty {
|
match ty.sty {
|
||||||
ty::Adt(adt_def, _) => Some(adt_def.did),
|
ty::Adt(adt_def, _) => Some(adt_def.did),
|
||||||
|
|
||||||
ty::Dynamic(data, ..) => Some(data.principal().def_id()),
|
ty::Dynamic(data, ..) => data.principal_def_id(),
|
||||||
|
|
||||||
ty::Array(subty, _) |
|
ty::Array(subty, _) |
|
||||||
ty::Slice(subty) => characteristic_def_id_of_type(subty),
|
ty::Slice(subty) => characteristic_def_id_of_type(subty),
|
||||||
|
|
|
@ -569,13 +569,18 @@ impl<'a, 'gcx, 'tcx> Binder<ExistentialPredicate<'tcx>> {
|
||||||
impl<'tcx> serialize::UseSpecializedDecodable for &'tcx List<ExistentialPredicate<'tcx>> {}
|
impl<'tcx> serialize::UseSpecializedDecodable for &'tcx List<ExistentialPredicate<'tcx>> {}
|
||||||
|
|
||||||
impl<'tcx> List<ExistentialPredicate<'tcx>> {
|
impl<'tcx> List<ExistentialPredicate<'tcx>> {
|
||||||
pub fn principal(&self) -> ExistentialTraitRef<'tcx> {
|
pub fn principal(&self) -> Option<ExistentialTraitRef<'tcx>> {
|
||||||
match self[0] {
|
match self[0] {
|
||||||
ExistentialPredicate::Trait(tr) => tr,
|
ExistentialPredicate::Trait(tr) => Some(tr),
|
||||||
other => bug!("first predicate is {:?}", other),
|
other => bug!("first predicate is {:?}", other),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
pub fn principal_def_id(&self) -> Option<DefId> {
|
||||||
|
self.principal().map(|d| d.def_id)
|
||||||
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn projection_bounds<'a>(&'a self) ->
|
pub fn projection_bounds<'a>(&'a self) ->
|
||||||
impl Iterator<Item=ExistentialProjection<'tcx>> + 'a {
|
impl Iterator<Item=ExistentialProjection<'tcx>> + 'a {
|
||||||
|
@ -599,8 +604,12 @@ impl<'tcx> List<ExistentialPredicate<'tcx>> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'tcx> Binder<&'tcx List<ExistentialPredicate<'tcx>>> {
|
impl<'tcx> Binder<&'tcx List<ExistentialPredicate<'tcx>>> {
|
||||||
pub fn principal(&self) -> PolyExistentialTraitRef<'tcx> {
|
pub fn principal(&self) -> Option<ty::Binder<ExistentialTraitRef<'tcx>>> {
|
||||||
Binder::bind(self.skip_binder().principal())
|
self.skip_binder().principal().map(Binder::bind)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn principal_def_id(&self) -> Option<DefId> {
|
||||||
|
self.skip_binder().principal_def_id()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -1917,7 +1926,9 @@ impl<'a, 'gcx, 'tcx> TyS<'tcx> {
|
||||||
}
|
}
|
||||||
Dynamic(ref obj, region) => {
|
Dynamic(ref obj, region) => {
|
||||||
out.push(region);
|
out.push(region);
|
||||||
out.extend(obj.principal().skip_binder().substs.regions());
|
if let Some(principal) = obj.principal() {
|
||||||
|
out.extend(principal.skip_binder().substs.regions());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Adt(_, substs) | Opaque(_, substs) => {
|
Adt(_, substs) | Opaque(_, substs) => {
|
||||||
out.extend(substs.regions())
|
out.extend(substs.regions())
|
||||||
|
|
|
@ -384,7 +384,7 @@ impl<'a, 'gcx, 'tcx> WfPredicates<'a, 'gcx, 'tcx> {
|
||||||
|
|
||||||
let cause = self.cause(traits::MiscObligation);
|
let cause = self.cause(traits::MiscObligation);
|
||||||
let component_traits =
|
let component_traits =
|
||||||
data.auto_traits().chain(once(data.principal().def_id()));
|
data.auto_traits().chain(data.principal_def_id());
|
||||||
self.out.extend(
|
self.out.extend(
|
||||||
component_traits.map(|did| traits::Obligation::new(
|
component_traits.map(|did| traits::Obligation::new(
|
||||||
cause.clone(),
|
cause.clone(),
|
||||||
|
|
|
@ -713,16 +713,18 @@ define_print! {
|
||||||
// Use a type that can't appear in defaults of type parameters.
|
// Use a type that can't appear in defaults of type parameters.
|
||||||
let dummy_self = tcx.mk_infer(ty::FreshTy(0));
|
let dummy_self = tcx.mk_infer(ty::FreshTy(0));
|
||||||
|
|
||||||
let principal = tcx
|
if let Some(principal) = self.principal() {
|
||||||
.lift(&self.principal())
|
let principal = tcx
|
||||||
.expect("could not lift TraitRef for printing")
|
.lift(&principal)
|
||||||
.with_self_ty(tcx, dummy_self);
|
.expect("could not lift TraitRef for printing")
|
||||||
let projections = self.projection_bounds().map(|p| {
|
.with_self_ty(tcx, dummy_self);
|
||||||
tcx.lift(&p)
|
let projections = self.projection_bounds().map(|p| {
|
||||||
.expect("could not lift projection for printing")
|
tcx.lift(&p)
|
||||||
.with_self_ty(tcx, dummy_self)
|
.expect("could not lift projection for printing")
|
||||||
}).collect::<Vec<_>>();
|
.with_self_ty(tcx, dummy_self)
|
||||||
cx.parameterized(f, principal.substs, principal.def_id, &projections)?;
|
}).collect::<Vec<_>>();
|
||||||
|
cx.parameterized(f, principal.substs, principal.def_id, &projections)?;
|
||||||
|
}
|
||||||
|
|
||||||
// Builtin bounds.
|
// Builtin bounds.
|
||||||
for did in self.auto_traits() {
|
for did in self.auto_traits() {
|
||||||
|
|
|
@ -50,7 +50,8 @@ pub struct CodegenCx<'ll, 'tcx: 'll> {
|
||||||
/// Cache instances of monomorphic and polymorphic items
|
/// Cache instances of monomorphic and polymorphic items
|
||||||
pub instances: RefCell<FxHashMap<Instance<'tcx>, &'ll Value>>,
|
pub instances: RefCell<FxHashMap<Instance<'tcx>, &'ll Value>>,
|
||||||
/// Cache generated vtables
|
/// Cache generated vtables
|
||||||
pub vtables: RefCell<FxHashMap<(Ty<'tcx>, ty::PolyExistentialTraitRef<'tcx>), &'ll Value>>,
|
pub vtables: RefCell<FxHashMap<
|
||||||
|
(Ty<'tcx>, Option<ty::PolyExistentialTraitRef<'tcx>>), &'ll Value>>,
|
||||||
/// Cache of constant strings,
|
/// Cache of constant strings,
|
||||||
pub const_cstr_cache: RefCell<FxHashMap<LocalInternedString, &'ll Value>>,
|
pub const_cstr_cache: RefCell<FxHashMap<LocalInternedString, &'ll Value>>,
|
||||||
|
|
||||||
|
@ -311,7 +312,7 @@ impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> {
|
||||||
|
|
||||||
impl MiscMethods<'tcx> for CodegenCx<'ll, 'tcx> {
|
impl MiscMethods<'tcx> for CodegenCx<'ll, 'tcx> {
|
||||||
fn vtables(&self) -> &RefCell<FxHashMap<(Ty<'tcx>,
|
fn vtables(&self) -> &RefCell<FxHashMap<(Ty<'tcx>,
|
||||||
ty::PolyExistentialTraitRef<'tcx>), &'ll Value>>
|
Option<ty::PolyExistentialTraitRef<'tcx>>), &'ll Value>>
|
||||||
{
|
{
|
||||||
&self.vtables
|
&self.vtables
|
||||||
}
|
}
|
||||||
|
|
|
@ -429,7 +429,8 @@ fn trait_pointer_metadata(
|
||||||
// But it does not describe the trait's methods.
|
// But it does not describe the trait's methods.
|
||||||
|
|
||||||
let containing_scope = match trait_type.sty {
|
let containing_scope = match trait_type.sty {
|
||||||
ty::Dynamic(ref data, ..) => Some(get_namespace_for_item(cx, data.principal().def_id())),
|
ty::Dynamic(ref data, ..) =>
|
||||||
|
data.principal_def_id().map(|did| get_namespace_for_item(cx, did)),
|
||||||
_ => {
|
_ => {
|
||||||
bug!("debuginfo: Unexpected trait-object type in \
|
bug!("debuginfo: Unexpected trait-object type in \
|
||||||
trait_pointer_metadata(): {:?}",
|
trait_pointer_metadata(): {:?}",
|
||||||
|
|
|
@ -107,12 +107,16 @@ pub fn push_debuginfo_type_name<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
ty::Dynamic(ref trait_data, ..) => {
|
ty::Dynamic(ref trait_data, ..) => {
|
||||||
let principal = cx.tcx.normalize_erasing_late_bound_regions(
|
if let Some(principal) = trait_data.principal() {
|
||||||
ty::ParamEnv::reveal_all(),
|
let principal = cx.tcx.normalize_erasing_late_bound_regions(
|
||||||
&trait_data.principal(),
|
ty::ParamEnv::reveal_all(),
|
||||||
);
|
&principal,
|
||||||
push_item_name(cx, principal.def_id, false, output);
|
);
|
||||||
push_type_params(cx, principal.substs, output);
|
push_item_name(cx, principal.def_id, false, output);
|
||||||
|
push_type_params(cx, principal.substs, output);
|
||||||
|
} else {
|
||||||
|
output.push_str("dyn '_");
|
||||||
|
}
|
||||||
},
|
},
|
||||||
ty::FnDef(..) | ty::FnPtr(_) => {
|
ty::FnDef(..) | ty::FnPtr(_) => {
|
||||||
let sig = t.fn_sig(cx.tcx);
|
let sig = t.fn_sig(cx.tcx);
|
||||||
|
|
|
@ -69,7 +69,7 @@ impl<'a, 'tcx: 'a> VirtualIndex {
|
||||||
pub fn get_vtable<'tcx, Cx: CodegenMethods<'tcx>>(
|
pub fn get_vtable<'tcx, Cx: CodegenMethods<'tcx>>(
|
||||||
cx: &Cx,
|
cx: &Cx,
|
||||||
ty: Ty<'tcx>,
|
ty: Ty<'tcx>,
|
||||||
trait_ref: ty::PolyExistentialTraitRef<'tcx>,
|
trait_ref: Option<ty::PolyExistentialTraitRef<'tcx>>,
|
||||||
) -> Cx::Value {
|
) -> Cx::Value {
|
||||||
let tcx = cx.tcx();
|
let tcx = cx.tcx();
|
||||||
|
|
||||||
|
@ -83,8 +83,15 @@ pub fn get_vtable<'tcx, Cx: CodegenMethods<'tcx>>(
|
||||||
// Not in the cache. Build it.
|
// Not in the cache. Build it.
|
||||||
let nullptr = cx.const_null(cx.type_i8p());
|
let nullptr = cx.const_null(cx.type_i8p());
|
||||||
|
|
||||||
let methods = tcx.vtable_methods(trait_ref.with_self_ty(tcx, ty));
|
let methods_root;
|
||||||
let methods = methods.iter().cloned().map(|opt_mth| {
|
let methods = if let Some(trait_ref) = trait_ref {
|
||||||
|
methods_root = tcx.vtable_methods(trait_ref.with_self_ty(tcx, ty));
|
||||||
|
methods_root.iter()
|
||||||
|
} else {
|
||||||
|
(&[]).iter()
|
||||||
|
};
|
||||||
|
|
||||||
|
let methods = methods.cloned().map(|opt_mth| {
|
||||||
opt_mth.map_or(nullptr, |(def_id, substs)| {
|
opt_mth.map_or(nullptr, |(def_id, substs)| {
|
||||||
callee::resolve_and_get_fn_for_vtable(cx, def_id, substs)
|
callee::resolve_and_get_fn_for_vtable(cx, def_id, substs)
|
||||||
})
|
})
|
||||||
|
|
|
@ -11,7 +11,7 @@ use std::sync::Arc;
|
||||||
pub trait MiscMethods<'tcx>: BackendTypes {
|
pub trait MiscMethods<'tcx>: BackendTypes {
|
||||||
fn vtables(
|
fn vtables(
|
||||||
&self,
|
&self,
|
||||||
) -> &RefCell<FxHashMap<(Ty<'tcx>, ty::PolyExistentialTraitRef<'tcx>), Self::Value>>;
|
) -> &RefCell<FxHashMap<(Ty<'tcx>, Option<ty::PolyExistentialTraitRef<'tcx>>), Self::Value>>;
|
||||||
fn check_overflow(&self) -> bool;
|
fn check_overflow(&self) -> bool;
|
||||||
fn instances(&self) -> &RefCell<FxHashMap<Instance<'tcx>, Self::Value>>;
|
fn instances(&self) -> &RefCell<FxHashMap<Instance<'tcx>, Self::Value>>;
|
||||||
fn get_fn(&self, instance: Instance<'tcx>) -> Self::Value;
|
fn get_fn(&self, instance: Instance<'tcx>) -> Self::Value;
|
||||||
|
|
|
@ -42,7 +42,7 @@ pub struct EvalContext<'a, 'mir, 'tcx: 'a + 'mir, M: Machine<'a, 'mir, 'tcx>> {
|
||||||
pub(crate) stack: Vec<Frame<'mir, 'tcx, M::PointerTag, M::FrameExtra>>,
|
pub(crate) stack: Vec<Frame<'mir, 'tcx, M::PointerTag, M::FrameExtra>>,
|
||||||
|
|
||||||
/// A cache for deduplicating vtables
|
/// A cache for deduplicating vtables
|
||||||
pub(super) vtables: FxHashMap<(Ty<'tcx>, ty::PolyExistentialTraitRef<'tcx>), AllocId>,
|
pub(super) vtables: FxHashMap<(Ty<'tcx>, Option<ty::PolyExistentialTraitRef<'tcx>>), AllocId>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A stack frame.
|
/// A stack frame.
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
use rustc_data_structures::sync::Lrc;
|
||||||
use rustc::ty::{self, Ty};
|
use rustc::ty::{self, Ty};
|
||||||
use rustc::ty::layout::{Size, Align, LayoutOf};
|
use rustc::ty::layout::{Size, Align, LayoutOf};
|
||||||
use rustc::mir::interpret::{Scalar, Pointer, EvalResult, PointerArithmetic};
|
use rustc::mir::interpret::{Scalar, Pointer, EvalResult, PointerArithmetic};
|
||||||
|
@ -14,7 +15,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M>
|
||||||
pub fn get_vtable(
|
pub fn get_vtable(
|
||||||
&mut self,
|
&mut self,
|
||||||
ty: Ty<'tcx>,
|
ty: Ty<'tcx>,
|
||||||
poly_trait_ref: ty::PolyExistentialTraitRef<'tcx>,
|
poly_trait_ref: Option<ty::PolyExistentialTraitRef<'tcx>>,
|
||||||
) -> EvalResult<'tcx, Pointer<M::PointerTag>> {
|
) -> EvalResult<'tcx, Pointer<M::PointerTag>> {
|
||||||
trace!("get_vtable(trait_ref={:?})", poly_trait_ref);
|
trace!("get_vtable(trait_ref={:?})", poly_trait_ref);
|
||||||
|
|
||||||
|
@ -24,10 +25,14 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M>
|
||||||
return Ok(Pointer::from(vtable).with_default_tag());
|
return Ok(Pointer::from(vtable).with_default_tag());
|
||||||
}
|
}
|
||||||
|
|
||||||
let trait_ref = poly_trait_ref.with_self_ty(*self.tcx, ty);
|
let methods = if let Some(poly_trait_ref) = poly_trait_ref {
|
||||||
let trait_ref = self.tcx.erase_regions(&trait_ref);
|
let trait_ref = poly_trait_ref.with_self_ty(*self.tcx, ty);
|
||||||
|
let trait_ref = self.tcx.erase_regions(&trait_ref);
|
||||||
|
|
||||||
let methods = self.tcx.vtable_methods(trait_ref);
|
self.tcx.vtable_methods(trait_ref)
|
||||||
|
} else {
|
||||||
|
Lrc::new(Vec::new())
|
||||||
|
};
|
||||||
|
|
||||||
let layout = self.layout_of(ty)?;
|
let layout = self.layout_of(ty)?;
|
||||||
assert!(!layout.is_unsized(), "can't create a vtable for an unsized type");
|
assert!(!layout.is_unsized(), "can't create a vtable for an unsized type");
|
||||||
|
|
|
@ -894,20 +894,23 @@ fn create_mono_items_for_vtable_methods<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||||
!impl_ty.needs_subst() && !impl_ty.has_escaping_bound_vars());
|
!impl_ty.needs_subst() && !impl_ty.has_escaping_bound_vars());
|
||||||
|
|
||||||
if let ty::Dynamic(ref trait_ty, ..) = trait_ty.sty {
|
if let ty::Dynamic(ref trait_ty, ..) = trait_ty.sty {
|
||||||
let poly_trait_ref = trait_ty.principal().with_self_ty(tcx, impl_ty);
|
if let Some(principal) = trait_ty.principal() {
|
||||||
assert!(!poly_trait_ref.has_escaping_bound_vars());
|
let poly_trait_ref = principal.with_self_ty(tcx, impl_ty);
|
||||||
|
assert!(!poly_trait_ref.has_escaping_bound_vars());
|
||||||
|
|
||||||
// Walk all methods of the trait, including those of its supertraits
|
// Walk all methods of the trait, including those of its supertraits
|
||||||
let methods = tcx.vtable_methods(poly_trait_ref);
|
let methods = tcx.vtable_methods(poly_trait_ref);
|
||||||
let methods = methods.iter().cloned().filter_map(|method| method)
|
let methods = methods.iter().cloned().filter_map(|method| method)
|
||||||
.map(|(def_id, substs)| ty::Instance::resolve_for_vtable(
|
.map(|(def_id, substs)| ty::Instance::resolve_for_vtable(
|
||||||
tcx,
|
tcx,
|
||||||
ty::ParamEnv::reveal_all(),
|
ty::ParamEnv::reveal_all(),
|
||||||
def_id,
|
def_id,
|
||||||
substs).unwrap())
|
substs).unwrap())
|
||||||
.filter(|&instance| should_monomorphize_locally(tcx, &instance))
|
.filter(|&instance| should_monomorphize_locally(tcx, &instance))
|
||||||
.map(|instance| create_fn_mono_item(instance));
|
.map(|instance| create_fn_mono_item(instance));
|
||||||
output.extend(methods);
|
output.extend(methods);
|
||||||
|
}
|
||||||
|
|
||||||
// Also add the destructor
|
// Also add the destructor
|
||||||
visit_drop_use(tcx, impl_ty, false, output);
|
visit_drop_use(tcx, impl_ty, false, output);
|
||||||
}
|
}
|
||||||
|
|
|
@ -304,13 +304,16 @@ impl<'a, 'tcx> DefPathBasedNames<'a, 'tcx> {
|
||||||
output.push(']');
|
output.push(']');
|
||||||
},
|
},
|
||||||
ty::Dynamic(ref trait_data, ..) => {
|
ty::Dynamic(ref trait_data, ..) => {
|
||||||
let principal = trait_data.principal();
|
if let Some(principal) = trait_data.principal() {
|
||||||
self.push_def_path(principal.def_id(), output);
|
self.push_def_path(principal.def_id(), output);
|
||||||
self.push_type_params(
|
self.push_type_params(
|
||||||
principal.skip_binder().substs,
|
principal.skip_binder().substs,
|
||||||
trait_data.projection_bounds(),
|
trait_data.projection_bounds(),
|
||||||
output,
|
output,
|
||||||
);
|
);
|
||||||
|
} else {
|
||||||
|
output.push_str("dyn '_");
|
||||||
|
}
|
||||||
},
|
},
|
||||||
ty::Foreign(did) => self.push_def_path(did, output),
|
ty::Foreign(did) => self.push_def_path(did, output),
|
||||||
ty::FnDef(..) |
|
ty::FnDef(..) |
|
||||||
|
|
|
@ -63,7 +63,7 @@ enum PointerKind<'tcx> {
|
||||||
/// No metadata attached, ie pointer to sized type or foreign type
|
/// No metadata attached, ie pointer to sized type or foreign type
|
||||||
Thin,
|
Thin,
|
||||||
/// A trait object
|
/// A trait object
|
||||||
Vtable(DefId),
|
Vtable(Option<DefId>),
|
||||||
/// Slice
|
/// Slice
|
||||||
Length,
|
Length,
|
||||||
/// The unsize info of this projection
|
/// The unsize info of this projection
|
||||||
|
@ -95,7 +95,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||||
Ok(match t.sty {
|
Ok(match t.sty {
|
||||||
ty::Slice(_) | ty::Str => Some(PointerKind::Length),
|
ty::Slice(_) | ty::Str => Some(PointerKind::Length),
|
||||||
ty::Dynamic(ref tty, ..) =>
|
ty::Dynamic(ref tty, ..) =>
|
||||||
Some(PointerKind::Vtable(tty.principal().def_id())),
|
Some(PointerKind::Vtable(tty.principal_def_id())),
|
||||||
ty::Adt(def, substs) if def.is_struct() => {
|
ty::Adt(def, substs) if def.is_struct() => {
|
||||||
match def.non_enum_variant().fields.last() {
|
match def.non_enum_variant().fields.last() {
|
||||||
None => Some(PointerKind::Thin),
|
None => Some(PointerKind::Thin),
|
||||||
|
|
|
@ -190,7 +190,9 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||||
self.deduce_sig_from_projection(None, &pb)
|
self.deduce_sig_from_projection(None, &pb)
|
||||||
})
|
})
|
||||||
.next();
|
.next();
|
||||||
let kind = self.tcx.lang_items().fn_trait_kind(object_type.principal().def_id());
|
let kind = object_type.principal_def_id().and_then(|did| {
|
||||||
|
self.tcx.lang_items().fn_trait_kind(did)
|
||||||
|
});
|
||||||
(sig, kind)
|
(sig, kind)
|
||||||
}
|
}
|
||||||
ty::Infer(ty::TyVar(vid)) => self.deduce_expectations_from_obligations(vid),
|
ty::Infer(ty::TyVar(vid)) => self.deduce_expectations_from_obligations(vid),
|
||||||
|
|
|
@ -280,7 +280,11 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> {
|
||||||
.include_raw_pointers()
|
.include_raw_pointers()
|
||||||
.filter_map(|(ty, _)|
|
.filter_map(|(ty, _)|
|
||||||
match ty.sty {
|
match ty.sty {
|
||||||
ty::Dynamic(ref data, ..) => Some(closure(self, ty, data.principal())),
|
ty::Dynamic(ref data, ..) => {
|
||||||
|
Some(closure(self, ty, data.principal().unwrap_or_else(|| {
|
||||||
|
span_bug!(self.span, "calling trait method on empty object?")
|
||||||
|
})))
|
||||||
|
},
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
|
@ -505,17 +505,18 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
|
||||||
|
|
||||||
match self_ty.value.value.sty {
|
match self_ty.value.value.sty {
|
||||||
ty::Dynamic(ref data, ..) => {
|
ty::Dynamic(ref data, ..) => {
|
||||||
let p = data.principal();
|
if let Some(p) = data.principal() {
|
||||||
self.fcx.probe(|_| {
|
self.fcx.probe(|_| {
|
||||||
let InferOk { value: self_ty, obligations: _ } =
|
let InferOk { value: self_ty, obligations: _ } =
|
||||||
self.fcx.probe_instantiate_query_response(
|
self.fcx.probe_instantiate_query_response(
|
||||||
self.span, &self.orig_steps_var_values, self_ty)
|
self.span, &self.orig_steps_var_values, self_ty)
|
||||||
.unwrap_or_else(|_| {
|
.unwrap_or_else(|_| {
|
||||||
span_bug!(self.span, "{:?} was applicable but now isn't?", self_ty)
|
span_bug!(self.span, "{:?} was applicable but now isn't?", self_ty)
|
||||||
});
|
});
|
||||||
self.assemble_inherent_candidates_from_object(self_ty);
|
self.assemble_inherent_candidates_from_object(self_ty);
|
||||||
});
|
});
|
||||||
self.assemble_inherent_impl_candidates_for_type(p.def_id());
|
self.assemble_inherent_impl_candidates_for_type(p.def_id());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
ty::Adt(def, _) => {
|
ty::Adt(def, _) => {
|
||||||
self.assemble_inherent_impl_candidates_for_type(def.did);
|
self.assemble_inherent_impl_candidates_for_type(def.did);
|
||||||
|
@ -680,10 +681,12 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
|
||||||
self_ty);
|
self_ty);
|
||||||
|
|
||||||
let principal = match self_ty.sty {
|
let principal = match self_ty.sty {
|
||||||
ty::Dynamic(ref data, ..) => data.principal(),
|
ty::Dynamic(ref data, ..) => Some(data),
|
||||||
_ => span_bug!(self.span, "non-object {:?} in assemble_inherent_candidates_from_object",
|
_ => None
|
||||||
self_ty)
|
}.and_then(|data| data.principal()).unwrap_or_else(|| {
|
||||||
};
|
span_bug!(self.span, "non-object {:?} in assemble_inherent_candidates_from_object",
|
||||||
|
self_ty)
|
||||||
|
});
|
||||||
|
|
||||||
// It is illegal to invoke a method on a trait instance that
|
// It is illegal to invoke a method on a trait instance that
|
||||||
// refers to the `Self` type. An error will be reported by
|
// refers to the `Self` type. An error will be reported by
|
||||||
|
|
|
@ -651,7 +651,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||||
ty::Adt(def, _) => def.did.is_local(),
|
ty::Adt(def, _) => def.did.is_local(),
|
||||||
ty::Foreign(did) => did.is_local(),
|
ty::Foreign(did) => did.is_local(),
|
||||||
|
|
||||||
ty::Dynamic(ref tr, ..) => tr.principal().def_id().is_local(),
|
ty::Dynamic(ref tr, ..) =>
|
||||||
|
tr.principal().map(|d| d.def_id().is_local()).unwrap_or(false),
|
||||||
|
|
||||||
ty::Param(_) => true,
|
ty::Param(_) => true,
|
||||||
|
|
||||||
|
|
|
@ -95,8 +95,8 @@ impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for InherentCollect<'a, 'tcx> {
|
||||||
ty::Foreign(did) => {
|
ty::Foreign(did) => {
|
||||||
self.check_def_id(item, did);
|
self.check_def_id(item, did);
|
||||||
}
|
}
|
||||||
ty::Dynamic(ref data, ..) => {
|
ty::Dynamic(ref data, ..) if data.principal_def_id().is_some() => {
|
||||||
self.check_def_id(item, data.principal().def_id());
|
self.check_def_id(item, data.principal_def_id().unwrap());
|
||||||
}
|
}
|
||||||
ty::Char => {
|
ty::Char => {
|
||||||
self.check_primitive_impl(def_id,
|
self.check_primitive_impl(def_id,
|
||||||
|
|
|
@ -171,25 +171,28 @@ fn check_impl_overlap<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, node_id: ast::NodeI
|
||||||
// This is something like impl Trait1 for Trait2. Illegal
|
// This is something like impl Trait1 for Trait2. Illegal
|
||||||
// if Trait1 is a supertrait of Trait2 or Trait2 is not object safe.
|
// if Trait1 is a supertrait of Trait2 or Trait2 is not object safe.
|
||||||
|
|
||||||
if !tcx.is_object_safe(data.principal().def_id()) {
|
if let Some(principal_def_id) = data.principal_def_id() {
|
||||||
// This is an error, but it will be reported by wfcheck. Ignore it here.
|
if !tcx.is_object_safe(principal_def_id) {
|
||||||
// This is tested by `coherence-impl-trait-for-trait-object-safe.rs`.
|
// This is an error, but it will be reported by wfcheck. Ignore it here.
|
||||||
} else {
|
// This is tested by `coherence-impl-trait-for-trait-object-safe.rs`.
|
||||||
let mut supertrait_def_ids =
|
} else {
|
||||||
traits::supertrait_def_ids(tcx, data.principal().def_id());
|
let mut supertrait_def_ids =
|
||||||
if supertrait_def_ids.any(|d| d == trait_def_id) {
|
traits::supertrait_def_ids(tcx, principal_def_id);
|
||||||
let sp = tcx.sess.source_map().def_span(tcx.span_of_impl(impl_def_id).unwrap());
|
if supertrait_def_ids.any(|d| d == trait_def_id) {
|
||||||
struct_span_err!(tcx.sess,
|
let sp = tcx.sess.source_map().def_span(tcx.span_of_impl(impl_def_id).unwrap());
|
||||||
sp,
|
struct_span_err!(tcx.sess,
|
||||||
E0371,
|
sp,
|
||||||
"the object type `{}` automatically implements the trait `{}`",
|
E0371,
|
||||||
trait_ref.self_ty(),
|
"the object type `{}` automatically implements the trait `{}`",
|
||||||
tcx.item_path_str(trait_def_id))
|
trait_ref.self_ty(),
|
||||||
.span_label(sp, format!("`{}` automatically implements trait `{}`",
|
tcx.item_path_str(trait_def_id))
|
||||||
trait_ref.self_ty(),
|
.span_label(sp, format!("`{}` automatically implements trait `{}`",
|
||||||
tcx.item_path_str(trait_def_id)))
|
trait_ref.self_ty(),
|
||||||
.emit();
|
tcx.item_path_str(trait_def_id)))
|
||||||
|
.emit();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// FIXME: also check auto-trait def-ids? (e.g. `impl Sync for Foo+Sync`)?
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -194,27 +194,28 @@ fn insert_required_predicates_to_be_wf<'tcx>(
|
||||||
debug!("Dynamic");
|
debug!("Dynamic");
|
||||||
debug!("field_ty = {}", &field_ty);
|
debug!("field_ty = {}", &field_ty);
|
||||||
debug!("ty in field = {}", &ty);
|
debug!("ty in field = {}", &ty);
|
||||||
let ex_trait_ref = obj.principal();
|
if let Some(ex_trait_ref) = obj.principal() {
|
||||||
// Here, we are passing the type `usize` as a
|
// Here, we are passing the type `usize` as a
|
||||||
// placeholder value with the function
|
// placeholder value with the function
|
||||||
// `with_self_ty`, since there is no concrete type
|
// `with_self_ty`, since there is no concrete type
|
||||||
// `Self` for a `dyn Trait` at this
|
// `Self` for a `dyn Trait` at this
|
||||||
// stage. Therefore when checking explicit
|
// stage. Therefore when checking explicit
|
||||||
// predicates in `check_explicit_predicates` we
|
// predicates in `check_explicit_predicates` we
|
||||||
// need to ignore checking the explicit_map for
|
// need to ignore checking the explicit_map for
|
||||||
// Self type.
|
// Self type.
|
||||||
let substs = ex_trait_ref
|
let substs = ex_trait_ref
|
||||||
.with_self_ty(tcx, tcx.types.usize)
|
.with_self_ty(tcx, tcx.types.usize)
|
||||||
.skip_binder()
|
.skip_binder()
|
||||||
.substs;
|
.substs;
|
||||||
check_explicit_predicates(
|
check_explicit_predicates(
|
||||||
tcx,
|
tcx,
|
||||||
&ex_trait_ref.skip_binder().def_id,
|
&ex_trait_ref.skip_binder().def_id,
|
||||||
substs,
|
substs,
|
||||||
required_predicates,
|
required_predicates,
|
||||||
explicit_map,
|
explicit_map,
|
||||||
IgnoreSelfTy(true),
|
IgnoreSelfTy(true),
|
||||||
);
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ty::Projection(obj) => {
|
ty::Projection(obj) => {
|
||||||
|
|
|
@ -301,11 +301,12 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
|
||||||
let contra = self.contravariant(variance);
|
let contra = self.contravariant(variance);
|
||||||
self.add_constraints_from_region(current, r, contra);
|
self.add_constraints_from_region(current, r, contra);
|
||||||
|
|
||||||
let poly_trait_ref = data
|
if let Some(poly_trait_ref) = data.principal() {
|
||||||
.principal()
|
let poly_trait_ref =
|
||||||
.with_self_ty(self.tcx(), self.tcx().types.err);
|
poly_trait_ref.with_self_ty(self.tcx(), self.tcx().types.err);
|
||||||
self.add_constraints_from_trait_ref(
|
self.add_constraints_from_trait_ref(
|
||||||
current, *poly_trait_ref.skip_binder(), variance);
|
current, *poly_trait_ref.skip_binder(), variance);
|
||||||
|
}
|
||||||
|
|
||||||
for projection in data.projection_bounds() {
|
for projection in data.projection_bounds() {
|
||||||
self.add_constraints_from_ty(
|
self.add_constraints_from_ty(
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue