Privatize TraitObject.principal and add a method accessor, returning Option.

This commit is contained in:
Mark-Simulacrum 2016-11-12 15:46:16 -07:00
parent 0b399e5e99
commit 46c7a117f8
29 changed files with 141 additions and 102 deletions

View File

@ -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::TyTrait(ref data) => {
data.principal().map_or(false, |p| tcx.has_attr(p.def_id(), "fundamental"))
}
_ => false
}
}
@ -273,7 +271,7 @@ fn ty_is_local_constructor(tcx: TyCtxt, ty: Ty, infer_is_local: InferIsLocal)->
}
ty::TyTrait(ref tt) => {
tt.principal.def_id().is_local()
tt.principal().map_or(false, |p| p.def_id().is_local())
}
ty::TyError => {

View File

@ -1528,7 +1528,10 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
_ => {}
}
data.principal.with_self_ty(this.tcx(), self_ty)
match data.principal() {
Some(ref p) => p.with_self_ty(this.tcx(), self_ty),
None => return,
}
}
ty::TyInfer(ty::TyVar(_)) => {
debug!("assemble_candidates_from_object_ty: ambiguous");
@ -1611,8 +1614,11 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
//
// We always upcast when we can because of reason
// #2 (region bounds).
data_a.principal.def_id() == data_b.principal.def_id() &&
data_a.builtin_bounds.is_superset(&data_b.builtin_bounds)
match (data_a.principal(), data_b.principal()) {
(Some(ref a), Some(ref b)) => a.def_id() == b.def_id() &&
data_a.builtin_bounds.is_superset(&data_b.builtin_bounds),
_ => false
}
}
// T -> Trait.
@ -2167,7 +2173,8 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
match self_ty.sty {
ty::TyTrait(ref data) => {
// OK to skip the binder, it is reintroduced below
let input_types = data.principal.input_types();
let principal = data.principal().unwrap();
let input_types = principal.input_types();
let assoc_types = data.projection_bounds.iter()
.map(|pb| pb.skip_binder().ty);
let all_types: Vec<_> = input_types.chain(assoc_types)
@ -2301,7 +2308,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
let self_ty = self.infcx.shallow_resolve(*obligation.self_ty().skip_binder());
let poly_trait_ref = match self_ty.sty {
ty::TyTrait(ref data) => {
data.principal.with_self_ty(self.tcx(), self_ty)
data.principal().unwrap().with_self_ty(self.tcx(), self_ty)
}
_ => {
span_bug!(obligation.cause.span,
@ -2471,12 +2478,13 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
// Trait+Kx+'a -> Trait+Ky+'b (upcasts).
(&ty::TyTrait(ref data_a), &ty::TyTrait(ref data_b)) => {
// See assemble_candidates_for_unsizing for more info.
let new_trait = tcx.mk_trait(ty::TraitObject {
principal: data_a.principal,
region_bound: data_b.region_bound,
builtin_bounds: data_b.builtin_bounds,
projection_bounds: data_a.projection_bounds.clone(),
});
let new_trait = tcx.mk_trait(ty::TraitObject::new(
data_a.principal(),
data_b.region_bound,
data_b.builtin_bounds,
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)?;
@ -2499,7 +2507,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
data.builtin_bounds.iter().flat_map(|bound| {
tcx.lang_items.from_builtin_kind(bound).ok()
})
.chain(Some(data.principal.def_id()));
.chain(data.principal().map(|ref p| p.def_id()));
if let Some(did) = object_dids.find(|did| {
!tcx.is_object_safe(*did)
}) {
@ -2516,7 +2524,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
};
// Create the obligation for casting from T to Trait.
push(data.principal.with_self_ty(tcx, source).to_predicate());
push(data.principal().unwrap().with_self_ty(tcx, source).to_predicate());
// We can only make objects from sized types.
let mut builtin_bounds = data.builtin_bounds;

View File

@ -215,7 +215,8 @@ impl<'a, 'gcx, 'lcx, 'tcx> ty::TyS<'tcx> {
ty::TyFnDef(..) => format!("fn item"),
ty::TyFnPtr(_) => "fn pointer".to_string(),
ty::TyTrait(ref inner) => {
format!("trait {}", tcx.item_path_str(inner.principal.def_id()))
inner.principal().map_or_else(|| "trait".to_string(),
|p| format!("trait {}", tcx.item_path_str(p.def_id())))
}
ty::TyClosure(..) => "closure".to_string(),
ty::TyTuple(_) => "tuple".to_string(),

View File

@ -60,7 +60,7 @@ pub fn simplify_type<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
ty::TyArray(..) | ty::TySlice(_) => Some(ArraySimplifiedType),
ty::TyRawPtr(_) => Some(PtrSimplifiedType),
ty::TyTrait(ref trait_info) => {
Some(TraitSimplifiedType(trait_info.principal.def_id()))
trait_info.principal().map(|p| TraitSimplifiedType(p.def_id()))
}
ty::TyRef(_, mt) => {
// since we introduce auto-refs during method lookup, we

View File

@ -123,7 +123,7 @@ impl FlagComputation {
&ty::TyTrait(ref obj) => {
let mut computation = FlagComputation::new();
computation.add_substs(obj.principal.skip_binder().substs);
computation.add_substs(obj.principal().unwrap().skip_binder().substs);
for projection_bound in &obj.projection_bounds {
let mut proj_computation = FlagComputation::new();
proj_computation.add_existential_projection(&projection_bound.0);

View File

@ -316,7 +316,7 @@ pub fn characteristic_def_id_of_type(ty: Ty) -> Option<DefId> {
match ty.sty {
ty::TyAdt(adt_def, _) => Some(adt_def.did),
ty::TyTrait(ref data) => Some(data.principal.def_id()),
ty::TyTrait(ref data) => data.principal().map(|ref p| p.def_id()),
ty::TyArray(subty, _) |
ty::TySlice(subty) |

View File

@ -417,7 +417,11 @@ pub fn super_relate_tys<'a, 'gcx, 'tcx, R>(relation: &mut R,
(&ty::TyTrait(ref a_obj), &ty::TyTrait(ref b_obj)) =>
{
let principal = relation.relate(&a_obj.principal, &b_obj.principal)?;
let principal = match (a_obj.principal(), b_obj.principal()) {
(Some(ref a_p), Some(ref b_p)) => Some(relation.relate(a_p, b_p)?),
(None, None) => None,
_ => return Err(TypeError::Sorts(expected_found(relation, &a, &b))),
};
let r =
relation.with_cause(
Cause::ExistentialRegionBound,
@ -426,12 +430,7 @@ pub fn super_relate_tys<'a, 'gcx, 'tcx, R>(relation: &mut R,
&b_obj.region_bound))?;
let nb = relation.relate(&a_obj.builtin_bounds, &b_obj.builtin_bounds)?;
let pb = relation.relate(&a_obj.projection_bounds, &b_obj.projection_bounds)?;
Ok(tcx.mk_trait(ty::TraitObject {
principal: principal,
region_bound: r,
builtin_bounds: nb,
projection_bounds: pb
}))
Ok(tcx.mk_trait(ty::TraitObject::new(principal, r, nb, pb)))
}
(&ty::TyClosure(a_id, a_substs),

View File

@ -429,16 +429,16 @@ impl<'tcx, T:TypeFoldable<'tcx>> TypeFoldable<'tcx> for ty::Binder<T> {
impl<'tcx> TypeFoldable<'tcx> for ty::TraitObject<'tcx> {
fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self {
ty::TraitObject {
principal: self.principal.fold_with(folder),
region_bound: self.region_bound.fold_with(folder),
builtin_bounds: self.builtin_bounds,
projection_bounds: self.projection_bounds.fold_with(folder),
}
ty::TraitObject::new(
self.principal().map(|p| p.fold_with(folder)),
self.region_bound.fold_with(folder),
self.builtin_bounds,
self.projection_bounds.fold_with(folder),
)
}
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
self.principal.visit_with(visitor) ||
self.principal().map(|p| p.visit_with(visitor)).unwrap_or(true) ||
self.region_bound.visit_with(visitor) ||
self.projection_bounds.visit_with(visitor)
}

View File

@ -277,12 +277,29 @@ impl<'a, 'gcx, 'acx, 'tcx> ClosureSubsts<'tcx> {
#[derive(Clone, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)]
pub struct TraitObject<'tcx> {
pub principal: PolyExistentialTraitRef<'tcx>,
principal: Option<PolyExistentialTraitRef<'tcx>>,
pub region_bound: &'tcx ty::Region,
pub builtin_bounds: BuiltinBounds,
pub projection_bounds: Vec<PolyExistentialProjection<'tcx>>,
}
impl<'tcx> TraitObject<'tcx> {
pub fn new(principal: Option<PolyExistentialTraitRef<'tcx>>, region_bound: &'tcx ty::Region,
builtin_bounds: BuiltinBounds, projection_bounds: Vec<PolyExistentialProjection<'tcx>>)
-> Self {
TraitObject {
principal: principal,
region_bound: region_bound,
builtin_bounds: builtin_bounds,
projection_bounds: projection_bounds,
}
}
pub fn principal(&self) -> Option<PolyExistentialTraitRef<'tcx>> {
self.principal
}
}
/// A complete reference to a trait. These take numerous guises in syntax,
/// but perhaps the most recognizable form is in a where clause:
///
@ -1221,7 +1238,7 @@ impl<'a, 'gcx, 'tcx> TyS<'tcx> {
pub fn ty_to_def_id(&self) -> Option<DefId> {
match self.sty {
TyTrait(ref tt) => Some(tt.principal.def_id()),
TyTrait(ref tt) => tt.principal().map(|p| p.def_id()),
TyAdt(def, _) => Some(def.did),
TyClosure(id, _) => Some(id),
_ => None
@ -1245,7 +1262,7 @@ impl<'a, 'gcx, 'tcx> TyS<'tcx> {
}
TyTrait(ref obj) => {
let mut v = vec![obj.region_bound];
v.extend(obj.principal.skip_binder().substs.regions());
v.extend(obj.principal().unwrap().skip_binder().substs.regions());
v
}
TyAdt(_, substs) | TyAnon(_, substs) => {

View File

@ -532,7 +532,9 @@ impl<'a, 'gcx, 'tcx, H: Hasher> TypeVisitor<'tcx> for TypeIdHasher<'a, 'gcx, 'tc
self.hash(f.sig.inputs().skip_binder().len());
}
TyTrait(ref data) => {
self.def_id(data.principal.def_id());
if let Some(ref p) = data.principal() {
self.def_id(p.def_id());
}
self.hash(data.builtin_bounds);
}
TyTuple(tys) => {

View File

@ -93,7 +93,10 @@ fn push_subtypes<'tcx>(stack: &mut TypeWalkerStack<'tcx>, parent_ty: Ty<'tcx>) {
stack.extend(data.trait_ref.substs.types().rev());
}
ty::TyTrait(ref obj) => {
stack.extend(obj.principal.input_types().rev());
match obj.principal() {
Some(ref p) => stack.extend(p.input_types().rev()),
None => {}
}
stack.extend(obj.projection_bounds.iter().map(|pred| {
pred.0.ty
}).rev());

View File

@ -394,7 +394,7 @@ impl<'a, 'gcx, 'tcx> WfPredicates<'a, 'gcx, 'tcx> {
data.builtin_bounds.iter().flat_map(|bound| {
tcx.lang_items.from_builtin_kind(bound).ok()
})
.chain(Some(data.principal.def_id()));
.chain(data.principal().map(|ref p| p.def_id()));
self.out.extend(
component_traits.map(|did| { traits::Obligation::new(
cause.clone(),
@ -492,7 +492,7 @@ impl<'a, 'gcx, 'tcx> WfPredicates<'a, 'gcx, 'tcx> {
if !data.has_escaping_regions() {
let implicit_bounds =
object_region_bounds(self.infcx.tcx,
data.principal,
data.principal().unwrap(),
data.builtin_bounds);
let explicit_bound = data.region_bound;

View File

@ -339,7 +339,7 @@ impl<'tcx> fmt::Display for ty::TraitObject<'tcx> {
// Use a type that can't appear in defaults of type parameters.
let dummy_self = tcx.mk_infer(ty::FreshTy(0));
let principal = tcx.lift(&self.principal)
let principal = self.principal().and_then(|ref p| tcx.lift(p))
.expect("could not lift TraitRef for printing")
.with_self_ty(tcx, dummy_self).0;
let projections = self.projection_bounds.iter().map(|p| {
@ -466,7 +466,7 @@ impl<'tcx> fmt::Debug for ty::TraitObject<'tcx> {
};
maybe_continue(f)?;
write!(f, "{:?}", self.principal)?;
write!(f, "{:?}", self.principal())?;
let region_str = format!("{:?}", self.region_bound);
if !region_str.is_empty() {

View File

@ -302,7 +302,7 @@ pub fn unsized_info<'ccx, 'tcx>(ccx: &CrateContext<'ccx, 'tcx>,
old_info.expect("unsized_info: missing old info for trait upcast")
}
(_, &ty::TyTrait(ref data)) => {
let trait_ref = data.principal.with_self_ty(ccx.tcx(), source);
let trait_ref = data.principal().unwrap().with_self_ty(ccx.tcx(), source);
let trait_ref = ccx.tcx().erase_regions(&trait_ref);
consts::ptrcast(meth::get_vtable(ccx, trait_ref),
Type::vtable_ptr(ccx))

View File

@ -1004,7 +1004,7 @@ fn create_trans_items_for_vtable_methods<'a, 'tcx>(scx: &SharedCrateContext<'a,
assert!(!trait_ty.needs_subst() && !impl_ty.needs_subst());
if let ty::TyTrait(ref trait_ty) = trait_ty.sty {
let poly_trait_ref = trait_ty.principal.with_self_ty(scx.tcx(), impl_ty);
let poly_trait_ref = trait_ty.principal().unwrap().with_self_ty(scx.tcx(), impl_ty);
let param_substs = scx.tcx().intern_substs(&[]);
// Walk all methods of the trait, including those of its supertraits

View File

@ -431,8 +431,13 @@ fn trait_pointer_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
// type is assigned the correct name, size, namespace, and source location.
// But it does not describe the trait's methods.
let def_id = match trait_type.sty {
ty::TyTrait(ref data) => data.principal.def_id(),
let containing_scope = match trait_type.sty {
ty::TyTrait(ref data) => if let Some(principal) = data.principal() {
let def_id = principal.def_id();
get_namespace_and_span_for_item(cx, def_id).0
} else {
NO_SCOPE_METADATA
},
_ => {
bug!("debuginfo: Unexpected trait-object type in \
trait_pointer_metadata(): {:?}",
@ -444,8 +449,6 @@ fn trait_pointer_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
let trait_type_name =
compute_debuginfo_type_name(cx, trait_object_type, false);
let (containing_scope, _) = get_namespace_and_span_for_item(cx, def_id);
let trait_llvm_type = type_of::type_of(cx, trait_object_type);
let file_metadata = unknown_file_metadata(cx);

View File

@ -94,10 +94,12 @@ pub fn push_debuginfo_type_name<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
output.push(']');
},
ty::TyTrait(ref trait_data) => {
if let Some(principal) = trait_data.principal() {
let principal = cx.tcx().erase_late_bound_regions_and_normalize(
&trait_data.principal);
&principal);
push_item_name(cx, principal.def_id, false, output);
push_type_params(cx, principal.substs, output);
}
},
ty::TyFnDef(.., &ty::BareFnTy{ unsafety, abi, ref sig } ) |
ty::TyFnPtr(&ty::BareFnTy{ unsafety, abi, ref sig } ) => {

View File

@ -458,10 +458,12 @@ impl<'a, 'tcx> DefPathBasedNames<'a, 'tcx> {
output.push(']');
},
ty::TyTrait(ref trait_data) => {
self.push_def_path(trait_data.principal.def_id(), output);
self.push_type_params(trait_data.principal.skip_binder().substs,
if let Some(principal) = trait_data.principal() {
self.push_def_path(principal.def_id(), output);
self.push_type_params(principal.skip_binder().substs,
&trait_data.projection_bounds,
output);
}
},
ty::TyFnDef(.., &ty::BareFnTy{ unsafety, abi, ref sig } ) |
ty::TyFnPtr(&ty::BareFnTy{ unsafety, abi, ref sig } ) => {

View File

@ -1135,12 +1135,12 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
.emit();
}
let ty = tcx.mk_trait(ty::TraitObject {
principal: existential_principal,
region_bound: region_bound,
builtin_bounds: builtin_bounds,
projection_bounds: existential_projections
});
let ty = tcx.mk_trait(ty::TraitObject::new(
Some(existential_principal),
region_bound,
builtin_bounds,
existential_projections
));
debug!("trait_object_type: {:?}", ty);
ty
}

View File

@ -78,7 +78,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
fn unsize_kind(&self, t: Ty<'tcx>) -> Option<UnsizeKind<'tcx>> {
match t.sty {
ty::TySlice(_) | ty::TyStr => Some(UnsizeKind::Length),
ty::TyTrait(ref tty) => Some(UnsizeKind::Vtable(tty.principal.def_id())),
ty::TyTrait(ref tty) => Some(UnsizeKind::Vtable(tty.principal().unwrap().def_id())),
ty::TyAdt(def, substs) if def.is_struct() => {
// FIXME(arielb1): do some kind of normalization
match def.struct_variant().fields.last() {

View File

@ -119,7 +119,7 @@ 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.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),

View File

@ -255,7 +255,7 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> {
.autoderef(self.span, self_ty)
.filter_map(|(ty, _)| {
match ty.sty {
ty::TyTrait(ref data) => Some(closure(self, ty, data.principal)),
ty::TyTrait(ref data) => data.principal().map(|p| closure(self, ty, p)),
_ => None,
}
})

View File

@ -296,8 +296,8 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
match self_ty.sty {
ty::TyTrait(box ref data) => {
self.assemble_inherent_candidates_from_object(self_ty, data.principal);
self.assemble_inherent_impl_candidates_for_type(data.principal.def_id());
self.assemble_inherent_candidates_from_object(self_ty, data.principal().unwrap());
self.assemble_inherent_impl_candidates_for_type(data.principal().unwrap().def_id());
}
ty::TyAdt(def, _) => {
self.assemble_inherent_impl_candidates_for_type(def.did);

View File

@ -379,7 +379,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
match ty.sty {
ty::TyAdt(def, _) => def.did.is_local(),
ty::TyTrait(ref tr) => tr.principal.def_id().is_local(),
ty::TyTrait(ref tr) => tr.principal().map(|p| p.def_id().is_local()).unwrap_or(false),
ty::TyParam(_) => true,

View File

@ -68,7 +68,7 @@ impl<'a, 'gcx, 'tcx> CoherenceChecker<'a, 'gcx, 'tcx> {
match ty.sty {
TyAdt(def, _) => Some(def.did),
TyTrait(ref t) => Some(t.principal.def_id()),
TyTrait(ref t) => t.principal().map(|p| p.def_id()),
TyBox(_) => self.inference_context.tcx.lang_items.owned_box(),

View File

@ -86,8 +86,8 @@ impl<'cx, 'tcx> OrphanChecker<'cx, 'tcx> {
ty::TyAdt(def, _) => {
self.check_def_id(item, def.did);
}
ty::TyTrait(ref data) => {
self.check_def_id(item, data.principal.def_id());
ty::TyTrait(ref data) if data.principal().is_some() => {
self.check_def_id(item, data.principal().unwrap().def_id());
}
ty::TyBox(..) => {
match self.tcx.lang_items.require_owned_box() {

View File

@ -182,14 +182,14 @@ 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 !self.tcx.is_object_safe(data.principal.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.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,

View File

@ -376,7 +376,7 @@ 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.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 {

View File

@ -1877,7 +1877,8 @@ impl<'tcx> Clean<Type> for ty::Ty<'tcx> {
}
}
ty::TyTrait(ref obj) => {
let did = obj.principal.def_id();
if let Some(principal) = obj.principal() {
let did = principal.def_id();
inline::record_extern_fqn(cx, did, TypeKind::Trait);
let mut typarams = vec![];
@ -1902,6 +1903,9 @@ impl<'tcx> Clean<Type> for ty::Ty<'tcx> {
did: did,
is_generic: false,
}
} else {
Never
}
}
ty::TyTuple(ref t) => Tuple(t.clean(cx)),