Look at projections from supertraits when constructing trait objects.
This commit is contained in:
parent
25a42b2ceb
commit
d08a42bf2c
5 changed files with 77 additions and 69 deletions
|
|
@ -506,9 +506,9 @@ pub enum TraitBoundModifier {
|
|||
}
|
||||
|
||||
/// The AST represents all type param bounds as types.
|
||||
/// typeck::collect::compute_bounds matches these against
|
||||
/// the "special" built-in traits (see middle::lang_items) and
|
||||
/// detects Copy, Send and Sync.
|
||||
/// `typeck::collect::compute_bounds` matches these against
|
||||
/// the "special" built-in traits (see `middle::lang_items`) and
|
||||
/// detects `Copy`, `Send` and `Sync`.
|
||||
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
|
||||
pub enum GenericBound {
|
||||
Trait(PolyTraitRef, TraitBoundModifier),
|
||||
|
|
|
|||
|
|
@ -333,7 +333,7 @@ impl<I> FilterToTraits<I> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'tcx,I:Iterator<Item = ty::Predicate<'tcx>>> Iterator for FilterToTraits<I> {
|
||||
impl<'tcx, I: Iterator<Item = ty::Predicate<'tcx>>> Iterator for FilterToTraits<I> {
|
||||
type Item = ty::PolyTraitRef<'tcx>;
|
||||
|
||||
fn next(&mut self) -> Option<ty::PolyTraitRef<'tcx>> {
|
||||
|
|
|
|||
|
|
@ -294,7 +294,7 @@ impl Visibility {
|
|||
}
|
||||
}
|
||||
|
||||
/// Returns true if an item with this visibility is accessible from the given block.
|
||||
/// Returns `true` if an item with this visibility is accessible from the given block.
|
||||
pub fn is_accessible_from<T: DefIdTree>(self, module: DefId, tree: T) -> bool {
|
||||
let restriction = match self {
|
||||
// Public items are visible everywhere.
|
||||
|
|
@ -309,7 +309,7 @@ impl Visibility {
|
|||
tree.is_descendant_of(module, restriction)
|
||||
}
|
||||
|
||||
/// Returns true if this visibility is at least as accessible as the given visibility
|
||||
/// Returns `true` if this visibility is at least as accessible as the given visibility
|
||||
pub fn is_at_least<T: DefIdTree>(self, vis: Visibility, tree: T) -> bool {
|
||||
let vis_restriction = match vis {
|
||||
Visibility::Public => return self == Visibility::Public,
|
||||
|
|
@ -320,7 +320,7 @@ impl Visibility {
|
|||
self.is_accessible_from(vis_restriction, tree)
|
||||
}
|
||||
|
||||
// Returns true if this item is visible anywhere in the local crate.
|
||||
// Returns `true` if this item is visible anywhere in the local crate.
|
||||
pub fn is_visible_locally(self) -> bool {
|
||||
match self {
|
||||
Visibility::Public => true,
|
||||
|
|
@ -451,7 +451,7 @@ bitflags! {
|
|||
// FIXME: Rename this to the actual property since it's used for generators too
|
||||
const HAS_TY_CLOSURE = 1 << 9;
|
||||
|
||||
// true if there are "names" of types and regions and so forth
|
||||
// `true` if there are "names" of types and regions and so forth
|
||||
// that are local to a particular fn
|
||||
const HAS_FREE_LOCAL_NAMES = 1 << 10;
|
||||
|
||||
|
|
@ -953,7 +953,7 @@ impl<'a, 'gcx, 'tcx> Generics {
|
|||
_ => bug!("expected lifetime parameter, but found another generic parameter")
|
||||
}
|
||||
} else {
|
||||
tcx.generics_of(self.parent.expect("parent_count>0 but no parent?"))
|
||||
tcx.generics_of(self.parent.expect("parent_count > 0 but no parent?"))
|
||||
.region_param(param, tcx)
|
||||
}
|
||||
}
|
||||
|
|
@ -970,7 +970,7 @@ impl<'a, 'gcx, 'tcx> Generics {
|
|||
_ => bug!("expected type parameter, but found another generic parameter")
|
||||
}
|
||||
} else {
|
||||
tcx.generics_of(self.parent.expect("parent_count>0 but no parent?"))
|
||||
tcx.generics_of(self.parent.expect("parent_count > 0 but no parent?"))
|
||||
.type_param(param, tcx)
|
||||
}
|
||||
}
|
||||
|
|
@ -993,6 +993,7 @@ impl<'a, 'gcx, 'tcx> GenericPredicates<'tcx> {
|
|||
self.instantiate_into(tcx, &mut instantiated, substs);
|
||||
instantiated
|
||||
}
|
||||
|
||||
pub fn instantiate_own(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>, substs: &Substs<'tcx>)
|
||||
-> InstantiatedPredicates<'tcx> {
|
||||
InstantiatedPredicates {
|
||||
|
|
@ -1256,14 +1257,14 @@ pub struct ProjectionPredicate<'tcx> {
|
|||
pub type PolyProjectionPredicate<'tcx> = Binder<ProjectionPredicate<'tcx>>;
|
||||
|
||||
impl<'tcx> PolyProjectionPredicate<'tcx> {
|
||||
/// Returns the def-id of the associated item being projected.
|
||||
/// Returns the `DefId` of the associated item being projected.
|
||||
pub fn item_def_id(&self) -> DefId {
|
||||
self.skip_binder().projection_ty.item_def_id
|
||||
}
|
||||
|
||||
pub fn to_poly_trait_ref(&self, tcx: TyCtxt<'_, '_, '_>) -> PolyTraitRef<'tcx> {
|
||||
// Note: unlike with TraitRef::to_poly_trait_ref(),
|
||||
// self.0.trait_ref is permitted to have escaping regions.
|
||||
// Note: unlike with `TraitRef::to_poly_trait_ref()`,
|
||||
// `self.0.trait_ref` is permitted to have escaping regions.
|
||||
// This is because here `self` has a `Binder` and so does our
|
||||
// return value, so we are preserving the number of binding
|
||||
// levels.
|
||||
|
|
@ -1274,12 +1275,12 @@ impl<'tcx> PolyProjectionPredicate<'tcx> {
|
|||
self.map_bound(|predicate| predicate.ty)
|
||||
}
|
||||
|
||||
/// The DefId of the TraitItem for the associated type.
|
||||
/// The `DefId` of the `TraitItem` for the associated type.
|
||||
///
|
||||
/// Note that this is not the DefId of the TraitRef containing this
|
||||
/// associated type, which is in tcx.associated_item(projection_def_id()).container.
|
||||
/// Note that this is not the `DefId` of the `TraitRef` containing this
|
||||
/// associated type, which is in `tcx.associated_item(projection_def_id()).container`.
|
||||
pub fn projection_def_id(&self) -> DefId {
|
||||
// ok to skip binder since trait def-id does not care about regions
|
||||
// okay to skip binder since trait def-id does not care about regions
|
||||
self.skip_binder().projection_ty.item_def_id
|
||||
}
|
||||
}
|
||||
|
|
@ -1515,14 +1516,14 @@ impl UniverseIndex {
|
|||
UniverseIndex::from_u32(self.private.checked_add(1).unwrap())
|
||||
}
|
||||
|
||||
/// True if `self` can name a name from `other` -- in other words,
|
||||
/// `true` if `self` can name a name from `other` -- in other words,
|
||||
/// if the set of names in `self` is a superset of those in
|
||||
/// `other` (`self >= other`).
|
||||
pub fn can_name(self, other: UniverseIndex) -> bool {
|
||||
self.private >= other.private
|
||||
}
|
||||
|
||||
/// True if `self` cannot name some names from `other` -- in other
|
||||
/// `true` if `self` cannot name some names from `other` -- in other
|
||||
/// words, if the set of names in `self` is a strict subset of
|
||||
/// those in `other` (`self < other`).
|
||||
pub fn cannot_name(self, other: UniverseIndex) -> bool {
|
||||
|
|
@ -1574,7 +1575,7 @@ impl<'tcx> ParamEnv<'tcx> {
|
|||
/// are revealed. This is suitable for monomorphized, post-typeck
|
||||
/// environments like codegen or doing optimizations.
|
||||
///
|
||||
/// NB. If you want to have predicates in scope, use `ParamEnv::new`,
|
||||
/// N.B. If you want to have predicates in scope, use `ParamEnv::new`,
|
||||
/// or invoke `param_env.with_reveal_all()`.
|
||||
pub fn reveal_all() -> Self {
|
||||
Self::new(List::empty(), Reveal::All)
|
||||
|
|
@ -1979,14 +1980,14 @@ impl ReprOptions {
|
|||
self.int.unwrap_or(attr::SignedInt(ast::IntTy::Isize))
|
||||
}
|
||||
|
||||
/// Returns true if this `#[repr()]` should inhabit "smart enum
|
||||
/// Returns `true` if this `#[repr()]` should inhabit "smart enum
|
||||
/// layout" optimizations, such as representing `Foo<&T>` as a
|
||||
/// single pointer.
|
||||
pub fn inhibit_enum_layout_opt(&self) -> bool {
|
||||
self.c() || self.int.is_some()
|
||||
}
|
||||
|
||||
/// Returns true if this `#[repr()]` should inhibit struct field reordering
|
||||
/// Returns `true` if this `#[repr()]` should inhibit struct field reordering
|
||||
/// optimizations, such as with repr(C) or repr(packed(1)).
|
||||
pub fn inhibit_struct_field_reordering_opt(&self) -> bool {
|
||||
!(self.flags & ReprFlags::IS_UNOPTIMISABLE).is_empty() || (self.pack == 1)
|
||||
|
|
@ -2089,7 +2090,7 @@ impl<'a, 'gcx, 'tcx> AdtDef {
|
|||
self.flags.intersects(AdtFlags::IS_FUNDAMENTAL)
|
||||
}
|
||||
|
||||
/// Returns true if this is PhantomData<T>.
|
||||
/// Returns `true` if this is PhantomData<T>.
|
||||
#[inline]
|
||||
pub fn is_phantom_data(&self) -> bool {
|
||||
self.flags.intersects(AdtFlags::IS_PHANTOM_DATA)
|
||||
|
|
@ -2105,7 +2106,7 @@ impl<'a, 'gcx, 'tcx> AdtDef {
|
|||
self.flags.intersects(AdtFlags::IS_RC)
|
||||
}
|
||||
|
||||
/// Returns true if this is Box<T>.
|
||||
/// Returns `true` if this is Box<T>.
|
||||
#[inline]
|
||||
pub fn is_box(&self) -> bool {
|
||||
self.flags.intersects(AdtFlags::IS_BOX)
|
||||
|
|
@ -2422,7 +2423,7 @@ impl<'a, 'tcx> ClosureKind {
|
|||
}
|
||||
}
|
||||
|
||||
/// True if this a type that impls this closure kind
|
||||
/// Returns `true` if this a type that impls this closure kind
|
||||
/// must also implement `other`.
|
||||
pub fn extends(self, other: ty::ClosureKind) -> bool {
|
||||
match (self, other) {
|
||||
|
|
@ -2678,7 +2679,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
|
|||
as Box<dyn Iterator<Item = AssociatedItem> + 'a>
|
||||
}
|
||||
|
||||
/// Returns true if the impls are the same polarity and the trait either
|
||||
/// Returns `true` if the impls are the same polarity and the trait either
|
||||
/// has no items or is annotated #[marker] and prevents item overrides.
|
||||
pub fn impls_are_allowed_to_overlap(self, def_id1: DefId, def_id2: DefId) -> bool {
|
||||
if self.features().overlapping_marker_traits {
|
||||
|
|
@ -2802,7 +2803,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
|
|||
attr::contains_name(&self.get_attrs(did), attr)
|
||||
}
|
||||
|
||||
/// Returns true if this is an `auto trait`.
|
||||
/// Returns `true` if this is an `auto trait`.
|
||||
pub fn trait_is_auto(self, trait_def_id: DefId) -> bool {
|
||||
self.trait_def(trait_def_id).has_auto_impl
|
||||
}
|
||||
|
|
|
|||
|
|
@ -451,7 +451,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o {
|
|||
}
|
||||
|
||||
// We manually build up the substitution, rather than using convenience
|
||||
// methods in subst.rs so that we can iterate over the arguments and
|
||||
// methods in `subst.rs` so that we can iterate over the arguments and
|
||||
// parameters in lock-step linearly, rather than trying to match each pair.
|
||||
let mut substs: SmallVec<[Kind<'tcx>; 8]> = SmallVec::with_capacity(count);
|
||||
|
||||
|
|
@ -469,7 +469,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o {
|
|||
}
|
||||
}
|
||||
|
||||
// (Unless it's been handled in `parent_substs`) `Self` is handled first.
|
||||
// `Self` is handled first, unless it's been handled in `parent_substs`.
|
||||
if has_self {
|
||||
if let Some(¶m) = params.peek() {
|
||||
if param.index == 0 {
|
||||
|
|
@ -698,7 +698,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o {
|
|||
trait_ref.path.segments.last().unwrap())
|
||||
}
|
||||
|
||||
/// Get the DefId of the given trait ref. It _must_ actually be a trait.
|
||||
/// Get the `DefId` of the given trait ref. It _must_ actually be a trait.
|
||||
fn trait_def_id(&self, trait_ref: &hir::TraitRef) -> DefId {
|
||||
let path = &trait_ref.path;
|
||||
match path.def {
|
||||
|
|
@ -711,7 +711,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o {
|
|||
}
|
||||
}
|
||||
|
||||
/// The given `trait_ref` must actually be trait.
|
||||
/// The given trait ref must actually be a trait.
|
||||
pub(super) fn instantiate_poly_trait_ref_inner(&self,
|
||||
trait_ref: &hir::TraitRef,
|
||||
self_ty: Ty<'tcx>,
|
||||
|
|
@ -738,7 +738,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o {
|
|||
let predicate: Result<_, ErrorReported> =
|
||||
self.ast_type_binding_to_poly_projection_predicate(
|
||||
trait_ref.ref_id, poly_trait_ref, binding, speculative, &mut dup_bindings);
|
||||
// ok to ignore Err because ErrorReported (see above)
|
||||
// okay to ignore Err because of ErrorReported (see above)
|
||||
Some((predicate.ok()?, binding.span))
|
||||
}));
|
||||
|
||||
|
|
@ -947,14 +947,6 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o {
|
|||
)
|
||||
}
|
||||
|
||||
/// Transform a `PolyTraitRef` into a `PolyExistentialTraitRef` by
|
||||
/// removing the dummy `Self` type (`TRAIT_OBJECT_DUMMY_SELF`).
|
||||
fn trait_ref_to_existential(&self, trait_ref: ty::TraitRef<'tcx>)
|
||||
-> ty::ExistentialTraitRef<'tcx> {
|
||||
assert_eq!(trait_ref.self_ty().sty, TRAIT_OBJECT_DUMMY_SELF);
|
||||
ty::ExistentialTraitRef::erase_self_ty(self.tcx(), trait_ref)
|
||||
}
|
||||
|
||||
fn conv_object_ty_poly_trait_ref(&self,
|
||||
span: Span,
|
||||
trait_bounds: &[hir::PolyTraitRef],
|
||||
|
|
@ -969,7 +961,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o {
|
|||
return tcx.types.err;
|
||||
}
|
||||
|
||||
let mut projection_bounds = vec![];
|
||||
let mut projection_bounds = Vec::new();
|
||||
let dummy_self = tcx.mk_ty(TRAIT_OBJECT_DUMMY_SELF);
|
||||
let principal = self.instantiate_poly_trait_ref(&trait_bounds[0],
|
||||
dummy_self,
|
||||
|
|
@ -994,23 +986,8 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o {
|
|||
.emit();
|
||||
}
|
||||
|
||||
// Erase the dummy_self (TRAIT_OBJECT_DUMMY_SELF) used above.
|
||||
let existential_principal = principal.map_bound(|trait_ref| {
|
||||
self.trait_ref_to_existential(trait_ref)
|
||||
});
|
||||
let existential_projections = projection_bounds.iter().map(|(bound, _)| {
|
||||
bound.map_bound(|b| {
|
||||
let trait_ref = self.trait_ref_to_existential(b.projection_ty.trait_ref(tcx));
|
||||
ty::ExistentialProjection {
|
||||
ty: b.ty,
|
||||
item_def_id: b.projection_ty.item_def_id,
|
||||
substs: trait_ref.substs,
|
||||
}
|
||||
})
|
||||
});
|
||||
|
||||
// Check that there are no gross object safety violations;
|
||||
// most importantly, that the supertraits don't contain Self,
|
||||
// most importantly, that the supertraits don't contain `Self`,
|
||||
// to avoid ICEs.
|
||||
let object_safety_violations =
|
||||
tcx.global_tcx().astconv_object_safety_violations(principal.def_id());
|
||||
|
|
@ -1021,13 +998,23 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o {
|
|||
return tcx.types.err;
|
||||
}
|
||||
|
||||
// Use a BTreeSet to keep output in a more consistent order.
|
||||
// Use a `BTreeSet` to keep output in a more consistent order.
|
||||
let mut associated_types = BTreeSet::default();
|
||||
|
||||
for tr in traits::supertraits(tcx, principal) {
|
||||
associated_types.extend(tcx.associated_items(tr.def_id())
|
||||
.filter(|item| item.kind == ty::AssociatedKind::Type)
|
||||
.map(|item| item.def_id));
|
||||
|
||||
projection_bounds.extend(tcx.predicates_of(tr.def_id())
|
||||
.predicates.into_iter()
|
||||
.filter_map(|(pred, span)| {
|
||||
if let ty::Predicate::Projection(proj) = pred {
|
||||
Some((proj, span))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
for (projection_bound, _) in &projection_bounds {
|
||||
|
|
@ -1046,11 +1033,28 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o {
|
|||
.emit();
|
||||
}
|
||||
|
||||
// Erase the `dummy_self` (`TRAIT_OBJECT_DUMMY_SELF`) used above.
|
||||
let existential_principal = principal.map_bound(|trait_ref| {
|
||||
assert_eq!(trait_ref.self_ty().sty, TRAIT_OBJECT_DUMMY_SELF);
|
||||
ty::ExistentialTraitRef::erase_self_ty(self.tcx(), trait_ref)
|
||||
});
|
||||
let existential_projections = projection_bounds.iter().map(|(bound, _)| {
|
||||
bound.map_bound(|b| {
|
||||
let trait_ref = ty::ExistentialTraitRef::erase_self_ty(self.tcx(),
|
||||
b.projection_ty.trait_ref(tcx));
|
||||
ty::ExistentialProjection {
|
||||
ty: b.ty,
|
||||
item_def_id: b.projection_ty.item_def_id,
|
||||
substs: trait_ref.substs,
|
||||
}
|
||||
})
|
||||
});
|
||||
|
||||
// Dedup auto traits so that `dyn Trait + Send + Send` is the same as `dyn Trait + Send`.
|
||||
auto_traits.sort();
|
||||
auto_traits.dedup();
|
||||
|
||||
// skip_binder is okay, because the predicates are re-bound.
|
||||
// Calling `skip_binder` is okay, because the predicates are re-bound.
|
||||
let mut v =
|
||||
iter::once(ty::ExistentialPredicate::Trait(*existential_principal.skip_binder()))
|
||||
.chain(auto_traits.into_iter().map(ty::ExistentialPredicate::AutoTrait))
|
||||
|
|
@ -1128,7 +1132,6 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o {
|
|||
span)
|
||||
}
|
||||
|
||||
|
||||
// Checks that bounds contains exactly one element and reports appropriate
|
||||
// errors otherwise.
|
||||
fn one_bound_for_assoc_type<I>(&self,
|
||||
|
|
@ -1186,11 +1189,11 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o {
|
|||
}
|
||||
|
||||
// Create a type from a path to an associated type.
|
||||
// For a path A::B::C::D, ty and ty_path_def are the type and def for A::B::C
|
||||
// and item_segment is the path segment for D. We return a type and a def for
|
||||
// For a path `A::B::C::D`, `ty` and `ty_path_def` are the type and def for `A::B::C`
|
||||
// and item_segment is the path segment for `D`. We return a type and a def for
|
||||
// the whole path.
|
||||
// Will fail except for T::A and Self::A; i.e., if ty/ty_path_def are not a type
|
||||
// parameter or Self.
|
||||
// Will fail except for `T::A` and `Self::A`; i.e., if `ty`/`ty_path_def` are not a type
|
||||
// parameter or `Self`.
|
||||
pub fn associated_path_def_to_ty(&self,
|
||||
ref_id: ast::NodeId,
|
||||
span: Span,
|
||||
|
|
@ -1210,7 +1213,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o {
|
|||
// item is declared.
|
||||
let bound = match (&ty.sty, ty_path_def) {
|
||||
(_, Def::SelfTy(Some(_), Some(impl_def_id))) => {
|
||||
// `Self` in an impl of a trait - we have a concrete self type and a
|
||||
// `Self` in an impl of a trait - we have a concrete `self` type and a
|
||||
// trait reference.
|
||||
let trait_ref = match tcx.impl_trait_ref(impl_def_id) {
|
||||
Some(trait_ref) => trait_ref,
|
||||
|
|
@ -1361,7 +1364,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o {
|
|||
let span = path.span;
|
||||
match path.def {
|
||||
Def::Existential(did) => {
|
||||
// check for desugared impl trait
|
||||
// Check for desugared impl trait.
|
||||
assert!(ty::is_impl_trait_defn(tcx, did).is_none());
|
||||
let item_segment = path.segments.split_last().unwrap();
|
||||
self.prohibit_generics(item_segment.1);
|
||||
|
|
@ -1398,7 +1401,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o {
|
|||
tcx.mk_ty_param(index, tcx.hir.name(node_id).as_interned_str())
|
||||
}
|
||||
Def::SelfTy(_, Some(def_id)) => {
|
||||
// Self in impl (we know the concrete type).
|
||||
// `Self` in impl (we know the concrete type)
|
||||
|
||||
assert_eq!(opt_self_ty, None);
|
||||
self.prohibit_generics(&path.segments);
|
||||
|
|
@ -1406,7 +1409,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o {
|
|||
tcx.at(span).type_of(def_id)
|
||||
}
|
||||
Def::SelfTy(Some(_), None) => {
|
||||
// Self in trait.
|
||||
// `Self` in trait
|
||||
assert_eq!(opt_self_ty, None);
|
||||
self.prohibit_generics(&path.segments);
|
||||
tcx.mk_self_type()
|
||||
|
|
|
|||
|
|
@ -186,6 +186,8 @@ fn check_associated_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
|||
item_id: ast::NodeId,
|
||||
span: Span,
|
||||
sig_if_method: Option<&hir::MethodSig>) {
|
||||
debug!("check_associated_item: {:?}", item_id);
|
||||
|
||||
let code = ObligationCauseCode::MiscObligation;
|
||||
for_id(tcx, item_id, span).with_fcx(|fcx, tcx| {
|
||||
let item = fcx.tcx.associated_item(fcx.tcx.hir.local_def_id(item_id));
|
||||
|
|
@ -311,6 +313,8 @@ fn check_type_defn<'a, 'tcx, F>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
|||
}
|
||||
|
||||
fn check_trait<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, item: &hir::Item) {
|
||||
debug!("check_trait: {:?}", item.id);
|
||||
|
||||
let trait_def_id = tcx.hir.local_def_id(item.id);
|
||||
|
||||
let trait_def = tcx.trait_def(trait_def_id);
|
||||
|
|
@ -1012,7 +1016,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
|||
}
|
||||
|
||||
None => {
|
||||
// Inherent impl: take implied bounds from the self type.
|
||||
// Inherent impl: take implied bounds from the `self` type.
|
||||
let self_ty = self.tcx.type_of(impl_def_id);
|
||||
let self_ty = self.normalize_associated_types_in(span, &self_ty);
|
||||
vec![self_ty]
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue