Plumb dyn trait representation through ty::Dynamic
This commit is contained in:
parent
eff35e59c6
commit
6c01273a15
29 changed files with 110 additions and 57 deletions
|
@ -69,7 +69,7 @@ impl<'a, 'tcx> VirtualIndex {
|
||||||
fn expect_dyn_trait_in_self<'tcx>(ty: Ty<'tcx>) -> ty::PolyExistentialTraitRef<'tcx> {
|
fn expect_dyn_trait_in_self<'tcx>(ty: Ty<'tcx>) -> ty::PolyExistentialTraitRef<'tcx> {
|
||||||
for arg in ty.peel_refs().walk() {
|
for arg in ty.peel_refs().walk() {
|
||||||
if let GenericArgKind::Type(ty) = arg.unpack() {
|
if let GenericArgKind::Type(ty) = arg.unpack() {
|
||||||
if let ty::Dynamic(data, _) = ty.kind() {
|
if let ty::Dynamic(data, _, _) = ty.kind() {
|
||||||
return data.principal().expect("expected principal trait object");
|
return data.principal().expect("expected principal trait object");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -312,7 +312,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
||||||
let new_vptr = self.get_vtable_ptr(ty, data_b.principal())?;
|
let new_vptr = self.get_vtable_ptr(ty, data_b.principal())?;
|
||||||
self.write_immediate(Immediate::new_dyn_trait(old_data, new_vptr, self), dest)
|
self.write_immediate(Immediate::new_dyn_trait(old_data, new_vptr, self), dest)
|
||||||
}
|
}
|
||||||
(_, &ty::Dynamic(ref data, _)) => {
|
(_, &ty::Dynamic(ref data, _, _repr)) => {
|
||||||
// Initial cast from sized to dyn trait
|
// Initial cast from sized to dyn trait
|
||||||
let vtable = self.get_vtable_ptr(src_pointee_ty, data.principal())?;
|
let vtable = self.get_vtable_ptr(src_pointee_ty, data.principal())?;
|
||||||
let ptr = self.read_scalar(src)?;
|
let ptr = self.read_scalar(src)?;
|
||||||
|
|
|
@ -95,7 +95,7 @@ pub(crate) fn eval_nullary_intrinsic<'tcx>(
|
||||||
| ty::Ref(_, _, _)
|
| ty::Ref(_, _, _)
|
||||||
| ty::FnDef(_, _)
|
| ty::FnDef(_, _)
|
||||||
| ty::FnPtr(_)
|
| ty::FnPtr(_)
|
||||||
| ty::Dynamic(_, _)
|
| ty::Dynamic(_, _, _)
|
||||||
| ty::Closure(_, _)
|
| ty::Closure(_, _)
|
||||||
| ty::Generator(_, _, _)
|
| ty::Generator(_, _, _)
|
||||||
| ty::GeneratorWitness(_)
|
| ty::GeneratorWitness(_)
|
||||||
|
|
|
@ -48,7 +48,7 @@ impl<'tcx> Printer<'tcx> for AbsolutePathPrinter<'tcx> {
|
||||||
| ty::FnPtr(_)
|
| ty::FnPtr(_)
|
||||||
| ty::Never
|
| ty::Never
|
||||||
| ty::Tuple(_)
|
| ty::Tuple(_)
|
||||||
| ty::Dynamic(_, _) => self.pretty_print_type(ty),
|
| ty::Dynamic(_, _, _) => self.pretty_print_type(ty),
|
||||||
|
|
||||||
// Placeholders (all printed as `_` to uniformize them).
|
// Placeholders (all printed as `_` to uniformize them).
|
||||||
ty::Param(_) | ty::Bound(..) | ty::Placeholder(_) | ty::Infer(_) | ty::Error(_) => {
|
ty::Param(_) | ty::Bound(..) | ty::Placeholder(_) | ty::Infer(_) | ty::Error(_) => {
|
||||||
|
|
|
@ -544,7 +544,7 @@ pub struct TraitObjectVisitor(pub FxHashSet<DefId>);
|
||||||
impl<'tcx> TypeVisitor<'tcx> for TraitObjectVisitor {
|
impl<'tcx> TypeVisitor<'tcx> for TraitObjectVisitor {
|
||||||
fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
|
fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
|
||||||
match t.kind() {
|
match t.kind() {
|
||||||
ty::Dynamic(preds, re) if re.is_static() => {
|
ty::Dynamic(preds, re, _) if re.is_static() => {
|
||||||
if let Some(def_id) = preds.principal_def_id() {
|
if let Some(def_id) = preds.principal_def_id() {
|
||||||
self.0.insert(def_id);
|
self.0.insert(def_id);
|
||||||
}
|
}
|
||||||
|
|
|
@ -222,7 +222,7 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults {
|
||||||
}
|
}
|
||||||
has_emitted
|
has_emitted
|
||||||
}
|
}
|
||||||
ty::Dynamic(binder, _) => {
|
ty::Dynamic(binder, _, _) => {
|
||||||
let mut has_emitted = false;
|
let mut has_emitted = false;
|
||||||
for predicate in binder.iter() {
|
for predicate in binder.iter() {
|
||||||
if let ty::ExistentialPredicate::Trait(ref trait_ref) =
|
if let ty::ExistentialPredicate::Trait(ref trait_ref) =
|
||||||
|
|
|
@ -63,7 +63,9 @@ use rustc_span::{Span, DUMMY_SP};
|
||||||
use rustc_target::abi::{Layout, LayoutS, TargetDataLayout, VariantIdx};
|
use rustc_target::abi::{Layout, LayoutS, TargetDataLayout, VariantIdx};
|
||||||
use rustc_target::spec::abi;
|
use rustc_target::spec::abi;
|
||||||
use rustc_type_ir::sty::TyKind::*;
|
use rustc_type_ir::sty::TyKind::*;
|
||||||
use rustc_type_ir::{InternAs, InternIteratorElement, Interner, TypeFlags};
|
use rustc_type_ir::{
|
||||||
|
InternAs, InternIteratorElement, Interner, TraitObjectRepresentation, TypeFlags,
|
||||||
|
};
|
||||||
|
|
||||||
use std::any::Any;
|
use std::any::Any;
|
||||||
use std::borrow::Borrow;
|
use std::borrow::Borrow;
|
||||||
|
@ -2545,8 +2547,9 @@ impl<'tcx> TyCtxt<'tcx> {
|
||||||
self,
|
self,
|
||||||
obj: &'tcx List<ty::Binder<'tcx, ExistentialPredicate<'tcx>>>,
|
obj: &'tcx List<ty::Binder<'tcx, ExistentialPredicate<'tcx>>>,
|
||||||
reg: ty::Region<'tcx>,
|
reg: ty::Region<'tcx>,
|
||||||
|
repr: TraitObjectRepresentation,
|
||||||
) -> Ty<'tcx> {
|
) -> Ty<'tcx> {
|
||||||
self.mk_ty(Dynamic(obj, reg))
|
self.mk_ty(Dynamic(obj, reg, repr))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
|
|
|
@ -467,7 +467,7 @@ impl<'tcx> TypeVisitor<'tcx> for IsSuggestableVisitor<'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Dynamic(dty, _) => {
|
Dynamic(dty, _, _) => {
|
||||||
for pred in *dty {
|
for pred in *dty {
|
||||||
match pred.skip_binder() {
|
match pred.skip_binder() {
|
||||||
ExistentialPredicate::Trait(_) | ExistentialPredicate::Projection(_) => {
|
ExistentialPredicate::Trait(_) | ExistentialPredicate::Projection(_) => {
|
||||||
|
|
|
@ -171,7 +171,7 @@ impl FlagComputation {
|
||||||
self.add_substs(substs);
|
self.add_substs(substs);
|
||||||
}
|
}
|
||||||
|
|
||||||
&ty::Dynamic(obj, r) => {
|
&ty::Dynamic(obj, r, _) => {
|
||||||
for predicate in obj.iter() {
|
for predicate in obj.iter() {
|
||||||
self.bound_computation(predicate, |computation, predicate| match predicate {
|
self.bound_computation(predicate, |computation, predicate| match predicate {
|
||||||
ty::ExistentialPredicate::Trait(tr) => computation.add_substs(tr.substs),
|
ty::ExistentialPredicate::Trait(tr) => computation.add_substs(tr.substs),
|
||||||
|
|
|
@ -2464,7 +2464,8 @@ where
|
||||||
|
|
||||||
match tcx.struct_tail_erasing_lifetimes(pointee, cx.param_env()).kind() {
|
match tcx.struct_tail_erasing_lifetimes(pointee, cx.param_env()).kind() {
|
||||||
ty::Slice(_) | ty::Str => TyMaybeWithLayout::Ty(tcx.types.usize),
|
ty::Slice(_) | ty::Str => TyMaybeWithLayout::Ty(tcx.types.usize),
|
||||||
ty::Dynamic(_, _) => {
|
// FIXME(eholk): Do the right thing with trait object representation
|
||||||
|
ty::Dynamic(_, _, _repr) => {
|
||||||
TyMaybeWithLayout::Ty(tcx.mk_imm_ref(
|
TyMaybeWithLayout::Ty(tcx.mk_imm_ref(
|
||||||
tcx.lifetimes.re_static,
|
tcx.lifetimes.re_static,
|
||||||
tcx.mk_array(tcx.types.usize, 3),
|
tcx.mk_array(tcx.types.usize, 3),
|
||||||
|
|
|
@ -16,6 +16,7 @@ use rustc_session::cstore::{ExternCrate, ExternCrateSource};
|
||||||
use rustc_span::symbol::{kw, Ident, Symbol};
|
use rustc_span::symbol::{kw, Ident, Symbol};
|
||||||
use rustc_target::abi::Size;
|
use rustc_target::abi::Size;
|
||||||
use rustc_target::spec::abi::Abi;
|
use rustc_target::spec::abi::Abi;
|
||||||
|
use rustc_type_ir::TraitObjectRepresentation;
|
||||||
|
|
||||||
use std::cell::Cell;
|
use std::cell::Cell;
|
||||||
use std::char;
|
use std::char;
|
||||||
|
@ -619,12 +620,16 @@ pub trait PrettyPrinter<'tcx>:
|
||||||
ty::Adt(def, substs) => {
|
ty::Adt(def, substs) => {
|
||||||
p!(print_def_path(def.did(), substs));
|
p!(print_def_path(def.did(), substs));
|
||||||
}
|
}
|
||||||
ty::Dynamic(data, r) => {
|
ty::Dynamic(data, r, repr) => {
|
||||||
let print_r = self.should_print_region(r);
|
let print_r = self.should_print_region(r);
|
||||||
if print_r {
|
if print_r {
|
||||||
p!("(");
|
p!("(");
|
||||||
}
|
}
|
||||||
p!("dyn ", print(data));
|
match repr {
|
||||||
|
TraitObjectRepresentation::Unsized => p!("dyn "),
|
||||||
|
TraitObjectRepresentation::Sized => p!("dyn* "),
|
||||||
|
}
|
||||||
|
p!(print(data));
|
||||||
if print_r {
|
if print_r {
|
||||||
p!(" + ", print(r), ")");
|
p!(" + ", print(r), ")");
|
||||||
}
|
}
|
||||||
|
|
|
@ -441,7 +441,9 @@ pub fn super_relate_tys<'tcx, R: TypeRelation<'tcx>>(
|
||||||
|
|
||||||
(&ty::Foreign(a_id), &ty::Foreign(b_id)) if a_id == b_id => Ok(tcx.mk_foreign(a_id)),
|
(&ty::Foreign(a_id), &ty::Foreign(b_id)) if a_id == b_id => Ok(tcx.mk_foreign(a_id)),
|
||||||
|
|
||||||
(&ty::Dynamic(a_obj, a_region), &ty::Dynamic(b_obj, b_region)) => {
|
(&ty::Dynamic(a_obj, a_region, a_repr), &ty::Dynamic(b_obj, b_region, b_repr))
|
||||||
|
if a_repr == b_repr =>
|
||||||
|
{
|
||||||
let region_bound = relation.with_cause(Cause::ExistentialRegionBound, |relation| {
|
let region_bound = relation.with_cause(Cause::ExistentialRegionBound, |relation| {
|
||||||
relation.relate_with_variance(
|
relation.relate_with_variance(
|
||||||
ty::Contravariant,
|
ty::Contravariant,
|
||||||
|
@ -450,7 +452,7 @@ pub fn super_relate_tys<'tcx, R: TypeRelation<'tcx>>(
|
||||||
b_region,
|
b_region,
|
||||||
)
|
)
|
||||||
})?;
|
})?;
|
||||||
Ok(tcx.mk_dynamic(relation.relate(a_obj, b_obj)?, region_bound))
|
Ok(tcx.mk_dynamic(relation.relate(a_obj, b_obj)?, region_bound, a_repr))
|
||||||
}
|
}
|
||||||
|
|
||||||
(&ty::Generator(a_id, a_substs, movability), &ty::Generator(b_id, b_substs, _))
|
(&ty::Generator(a_id, a_substs, movability), &ty::Generator(b_id, b_substs, _))
|
||||||
|
|
|
@ -1014,9 +1014,11 @@ impl<'tcx> TypeSuperFoldable<'tcx> for Ty<'tcx> {
|
||||||
ty::Array(typ, sz) => ty::Array(typ.try_fold_with(folder)?, sz.try_fold_with(folder)?),
|
ty::Array(typ, sz) => ty::Array(typ.try_fold_with(folder)?, sz.try_fold_with(folder)?),
|
||||||
ty::Slice(typ) => ty::Slice(typ.try_fold_with(folder)?),
|
ty::Slice(typ) => ty::Slice(typ.try_fold_with(folder)?),
|
||||||
ty::Adt(tid, substs) => ty::Adt(tid, substs.try_fold_with(folder)?),
|
ty::Adt(tid, substs) => ty::Adt(tid, substs.try_fold_with(folder)?),
|
||||||
ty::Dynamic(trait_ty, region) => {
|
ty::Dynamic(trait_ty, region, representation) => ty::Dynamic(
|
||||||
ty::Dynamic(trait_ty.try_fold_with(folder)?, region.try_fold_with(folder)?)
|
trait_ty.try_fold_with(folder)?,
|
||||||
}
|
region.try_fold_with(folder)?,
|
||||||
|
representation,
|
||||||
|
),
|
||||||
ty::Tuple(ts) => ty::Tuple(ts.try_fold_with(folder)?),
|
ty::Tuple(ts) => ty::Tuple(ts.try_fold_with(folder)?),
|
||||||
ty::FnDef(def_id, substs) => ty::FnDef(def_id, substs.try_fold_with(folder)?),
|
ty::FnDef(def_id, substs) => ty::FnDef(def_id, substs.try_fold_with(folder)?),
|
||||||
ty::FnPtr(f) => ty::FnPtr(f.try_fold_with(folder)?),
|
ty::FnPtr(f) => ty::FnPtr(f.try_fold_with(folder)?),
|
||||||
|
@ -1060,7 +1062,7 @@ impl<'tcx> TypeSuperVisitable<'tcx> for Ty<'tcx> {
|
||||||
}
|
}
|
||||||
ty::Slice(typ) => typ.visit_with(visitor),
|
ty::Slice(typ) => typ.visit_with(visitor),
|
||||||
ty::Adt(_, substs) => substs.visit_with(visitor),
|
ty::Adt(_, substs) => substs.visit_with(visitor),
|
||||||
ty::Dynamic(ref trait_ty, ref reg) => {
|
ty::Dynamic(ref trait_ty, ref reg, _) => {
|
||||||
trait_ty.visit_with(visitor)?;
|
trait_ty.visit_with(visitor)?;
|
||||||
reg.visit_with(visitor)
|
reg.visit_with(visitor)
|
||||||
}
|
}
|
||||||
|
|
|
@ -152,7 +152,7 @@ fn push_inner<'tcx>(stack: &mut TypeWalkerStack<'tcx>, parent: GenericArg<'tcx>)
|
||||||
ty::Projection(data) => {
|
ty::Projection(data) => {
|
||||||
stack.extend(data.substs.iter().rev());
|
stack.extend(data.substs.iter().rev());
|
||||||
}
|
}
|
||||||
ty::Dynamic(obj, lt) => {
|
ty::Dynamic(obj, lt, _) => {
|
||||||
stack.push(lt.into());
|
stack.push(lt.into());
|
||||||
stack.extend(obj.iter().rev().flat_map(|predicate| {
|
stack.extend(obj.iter().rev().flat_map(|predicate| {
|
||||||
let (substs, opt_ty) = match predicate.skip_binder() {
|
let (substs, opt_ty) = match predicate.skip_binder() {
|
||||||
|
|
|
@ -627,7 +627,7 @@ fn encode_ty<'tcx>(
|
||||||
}
|
}
|
||||||
|
|
||||||
// Trait types
|
// Trait types
|
||||||
ty::Dynamic(predicates, region) => {
|
ty::Dynamic(predicates, region, _repr) => {
|
||||||
// u3dynI<element-type1[..element-typeN]>E, where <element-type> is <predicate>, as
|
// u3dynI<element-type1[..element-typeN]>E, where <element-type> is <predicate>, as
|
||||||
// vendor extended type.
|
// vendor extended type.
|
||||||
let mut s = String::from("u3dynI");
|
let mut s = String::from("u3dynI");
|
||||||
|
|
|
@ -479,7 +479,7 @@ impl<'tcx> Printer<'tcx> for &mut SymbolMangler<'tcx> {
|
||||||
})?;
|
})?;
|
||||||
}
|
}
|
||||||
|
|
||||||
ty::Dynamic(predicates, r) => {
|
ty::Dynamic(predicates, r, _repr) => {
|
||||||
self.push("D");
|
self.push("D");
|
||||||
self = self.print_dyn_existential(predicates)?;
|
self = self.print_dyn_existential(predicates)?;
|
||||||
self = r.print(self)?;
|
self = r.print(self)?;
|
||||||
|
|
|
@ -256,7 +256,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if let ty::Dynamic(traits, _) = self_ty.kind() {
|
if let ty::Dynamic(traits, _, _) = self_ty.kind() {
|
||||||
for t in traits.iter() {
|
for t in traits.iter() {
|
||||||
if let ty::ExistentialPredicate::Trait(trait_ref) = t.skip_binder() {
|
if let ty::ExistentialPredicate::Trait(trait_ref) = t.skip_binder() {
|
||||||
flags.push((sym::_Self, Some(self.tcx.def_path_str(trait_ref.def_id))))
|
flags.push((sym::_Self, Some(self.tcx.def_path_str(trait_ref.def_id))))
|
||||||
|
|
|
@ -1067,7 +1067,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
|
||||||
self_ty: Ty<'tcx>,
|
self_ty: Ty<'tcx>,
|
||||||
object_ty: Ty<'tcx>,
|
object_ty: Ty<'tcx>,
|
||||||
) {
|
) {
|
||||||
let ty::Dynamic(predicates, _) = object_ty.kind() else { return; };
|
let ty::Dynamic(predicates, _, _) = object_ty.kind() else { return; };
|
||||||
let self_ref_ty = self.tcx.mk_imm_ref(self.tcx.lifetimes.re_erased, self_ty);
|
let self_ref_ty = self.tcx.mk_imm_ref(self.tcx.lifetimes.re_erased, self_ty);
|
||||||
|
|
||||||
for predicate in predicates.iter() {
|
for predicate in predicates.iter() {
|
||||||
|
@ -1365,7 +1365,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
|
||||||
let trait_pred = self.resolve_vars_if_possible(trait_pred);
|
let trait_pred = self.resolve_vars_if_possible(trait_pred);
|
||||||
let ty = trait_pred.skip_binder().self_ty();
|
let ty = trait_pred.skip_binder().self_ty();
|
||||||
let is_object_safe = match ty.kind() {
|
let is_object_safe = match ty.kind() {
|
||||||
ty::Dynamic(predicates, _) => {
|
ty::Dynamic(predicates, _, _) => {
|
||||||
// If the `dyn Trait` is not object safe, do not suggest `Box<dyn Trait>`.
|
// If the `dyn Trait` is not object safe, do not suggest `Box<dyn Trait>`.
|
||||||
predicates
|
predicates
|
||||||
.principal_def_id()
|
.principal_def_id()
|
||||||
|
@ -1425,7 +1425,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
|
||||||
let mut spans_and_needs_box = vec![];
|
let mut spans_and_needs_box = vec![];
|
||||||
|
|
||||||
match liberated_sig.output().kind() {
|
match liberated_sig.output().kind() {
|
||||||
ty::Dynamic(predicates, _) => {
|
ty::Dynamic(predicates, _, _) => {
|
||||||
let cause = ObligationCause::misc(ret_ty.span, fn_hir_id);
|
let cause = ObligationCause::misc(ret_ty.span, fn_hir_id);
|
||||||
let param_env = ty::ParamEnv::empty();
|
let param_env = ty::ParamEnv::empty();
|
||||||
|
|
||||||
|
|
|
@ -21,6 +21,7 @@ use rustc_middle::ty::abstract_const::{walk_abstract_const, AbstractConst};
|
||||||
use rustc_middle::ty::subst::{GenericArg, InternalSubsts, Subst};
|
use rustc_middle::ty::subst::{GenericArg, InternalSubsts, Subst};
|
||||||
use rustc_middle::ty::{
|
use rustc_middle::ty::{
|
||||||
self, EarlyBinder, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitor,
|
self, EarlyBinder, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitor,
|
||||||
|
TraitObjectRepresentation,
|
||||||
};
|
};
|
||||||
use rustc_middle::ty::{Predicate, ToPredicate};
|
use rustc_middle::ty::{Predicate, ToPredicate};
|
||||||
use rustc_session::lint::builtin::WHERE_CLAUSES_OBJECT_SAFETY;
|
use rustc_session::lint::builtin::WHERE_CLAUSES_OBJECT_SAFETY;
|
||||||
|
@ -600,7 +601,8 @@ fn object_ty_for_trait<'tcx>(
|
||||||
let existential_predicates = tcx
|
let existential_predicates = tcx
|
||||||
.mk_poly_existential_predicates(iter::once(trait_predicate).chain(projection_predicates));
|
.mk_poly_existential_predicates(iter::once(trait_predicate).chain(projection_predicates));
|
||||||
|
|
||||||
let object_ty = tcx.mk_dynamic(existential_predicates, lifetime);
|
let object_ty =
|
||||||
|
tcx.mk_dynamic(existential_predicates, lifetime, TraitObjectRepresentation::Unsized);
|
||||||
|
|
||||||
debug!("object_ty_for_trait: object_ty=`{}`", object_ty);
|
debug!("object_ty_for_trait: object_ty=`{}`", object_ty);
|
||||||
|
|
||||||
|
|
|
@ -784,7 +784,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||||
let upcast_trait_ref;
|
let upcast_trait_ref;
|
||||||
match (source.kind(), target.kind()) {
|
match (source.kind(), target.kind()) {
|
||||||
// TraitA+Kx+'a -> TraitB+Ky+'b (trait upcasting coercion).
|
// TraitA+Kx+'a -> TraitB+Ky+'b (trait upcasting coercion).
|
||||||
(&ty::Dynamic(ref data_a, r_a), &ty::Dynamic(ref data_b, r_b)) => {
|
(&ty::Dynamic(ref data_a, r_a, repr_a), &ty::Dynamic(ref data_b, r_b, repr_b))
|
||||||
|
if repr_a == repr_b =>
|
||||||
|
{
|
||||||
// See `assemble_candidates_for_unsizing` for more info.
|
// See `assemble_candidates_for_unsizing` for more info.
|
||||||
// We already checked the compatibility of auto traits within `assemble_candidates_for_unsizing`.
|
// We already checked the compatibility of auto traits within `assemble_candidates_for_unsizing`.
|
||||||
let principal_a = data_a.principal().unwrap();
|
let principal_a = data_a.principal().unwrap();
|
||||||
|
@ -810,7 +812,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||||
.map(ty::Binder::dummy),
|
.map(ty::Binder::dummy),
|
||||||
);
|
);
|
||||||
let existential_predicates = tcx.mk_poly_existential_predicates(iter);
|
let existential_predicates = tcx.mk_poly_existential_predicates(iter);
|
||||||
let source_trait = tcx.mk_dynamic(existential_predicates, r_b);
|
let source_trait = tcx.mk_dynamic(existential_predicates, r_b, repr_b);
|
||||||
|
|
||||||
// Require that the traits involved in this upcast are **equal**;
|
// Require that the traits involved in this upcast are **equal**;
|
||||||
// only the **lifetime bound** is changed.
|
// only the **lifetime bound** is changed.
|
||||||
|
@ -888,7 +890,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||||
let mut nested = vec![];
|
let mut nested = vec![];
|
||||||
match (source.kind(), target.kind()) {
|
match (source.kind(), target.kind()) {
|
||||||
// Trait+Kx+'a -> Trait+Ky+'b (auto traits and lifetime subtyping).
|
// Trait+Kx+'a -> Trait+Ky+'b (auto traits and lifetime subtyping).
|
||||||
(&ty::Dynamic(ref data_a, r_a), &ty::Dynamic(ref data_b, r_b)) => {
|
(&ty::Dynamic(ref data_a, r_a, repr_a), &ty::Dynamic(ref data_b, r_b, repr_b))
|
||||||
|
if repr_a == repr_b =>
|
||||||
|
{
|
||||||
// See `assemble_candidates_for_unsizing` for more info.
|
// See `assemble_candidates_for_unsizing` for more info.
|
||||||
// We already checked the compatibility of auto traits within `assemble_candidates_for_unsizing`.
|
// We already checked the compatibility of auto traits within `assemble_candidates_for_unsizing`.
|
||||||
let iter = data_a
|
let iter = data_a
|
||||||
|
@ -907,7 +911,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||||
.map(ty::Binder::dummy),
|
.map(ty::Binder::dummy),
|
||||||
);
|
);
|
||||||
let existential_predicates = tcx.mk_poly_existential_predicates(iter);
|
let existential_predicates = tcx.mk_poly_existential_predicates(iter);
|
||||||
let source_trait = tcx.mk_dynamic(existential_predicates, r_b);
|
let source_trait = tcx.mk_dynamic(existential_predicates, r_b, repr_b);
|
||||||
|
|
||||||
// Require that the traits involved in this upcast are **equal**;
|
// Require that the traits involved in this upcast are **equal**;
|
||||||
// only the **lifetime bound** is changed.
|
// only the **lifetime bound** is changed.
|
||||||
|
@ -934,7 +938,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
// `T` -> `Trait`
|
// `T` -> `Trait`
|
||||||
(_, &ty::Dynamic(ref data, r)) => {
|
(_, &ty::Dynamic(ref data, r, _repr)) => {
|
||||||
let mut object_dids = data.auto_traits().chain(data.principal_def_id());
|
let mut object_dids = data.auto_traits().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));
|
||||||
|
|
|
@ -639,7 +639,7 @@ impl<'tcx> WfPredicates<'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ty::Dynamic(data, r) => {
|
ty::Dynamic(data, r, _) => {
|
||||||
// WfObject
|
// WfObject
|
||||||
//
|
//
|
||||||
// Here, we defer WF checking due to higher-ranked
|
// Here, we defer WF checking due to higher-ranked
|
||||||
|
|
|
@ -326,7 +326,7 @@ impl<'tcx> LowerInto<'tcx, chalk_ir::Ty<RustInterner<'tcx>>> for Ty<'tcx> {
|
||||||
)),
|
)),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
ty::Dynamic(predicates, region) => chalk_ir::TyKind::Dyn(chalk_ir::DynTy {
|
ty::Dynamic(predicates, region, _repr) => chalk_ir::TyKind::Dyn(chalk_ir::DynTy {
|
||||||
bounds: predicates.lower_into(interner),
|
bounds: predicates.lower_into(interner),
|
||||||
lifetime: region.lower_into(interner),
|
lifetime: region.lower_into(interner),
|
||||||
}),
|
}),
|
||||||
|
|
|
@ -389,7 +389,7 @@ fn issue33140_self_ty(tcx: TyCtxt<'_>, def_id: DefId) -> Option<Ty<'_>> {
|
||||||
|
|
||||||
let self_ty = trait_ref.self_ty();
|
let self_ty = trait_ref.self_ty();
|
||||||
let self_ty_matches = match self_ty.kind() {
|
let self_ty_matches = match self_ty.kind() {
|
||||||
ty::Dynamic(ref data, re) if re.is_static() => data.principal().is_none(),
|
ty::Dynamic(ref data, re, _) if re.is_static() => data.principal().is_none(),
|
||||||
_ => false,
|
_ => false,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -18,6 +18,27 @@ use self::TyKind::*;
|
||||||
use rustc_data_structures::stable_hasher::HashStable;
|
use rustc_data_structures::stable_hasher::HashStable;
|
||||||
use rustc_serialize::{Decodable, Decoder, Encodable};
|
use rustc_serialize::{Decodable, Decoder, Encodable};
|
||||||
|
|
||||||
|
/// Specifies how a trait object is represented.
|
||||||
|
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Encodable, Decodable)]
|
||||||
|
pub enum TraitObjectRepresentation {
|
||||||
|
/// An unsized `dyn Trait` object
|
||||||
|
Unsized,
|
||||||
|
/// A sized `dyn* Trait` object
|
||||||
|
Sized,
|
||||||
|
}
|
||||||
|
|
||||||
|
// Manually implemented because deriving HashStable requires rustc_query_system, which would
|
||||||
|
// create a cyclic dependency.
|
||||||
|
impl<CTX> HashStable<CTX> for TraitObjectRepresentation {
|
||||||
|
fn hash_stable(
|
||||||
|
&self,
|
||||||
|
hcx: &mut CTX,
|
||||||
|
hasher: &mut rustc_data_structures::stable_hasher::StableHasher,
|
||||||
|
) {
|
||||||
|
std::mem::discriminant(self).hash_stable(hcx, hasher);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Defines the kinds of types used by the type system.
|
/// Defines the kinds of types used by the type system.
|
||||||
///
|
///
|
||||||
/// Types written by the user start out as `hir::TyKind` and get
|
/// Types written by the user start out as `hir::TyKind` and get
|
||||||
|
@ -95,7 +116,7 @@ pub enum TyKind<I: Interner> {
|
||||||
FnPtr(I::PolyFnSig),
|
FnPtr(I::PolyFnSig),
|
||||||
|
|
||||||
/// A trait object. Written as `dyn for<'b> Trait<'b, Assoc = u32> + Send + 'a`.
|
/// A trait object. Written as `dyn for<'b> Trait<'b, Assoc = u32> + Send + 'a`.
|
||||||
Dynamic(I::ListBinderExistentialPredicate, I::Region),
|
Dynamic(I::ListBinderExistentialPredicate, I::Region, TraitObjectRepresentation),
|
||||||
|
|
||||||
/// The anonymous type of a closure. Used to represent the type of `|a| a`.
|
/// The anonymous type of a closure. Used to represent the type of `|a| a`.
|
||||||
///
|
///
|
||||||
|
@ -218,7 +239,7 @@ const fn tykind_discriminant<I: Interner>(value: &TyKind<I>) -> usize {
|
||||||
Ref(_, _, _) => 11,
|
Ref(_, _, _) => 11,
|
||||||
FnDef(_, _) => 12,
|
FnDef(_, _) => 12,
|
||||||
FnPtr(_) => 13,
|
FnPtr(_) => 13,
|
||||||
Dynamic(_, _) => 14,
|
Dynamic(..) => 14,
|
||||||
Closure(_, _) => 15,
|
Closure(_, _) => 15,
|
||||||
Generator(_, _, _) => 16,
|
Generator(_, _, _) => 16,
|
||||||
GeneratorWitness(_) => 17,
|
GeneratorWitness(_) => 17,
|
||||||
|
@ -252,7 +273,7 @@ impl<I: Interner> Clone for TyKind<I> {
|
||||||
Ref(r, t, m) => Ref(r.clone(), t.clone(), m.clone()),
|
Ref(r, t, m) => Ref(r.clone(), t.clone(), m.clone()),
|
||||||
FnDef(d, s) => FnDef(d.clone(), s.clone()),
|
FnDef(d, s) => FnDef(d.clone(), s.clone()),
|
||||||
FnPtr(s) => FnPtr(s.clone()),
|
FnPtr(s) => FnPtr(s.clone()),
|
||||||
Dynamic(p, r) => Dynamic(p.clone(), r.clone()),
|
Dynamic(p, r, repr) => Dynamic(p.clone(), r.clone(), repr.clone()),
|
||||||
Closure(d, s) => Closure(d.clone(), s.clone()),
|
Closure(d, s) => Closure(d.clone(), s.clone()),
|
||||||
Generator(d, s, m) => Generator(d.clone(), s.clone(), m.clone()),
|
Generator(d, s, m) => Generator(d.clone(), s.clone(), m.clone()),
|
||||||
GeneratorWitness(g) => GeneratorWitness(g.clone()),
|
GeneratorWitness(g) => GeneratorWitness(g.clone()),
|
||||||
|
@ -297,9 +318,10 @@ impl<I: Interner> PartialEq for TyKind<I> {
|
||||||
__self_0 == __arg_1_0 && __self_1 == __arg_1_1
|
__self_0 == __arg_1_0 && __self_1 == __arg_1_1
|
||||||
}
|
}
|
||||||
(&FnPtr(ref __self_0), &FnPtr(ref __arg_1_0)) => __self_0 == __arg_1_0,
|
(&FnPtr(ref __self_0), &FnPtr(ref __arg_1_0)) => __self_0 == __arg_1_0,
|
||||||
(&Dynamic(ref __self_0, ref __self_1), &Dynamic(ref __arg_1_0, ref __arg_1_1)) => {
|
(
|
||||||
__self_0 == __arg_1_0 && __self_1 == __arg_1_1
|
&Dynamic(ref __self_0, ref __self_1, ref self_repr),
|
||||||
}
|
&Dynamic(ref __arg_1_0, ref __arg_1_1, ref arg_repr),
|
||||||
|
) => __self_0 == __arg_1_0 && __self_1 == __arg_1_1 && self_repr == arg_repr,
|
||||||
(&Closure(ref __self_0, ref __self_1), &Closure(ref __arg_1_0, ref __arg_1_1)) => {
|
(&Closure(ref __self_0, ref __self_1), &Closure(ref __arg_1_0, ref __arg_1_1)) => {
|
||||||
__self_0 == __arg_1_0 && __self_1 == __arg_1_1
|
__self_0 == __arg_1_0 && __self_1 == __arg_1_1
|
||||||
}
|
}
|
||||||
|
@ -384,12 +406,16 @@ impl<I: Interner> Ord for TyKind<I> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
(&FnPtr(ref __self_0), &FnPtr(ref __arg_1_0)) => Ord::cmp(__self_0, __arg_1_0),
|
(&FnPtr(ref __self_0), &FnPtr(ref __arg_1_0)) => Ord::cmp(__self_0, __arg_1_0),
|
||||||
(&Dynamic(ref __self_0, ref __self_1), &Dynamic(ref __arg_1_0, ref __arg_1_1)) => {
|
(
|
||||||
match Ord::cmp(__self_0, __arg_1_0) {
|
&Dynamic(ref __self_0, ref __self_1, ref self_repr),
|
||||||
Ordering::Equal => Ord::cmp(__self_1, __arg_1_1),
|
&Dynamic(ref __arg_1_0, ref __arg_1_1, ref arg_repr),
|
||||||
|
) => match Ord::cmp(__self_0, __arg_1_0) {
|
||||||
|
Ordering::Equal => match Ord::cmp(__self_1, __arg_1_1) {
|
||||||
|
Ordering::Equal => Ord::cmp(self_repr, arg_repr),
|
||||||
cmp => cmp,
|
cmp => cmp,
|
||||||
}
|
},
|
||||||
}
|
cmp => cmp,
|
||||||
|
},
|
||||||
(&Closure(ref __self_0, ref __self_1), &Closure(ref __arg_1_0, ref __arg_1_1)) => {
|
(&Closure(ref __self_0, ref __self_1), &Closure(ref __arg_1_0, ref __arg_1_1)) => {
|
||||||
match Ord::cmp(__self_0, __arg_1_0) {
|
match Ord::cmp(__self_0, __arg_1_0) {
|
||||||
Ordering::Equal => Ord::cmp(__self_1, __arg_1_1),
|
Ordering::Equal => Ord::cmp(__self_1, __arg_1_1),
|
||||||
|
@ -492,10 +518,11 @@ impl<I: Interner> hash::Hash for TyKind<I> {
|
||||||
hash::Hash::hash(&tykind_discriminant(self), state);
|
hash::Hash::hash(&tykind_discriminant(self), state);
|
||||||
hash::Hash::hash(__self_0, state)
|
hash::Hash::hash(__self_0, state)
|
||||||
}
|
}
|
||||||
(&Dynamic(ref __self_0, ref __self_1),) => {
|
(&Dynamic(ref __self_0, ref __self_1, ref repr),) => {
|
||||||
hash::Hash::hash(&tykind_discriminant(self), state);
|
hash::Hash::hash(&tykind_discriminant(self), state);
|
||||||
hash::Hash::hash(__self_0, state);
|
hash::Hash::hash(__self_0, state);
|
||||||
hash::Hash::hash(__self_1, state)
|
hash::Hash::hash(__self_1, state);
|
||||||
|
hash::Hash::hash(repr, state)
|
||||||
}
|
}
|
||||||
(&Closure(ref __self_0, ref __self_1),) => {
|
(&Closure(ref __self_0, ref __self_1),) => {
|
||||||
hash::Hash::hash(&tykind_discriminant(self), state);
|
hash::Hash::hash(&tykind_discriminant(self), state);
|
||||||
|
@ -570,7 +597,7 @@ impl<I: Interner> fmt::Debug for TyKind<I> {
|
||||||
Ref(f0, f1, f2) => Formatter::debug_tuple_field3_finish(f, "Ref", f0, f1, f2),
|
Ref(f0, f1, f2) => Formatter::debug_tuple_field3_finish(f, "Ref", f0, f1, f2),
|
||||||
FnDef(f0, f1) => Formatter::debug_tuple_field2_finish(f, "FnDef", f0, f1),
|
FnDef(f0, f1) => Formatter::debug_tuple_field2_finish(f, "FnDef", f0, f1),
|
||||||
FnPtr(f0) => Formatter::debug_tuple_field1_finish(f, "FnPtr", f0),
|
FnPtr(f0) => Formatter::debug_tuple_field1_finish(f, "FnPtr", f0),
|
||||||
Dynamic(f0, f1) => Formatter::debug_tuple_field2_finish(f, "Dynamic", f0, f1),
|
Dynamic(f0, f1, f2) => Formatter::debug_tuple_field3_finish(f, "Dynamic", f0, f1, f2),
|
||||||
Closure(f0, f1) => Formatter::debug_tuple_field2_finish(f, "Closure", f0, f1),
|
Closure(f0, f1) => Formatter::debug_tuple_field2_finish(f, "Closure", f0, f1),
|
||||||
Generator(f0, f1, f2) => {
|
Generator(f0, f1, f2) => {
|
||||||
Formatter::debug_tuple_field3_finish(f, "Generator", f0, f1, f2)
|
Formatter::debug_tuple_field3_finish(f, "Generator", f0, f1, f2)
|
||||||
|
@ -659,9 +686,10 @@ where
|
||||||
FnPtr(polyfnsig) => e.emit_enum_variant(disc, |e| {
|
FnPtr(polyfnsig) => e.emit_enum_variant(disc, |e| {
|
||||||
polyfnsig.encode(e);
|
polyfnsig.encode(e);
|
||||||
}),
|
}),
|
||||||
Dynamic(l, r) => e.emit_enum_variant(disc, |e| {
|
Dynamic(l, r, repr) => e.emit_enum_variant(disc, |e| {
|
||||||
l.encode(e);
|
l.encode(e);
|
||||||
r.encode(e);
|
r.encode(e);
|
||||||
|
repr.encode(e);
|
||||||
}),
|
}),
|
||||||
Closure(def_id, substs) => e.emit_enum_variant(disc, |e| {
|
Closure(def_id, substs) => e.emit_enum_variant(disc, |e| {
|
||||||
def_id.encode(e);
|
def_id.encode(e);
|
||||||
|
@ -748,7 +776,7 @@ where
|
||||||
11 => Ref(Decodable::decode(d), Decodable::decode(d), Decodable::decode(d)),
|
11 => Ref(Decodable::decode(d), Decodable::decode(d), Decodable::decode(d)),
|
||||||
12 => FnDef(Decodable::decode(d), Decodable::decode(d)),
|
12 => FnDef(Decodable::decode(d), Decodable::decode(d)),
|
||||||
13 => FnPtr(Decodable::decode(d)),
|
13 => FnPtr(Decodable::decode(d)),
|
||||||
14 => Dynamic(Decodable::decode(d), Decodable::decode(d)),
|
14 => Dynamic(Decodable::decode(d), Decodable::decode(d), Decodable::decode(d)),
|
||||||
15 => Closure(Decodable::decode(d), Decodable::decode(d)),
|
15 => Closure(Decodable::decode(d), Decodable::decode(d)),
|
||||||
16 => Generator(Decodable::decode(d), Decodable::decode(d), Decodable::decode(d)),
|
16 => Generator(Decodable::decode(d), Decodable::decode(d), Decodable::decode(d)),
|
||||||
17 => GeneratorWitness(Decodable::decode(d)),
|
17 => GeneratorWitness(Decodable::decode(d)),
|
||||||
|
@ -845,9 +873,10 @@ where
|
||||||
FnPtr(polyfnsig) => {
|
FnPtr(polyfnsig) => {
|
||||||
polyfnsig.hash_stable(__hcx, __hasher);
|
polyfnsig.hash_stable(__hcx, __hasher);
|
||||||
}
|
}
|
||||||
Dynamic(l, r) => {
|
Dynamic(l, r, repr) => {
|
||||||
l.hash_stable(__hcx, __hasher);
|
l.hash_stable(__hcx, __hasher);
|
||||||
r.hash_stable(__hcx, __hasher);
|
r.hash_stable(__hcx, __hasher);
|
||||||
|
repr.hash_stable(__hcx, __hasher);
|
||||||
}
|
}
|
||||||
Closure(def_id, substs) => {
|
Closure(def_id, substs) => {
|
||||||
def_id.hash_stable(__hcx, __hasher);
|
def_id.hash_stable(__hcx, __hasher);
|
||||||
|
|
|
@ -31,6 +31,7 @@ use rustc_middle::ty::GenericParamDefKind;
|
||||||
use rustc_middle::ty::{
|
use rustc_middle::ty::{
|
||||||
self, Const, DefIdTree, EarlyBinder, IsSuggestable, Ty, TyCtxt, TypeVisitable,
|
self, Const, DefIdTree, EarlyBinder, IsSuggestable, Ty, TyCtxt, TypeVisitable,
|
||||||
};
|
};
|
||||||
|
use rustc_middle::ty::{TraitObjectRepresentation};
|
||||||
use rustc_session::lint::builtin::{AMBIGUOUS_ASSOCIATED_ITEMS, BARE_TRAIT_OBJECTS};
|
use rustc_session::lint::builtin::{AMBIGUOUS_ASSOCIATED_ITEMS, BARE_TRAIT_OBJECTS};
|
||||||
use rustc_span::edition::Edition;
|
use rustc_span::edition::Edition;
|
||||||
use rustc_span::lev_distance::find_best_match_for_name;
|
use rustc_span::lev_distance::find_best_match_for_name;
|
||||||
|
@ -1572,7 +1573,11 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
||||||
};
|
};
|
||||||
debug!("region_bound: {:?}", region_bound);
|
debug!("region_bound: {:?}", region_bound);
|
||||||
|
|
||||||
let ty = tcx.mk_dynamic(existential_predicates, region_bound);
|
let ty = tcx.mk_dynamic(
|
||||||
|
existential_predicates,
|
||||||
|
region_bound,
|
||||||
|
TraitObjectRepresentation::Unsized, // FIXME: check whether the source syntax was dyn or dyn*
|
||||||
|
);
|
||||||
debug!("trait_object_type: {:?}", ty);
|
debug!("trait_object_type: {:?}", ty);
|
||||||
ty
|
ty
|
||||||
}
|
}
|
||||||
|
|
|
@ -527,7 +527,7 @@ fn check_must_not_suspend_ty<'tcx>(
|
||||||
}
|
}
|
||||||
has_emitted
|
has_emitted
|
||||||
}
|
}
|
||||||
ty::Dynamic(binder, _) => {
|
ty::Dynamic(binder, _, _) => {
|
||||||
let mut has_emitted = false;
|
let mut has_emitted = false;
|
||||||
for predicate in binder.iter() {
|
for predicate in binder.iter() {
|
||||||
if let ty::ExistentialPredicate::Trait(ref trait_ref) = predicate.skip_binder() {
|
if let ty::ExistentialPredicate::Trait(ref trait_ref) = predicate.skip_binder() {
|
||||||
|
|
|
@ -537,7 +537,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
bound_spans.push((self.tcx.def_span(def.did()), msg))
|
bound_spans.push((self.tcx.def_span(def.did()), msg))
|
||||||
}
|
}
|
||||||
// Point at the trait object that couldn't satisfy the bound.
|
// Point at the trait object that couldn't satisfy the bound.
|
||||||
ty::Dynamic(preds, _) => {
|
ty::Dynamic(preds, _, _) => {
|
||||||
for pred in preds.iter() {
|
for pred in preds.iter() {
|
||||||
match pred.skip_binder() {
|
match pred.skip_binder() {
|
||||||
ty::ExistentialPredicate::Trait(tr) => bound_spans
|
ty::ExistentialPredicate::Trait(tr) => bound_spans
|
||||||
|
|
|
@ -257,7 +257,7 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
|
||||||
self.add_constraints_from_invariant_substs(current, substs, variance);
|
self.add_constraints_from_invariant_substs(current, substs, variance);
|
||||||
}
|
}
|
||||||
|
|
||||||
ty::Dynamic(data, r) => {
|
ty::Dynamic(data, r, _) => {
|
||||||
// The type `Foo<T+'a>` is contravariant w/r/t `'a`:
|
// The type `Foo<T+'a>` is contravariant w/r/t `'a`:
|
||||||
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);
|
||||||
|
|
|
@ -1600,7 +1600,7 @@ pub(crate) fn clean_middle_ty<'tcx>(
|
||||||
let path = external_path(cx, did, false, ThinVec::new(), InternalSubsts::empty());
|
let path = external_path(cx, did, false, ThinVec::new(), InternalSubsts::empty());
|
||||||
Type::Path { path }
|
Type::Path { path }
|
||||||
}
|
}
|
||||||
ty::Dynamic(obj, ref reg) => {
|
ty::Dynamic(obj, ref reg, _) => {
|
||||||
// HACK: pick the first `did` as the `did` of the trait object. Someone
|
// HACK: pick the first `did` as the `did` of the trait object. Someone
|
||||||
// might want to implement "native" support for marker-trait-only
|
// might want to implement "native" support for marker-trait-only
|
||||||
// trait objects.
|
// trait objects.
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue