Rollup merge of #55687 - alexreg:fix-24010, r=scalexm
Take supertraits into account when calculating associated types Fixes #24010 and #23856. Applies to trait aliases too. As a by-product, this PR also makes repeated bindings of the same associated item in the same definition a hard error. This was previously a warning with a note about it becoming a hard error in the future. See #50589 for more info. I talked about this with @nikomatsakis recently, but only very superficially, so this shouldn't stop anyone from assigning it to themself to review and r+. N.B. The "WIP" commits represent imperfect attempts to solve the problem just for trait objects, but I've left them in for reference for the sake of whomever is reviewing this. CC @carllerche @theemathas @durka @mbrubeck
This commit is contained in:
commit
0e912b2c17
@ -2134,7 +2134,7 @@ static X: u32 = 42;
|
||||
|
||||
|
||||
register_diagnostics! {
|
||||
// E0006 // merged with E0005
|
||||
// E0006, // merged with E0005
|
||||
// E0101, // replaced with E0282
|
||||
// E0102, // replaced with E0282
|
||||
// E0134,
|
||||
@ -2183,9 +2183,7 @@ register_diagnostics! {
|
||||
E0657, // `impl Trait` can only capture lifetimes bound at the fn level
|
||||
E0687, // in-band lifetimes cannot be used in `fn`/`Fn` syntax
|
||||
E0688, // in-band lifetimes cannot be mixed with explicit lifetime binders
|
||||
|
||||
E0697, // closures cannot be static
|
||||
|
||||
E0707, // multiple elided lifetimes used in arguments of `async fn`
|
||||
E0708, // `async` non-`move` closures with arguments are not currently supported
|
||||
E0709, // multiple different lifetimes used in arguments of `async fn`
|
||||
|
@ -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),
|
||||
|
@ -300,12 +300,6 @@ declare_lint! {
|
||||
"detects labels that are never used"
|
||||
}
|
||||
|
||||
declare_lint! {
|
||||
pub DUPLICATE_ASSOCIATED_TYPE_BINDINGS,
|
||||
Warn,
|
||||
"warns about duplicate associated type bindings in generics"
|
||||
}
|
||||
|
||||
declare_lint! {
|
||||
pub DUPLICATE_MACRO_EXPORTS,
|
||||
Deny,
|
||||
@ -418,7 +412,6 @@ impl LintPass for HardwiredLints {
|
||||
ABSOLUTE_PATHS_NOT_STARTING_WITH_CRATE,
|
||||
UNSTABLE_NAME_COLLISIONS,
|
||||
IRREFUTABLE_LET_PATTERNS,
|
||||
DUPLICATE_ASSOCIATED_TYPE_BINDINGS,
|
||||
DUPLICATE_MACRO_EXPORTS,
|
||||
INTRA_DOC_LINK_RESOLUTION_FAILURE,
|
||||
MISSING_DOC_CODE_EXAMPLES,
|
||||
|
@ -50,11 +50,8 @@ pub use self::select::{EvaluationResult, IntercrateAmbiguityCause, OverflowError
|
||||
pub use self::specialize::{OverlapError, specialization_graph, translate_substs};
|
||||
pub use self::specialize::find_associated_item;
|
||||
pub use self::engine::{TraitEngine, TraitEngineExt};
|
||||
pub use self::util::elaborate_predicates;
|
||||
pub use self::util::supertraits;
|
||||
pub use self::util::Supertraits;
|
||||
pub use self::util::supertrait_def_ids;
|
||||
pub use self::util::SupertraitDefIds;
|
||||
pub use self::util::{elaborate_predicates, elaborate_trait_ref, elaborate_trait_refs};
|
||||
pub use self::util::{supertraits, supertrait_def_ids, Supertraits, SupertraitDefIds};
|
||||
pub use self::util::transitive_bounds;
|
||||
|
||||
#[allow(dead_code)]
|
||||
|
@ -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;
|
||||
|
||||
@ -544,14 +544,14 @@ impl<'tcx> TyS<'tcx> {
|
||||
pub fn is_primitive_ty(&self) -> bool {
|
||||
match self.sty {
|
||||
TyKind::Bool |
|
||||
TyKind::Char |
|
||||
TyKind::Int(_) |
|
||||
TyKind::Uint(_) |
|
||||
TyKind::Float(_) |
|
||||
TyKind::Infer(InferTy::IntVar(_)) |
|
||||
TyKind::Infer(InferTy::FloatVar(_)) |
|
||||
TyKind::Infer(InferTy::FreshIntTy(_)) |
|
||||
TyKind::Infer(InferTy::FreshFloatTy(_)) => true,
|
||||
TyKind::Char |
|
||||
TyKind::Int(_) |
|
||||
TyKind::Uint(_) |
|
||||
TyKind::Float(_) |
|
||||
TyKind::Infer(InferTy::IntVar(_)) |
|
||||
TyKind::Infer(InferTy::FloatVar(_)) |
|
||||
TyKind::Infer(InferTy::FreshIntTy(_)) |
|
||||
TyKind::Infer(InferTy::FreshFloatTy(_)) => true,
|
||||
TyKind::Ref(_, x, _) => x.is_primitive_ty(),
|
||||
_ => false,
|
||||
}
|
||||
@ -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 {
|
||||
@ -1041,15 +1042,15 @@ impl<'a, 'gcx, 'tcx> GenericPredicates<'tcx> {
|
||||
|
||||
#[derive(Clone, Copy, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)]
|
||||
pub enum Predicate<'tcx> {
|
||||
/// Corresponds to `where Foo : Bar<A,B,C>`. `Foo` here would be
|
||||
/// Corresponds to `where Foo: Bar<A,B,C>`. `Foo` here would be
|
||||
/// the `Self` type of the trait reference and `A`, `B`, and `C`
|
||||
/// would be the type parameters.
|
||||
Trait(PolyTraitPredicate<'tcx>),
|
||||
|
||||
/// where `'a : 'b`
|
||||
/// where `'a: 'b`
|
||||
RegionOutlives(PolyRegionOutlivesPredicate<'tcx>),
|
||||
|
||||
/// where `T : 'a`
|
||||
/// where `T: 'a`
|
||||
TypeOutlives(PolyTypeOutlivesPredicate<'tcx>),
|
||||
|
||||
/// where `<T as TraitRef>::Name == X`, approximately.
|
||||
@ -1062,7 +1063,7 @@ pub enum Predicate<'tcx> {
|
||||
/// trait must be object-safe
|
||||
ObjectSafe(DefId),
|
||||
|
||||
/// No direct syntax. May be thought of as `where T : FnFoo<...>`
|
||||
/// No direct syntax. May be thought of as `where T: FnFoo<...>`
|
||||
/// for some substitutions `...` and `T` being a closure type.
|
||||
/// Satisfied (or refuted) once we know the closure's kind.
|
||||
ClosureKind(DefId, ClosureSubsts<'tcx>, ClosureKind),
|
||||
@ -1111,11 +1112,11 @@ impl<'a, 'gcx, 'tcx> Predicate<'tcx> {
|
||||
//
|
||||
// Let's start with an easy case. Consider two traits:
|
||||
//
|
||||
// trait Foo<'a> : Bar<'a,'a> { }
|
||||
// trait Foo<'a>: Bar<'a,'a> { }
|
||||
// trait Bar<'b,'c> { }
|
||||
//
|
||||
// Now, if we have a trait reference `for<'x> T : Foo<'x>`, then
|
||||
// we can deduce that `for<'x> T : Bar<'x,'x>`. Basically, if we
|
||||
// Now, if we have a trait reference `for<'x> T: Foo<'x>`, then
|
||||
// we can deduce that `for<'x> T: Bar<'x,'x>`. Basically, if we
|
||||
// knew that `Foo<'x>` (for any 'x) then we also know that
|
||||
// `Bar<'x,'x>` (for any 'x). This more-or-less falls out from
|
||||
// normal substitution.
|
||||
@ -1128,21 +1129,21 @@ impl<'a, 'gcx, 'tcx> Predicate<'tcx> {
|
||||
//
|
||||
// Another example to be careful of is this:
|
||||
//
|
||||
// trait Foo1<'a> : for<'b> Bar1<'a,'b> { }
|
||||
// trait Foo1<'a>: for<'b> Bar1<'a,'b> { }
|
||||
// trait Bar1<'b,'c> { }
|
||||
//
|
||||
// Here, if we have `for<'x> T : Foo1<'x>`, then what do we know?
|
||||
// The answer is that we know `for<'x,'b> T : Bar1<'x,'b>`. The
|
||||
// Here, if we have `for<'x> T: Foo1<'x>`, then what do we know?
|
||||
// The answer is that we know `for<'x,'b> T: Bar1<'x,'b>`. The
|
||||
// reason is similar to the previous example: any impl of
|
||||
// `T:Foo1<'x>` must show that `for<'b> T : Bar1<'x, 'b>`. So
|
||||
// `T:Foo1<'x>` must show that `for<'b> T: Bar1<'x, 'b>`. So
|
||||
// basically we would want to collapse the bound lifetimes from
|
||||
// the input (`trait_ref`) and the supertraits.
|
||||
//
|
||||
// To achieve this in practice is fairly straightforward. Let's
|
||||
// consider the more complicated scenario:
|
||||
//
|
||||
// - We start out with `for<'x> T : Foo1<'x>`. In this case, `'x`
|
||||
// has a De Bruijn index of 1. We want to produce `for<'x,'b> T : Bar1<'x,'b>`,
|
||||
// - We start out with `for<'x> T: Foo1<'x>`. In this case, `'x`
|
||||
// has a De Bruijn index of 1. We want to produce `for<'x,'b> T: Bar1<'x,'b>`,
|
||||
// where both `'x` and `'b` would have a DB index of 1.
|
||||
// The substitution from the input trait-ref is therefore going to be
|
||||
// `'a => 'x` (where `'x` has a DB index of 1).
|
||||
@ -1194,6 +1195,7 @@ impl<'a, 'gcx, 'tcx> Predicate<'tcx> {
|
||||
pub struct TraitPredicate<'tcx> {
|
||||
pub trait_ref: TraitRef<'tcx>
|
||||
}
|
||||
|
||||
pub type PolyTraitPredicate<'tcx> = ty::Binder<TraitPredicate<'tcx>>;
|
||||
|
||||
impl<'tcx> TraitPredicate<'tcx> {
|
||||
@ -1218,7 +1220,7 @@ impl<'tcx> PolyTraitPredicate<'tcx> {
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, RustcEncodable, RustcDecodable)]
|
||||
pub struct OutlivesPredicate<A,B>(pub A, pub B); // `A : B`
|
||||
pub struct OutlivesPredicate<A,B>(pub A, pub B); // `A: B`
|
||||
pub type PolyOutlivesPredicate<A,B> = ty::Binder<OutlivesPredicate<A,B>>;
|
||||
pub type RegionOutlivesPredicate<'tcx> = OutlivesPredicate<ty::Region<'tcx>,
|
||||
ty::Region<'tcx>>;
|
||||
@ -1238,11 +1240,11 @@ pub type PolySubtypePredicate<'tcx> = ty::Binder<SubtypePredicate<'tcx>>;
|
||||
/// This kind of predicate has no *direct* correspondent in the
|
||||
/// syntax, but it roughly corresponds to the syntactic forms:
|
||||
///
|
||||
/// 1. `T : TraitRef<..., Item=Type>`
|
||||
/// 1. `T: TraitRef<..., Item=Type>`
|
||||
/// 2. `<T as TraitRef<...>>::Item == Type` (NYI)
|
||||
///
|
||||
/// In particular, form #1 is "desugared" to the combination of a
|
||||
/// normal trait predicate (`T : TraitRef<...>`) and one of these
|
||||
/// normal trait predicate (`T: TraitRef<...>`) and one of these
|
||||
/// predicates. Form #2 is a broader form in that it also permits
|
||||
/// equality between arbitrary types. Processing an instance of
|
||||
/// Form #2 eventually yields one of these `ProjectionPredicate`
|
||||
@ -1256,14 +1258,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 +1276,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 +1517,14 @@ impl UniverseIndex {
|
||||
UniverseIndex::from_u32(self.private.checked_add(1).unwrap())
|
||||
}
|
||||
|
||||
/// True if `self` can name a name from `other` -- in other words,
|
||||
/// Returns `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
|
||||
/// Returns `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 +1576,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 +1981,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 +2091,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 +2107,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 +2424,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) {
|
||||
@ -2475,7 +2477,7 @@ impl<'tcx> TyS<'tcx> {
|
||||
///
|
||||
/// Note: prefer `ty.walk()` where possible.
|
||||
pub fn maybe_walk<F>(&'tcx self, mut f: F)
|
||||
where F : FnMut(Ty<'tcx>) -> bool
|
||||
where F: FnMut(Ty<'tcx>) -> bool
|
||||
{
|
||||
let mut walker = self.walk();
|
||||
while let Some(ty) = walker.next() {
|
||||
@ -2678,7 +2680,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 +2804,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
|
||||
}
|
||||
|
@ -627,7 +627,7 @@ impl<'tcx> Binder<&'tcx List<ExistentialPredicate<'tcx>>> {
|
||||
/// A complete reference to a trait. These take numerous guises in syntax,
|
||||
/// but perhaps the most recognizable form is in a where clause:
|
||||
///
|
||||
/// T : Foo<U>
|
||||
/// T: Foo<U>
|
||||
///
|
||||
/// This would be represented by a trait-reference where the def-id is the
|
||||
/// def-id for the trait `Foo` and the substs define `T` as parameter 0,
|
||||
@ -637,8 +637,8 @@ impl<'tcx> Binder<&'tcx List<ExistentialPredicate<'tcx>>> {
|
||||
/// that case the `Self` parameter is absent from the substitutions.
|
||||
///
|
||||
/// Note that a `TraitRef` introduces a level of region binding, to
|
||||
/// account for higher-ranked trait bounds like `T : for<'a> Foo<&'a
|
||||
/// U>` or higher-ranked object types.
|
||||
/// account for higher-ranked trait bounds like `T: for<'a> Foo<&'a U>`
|
||||
/// or higher-ranked object types.
|
||||
#[derive(Copy, Clone, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)]
|
||||
pub struct TraitRef<'tcx> {
|
||||
pub def_id: DefId,
|
||||
@ -663,7 +663,7 @@ impl<'tcx> TraitRef<'tcx> {
|
||||
self.substs.type_at(0)
|
||||
}
|
||||
|
||||
pub fn input_types<'a>(&'a self) -> impl DoubleEndedIterator<Item=Ty<'tcx>> + 'a {
|
||||
pub fn input_types<'a>(&'a self) -> impl DoubleEndedIterator<Item = Ty<'tcx>> + 'a {
|
||||
// Select only the "input types" from a trait-reference. For
|
||||
// now this is all the types that appear in the
|
||||
// trait-reference, but it should eventually exclude
|
||||
@ -886,16 +886,16 @@ pub struct ProjectionTy<'tcx> {
|
||||
/// The parameters of the associated item.
|
||||
pub substs: &'tcx Substs<'tcx>,
|
||||
|
||||
/// The DefId of the TraitItem for the associated type N.
|
||||
/// The `DefId` of the `TraitItem` for the associated type `N`.
|
||||
///
|
||||
/// Note that this is not the DefId of the TraitRef containing this
|
||||
/// associated type, which is in tcx.associated_item(item_def_id).container.
|
||||
/// Note that this is not the `DefId` of the `TraitRef` containing this
|
||||
/// associated type, which is in `tcx.associated_item(item_def_id).container`.
|
||||
pub item_def_id: DefId,
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> ProjectionTy<'tcx> {
|
||||
/// Construct a ProjectionTy by searching the trait from trait_ref for the
|
||||
/// associated item named item_name.
|
||||
/// Construct a `ProjectionTy` by searching the trait from `trait_ref` for the
|
||||
/// associated item named `item_name`.
|
||||
pub fn from_ref_and_name(
|
||||
tcx: TyCtxt<'_, '_, '_>, trait_ref: ty::TraitRef<'tcx>, item_name: Ident
|
||||
) -> ProjectionTy<'tcx> {
|
||||
|
@ -27,7 +27,7 @@ use std::marker::PhantomData;
|
||||
use std::mem;
|
||||
use std::num::NonZeroUsize;
|
||||
|
||||
/// An entity in the Rust typesystem, which can be one of
|
||||
/// An entity in the Rust type system, which can be one of
|
||||
/// several kinds (only types and lifetimes for now).
|
||||
/// To reduce memory usage, a `Kind` is a interned pointer,
|
||||
/// with the lowest 2 bits being reserved for a tag to
|
||||
@ -171,7 +171,7 @@ impl<'tcx> Decodable for Kind<'tcx> {
|
||||
pub type Substs<'tcx> = List<Kind<'tcx>>;
|
||||
|
||||
impl<'a, 'gcx, 'tcx> Substs<'tcx> {
|
||||
/// Creates a Substs that maps each generic parameter to itself.
|
||||
/// Creates a `Substs` that maps each generic parameter to itself.
|
||||
pub fn identity_for_item(tcx: TyCtxt<'a, 'gcx, 'tcx>, def_id: DefId)
|
||||
-> &'tcx Substs<'tcx> {
|
||||
Substs::for_item(tcx, def_id, |param, _| {
|
||||
@ -179,9 +179,9 @@ impl<'a, 'gcx, 'tcx> Substs<'tcx> {
|
||||
})
|
||||
}
|
||||
|
||||
/// Creates a Substs for generic parameter definitions,
|
||||
/// Creates a `Substs` for generic parameter definitions,
|
||||
/// by calling closures to obtain each kind.
|
||||
/// The closures get to observe the Substs as they're
|
||||
/// The closures get to observe the `Substs` as they're
|
||||
/// being built, which can be used to correctly
|
||||
/// substitute defaults of generic parameters.
|
||||
pub fn for_item<F>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
|
||||
@ -242,7 +242,7 @@ impl<'a, 'gcx, 'tcx> Substs<'tcx> {
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn types(&'a self) -> impl DoubleEndedIterator<Item=Ty<'tcx>> + 'a {
|
||||
pub fn types(&'a self) -> impl DoubleEndedIterator<Item = Ty<'tcx>> + 'a {
|
||||
self.iter().filter_map(|k| {
|
||||
if let UnpackedKind::Type(ty) = k.unpack() {
|
||||
Some(ty)
|
||||
@ -253,7 +253,7 @@ impl<'a, 'gcx, 'tcx> Substs<'tcx> {
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn regions(&'a self) -> impl DoubleEndedIterator<Item=ty::Region<'tcx>> + 'a {
|
||||
pub fn regions(&'a self) -> impl DoubleEndedIterator<Item = ty::Region<'tcx>> + 'a {
|
||||
self.iter().filter_map(|k| {
|
||||
if let UnpackedKind::Lifetime(lt) = k.unpack() {
|
||||
Some(lt)
|
||||
@ -332,7 +332,7 @@ impl<'tcx> serialize::UseSpecializedDecodable for &'tcx Substs<'tcx> {}
|
||||
// `foo`. Or use `foo.subst_spanned(tcx, substs, Some(span))` when
|
||||
// there is more information available (for better errors).
|
||||
|
||||
pub trait Subst<'tcx> : Sized {
|
||||
pub trait Subst<'tcx>: Sized {
|
||||
fn subst<'a, 'gcx>(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>,
|
||||
substs: &[Kind<'tcx>]) -> Self {
|
||||
self.subst_spanned(tcx, substs, None)
|
||||
|
@ -317,11 +317,6 @@ pub fn register_builtins(store: &mut lint::LintStore, sess: Option<&Session>) {
|
||||
reference: "issue #51443 <https://github.com/rust-lang/rust/issues/51443>",
|
||||
edition: None,
|
||||
},
|
||||
FutureIncompatibleInfo {
|
||||
id: LintId::of(DUPLICATE_ASSOCIATED_TYPE_BINDINGS),
|
||||
reference: "issue #50589 <https://github.com/rust-lang/rust/issues/50589>",
|
||||
edition: None,
|
||||
},
|
||||
FutureIncompatibleInfo {
|
||||
id: LintId::of(PROC_MACRO_DERIVE_RESOLUTION_FALLBACK),
|
||||
reference: "issue #50504 <https://github.com/rust-lang/rust/issues/50504>",
|
||||
|
@ -37,7 +37,7 @@ use std::iter;
|
||||
use syntax::ast;
|
||||
use syntax::ptr::P;
|
||||
use syntax::feature_gate::{GateIssue, emit_feature_err};
|
||||
use syntax_pos::{Span, MultiSpan};
|
||||
use syntax_pos::{DUMMY_SP, Span, MultiSpan};
|
||||
|
||||
pub trait AstConv<'gcx, 'tcx> {
|
||||
fn tcx<'a>(&'a self) -> TyCtxt<'a, 'gcx, 'tcx>;
|
||||
@ -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))
|
||||
}));
|
||||
|
||||
@ -831,7 +831,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o {
|
||||
let tcx = self.tcx();
|
||||
|
||||
if !speculative {
|
||||
// Given something like `U : SomeTrait<T=X>`, we want to produce a
|
||||
// Given something like `U: SomeTrait<T = X>`, we want to produce a
|
||||
// predicate like `<U as SomeTrait>::T = X`. This is somewhat
|
||||
// subtle in the event that `T` is defined in a supertrait of
|
||||
// `SomeTrait`, because in that case we need to upcast.
|
||||
@ -839,7 +839,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o {
|
||||
// That is, consider this case:
|
||||
//
|
||||
// ```
|
||||
// trait SubTrait : SuperTrait<int> { }
|
||||
// trait SubTrait: SuperTrait<int> { }
|
||||
// trait SuperTrait<A> { type T; }
|
||||
//
|
||||
// ... B : SubTrait<T=foo> ...
|
||||
@ -908,16 +908,14 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o {
|
||||
if !speculative {
|
||||
dup_bindings.entry(assoc_ty.def_id)
|
||||
.and_modify(|prev_span| {
|
||||
let mut err = self.tcx().struct_span_lint_node(
|
||||
::rustc::lint::builtin::DUPLICATE_ASSOCIATED_TYPE_BINDINGS,
|
||||
ref_id,
|
||||
binding.span,
|
||||
&format!("associated type binding `{}` specified more than once",
|
||||
binding.item_name)
|
||||
);
|
||||
err.span_label(binding.span, "used more than once");
|
||||
err.span_label(*prev_span, format!("first use of `{}`", binding.item_name));
|
||||
err.emit();
|
||||
struct_span_err!(self.tcx().sess, binding.span, E0719,
|
||||
"the value of the associated type `{}` (from the trait `{}`) \
|
||||
is already specified",
|
||||
binding.item_name,
|
||||
tcx.item_path_str(assoc_ty.container.id()))
|
||||
.span_label(binding.span, "re-bound here")
|
||||
.span_label(*prev_span, format!("`{}` bound here first", binding.item_name))
|
||||
.emit();
|
||||
})
|
||||
.or_insert(binding.span);
|
||||
}
|
||||
@ -969,7 +967,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 +992,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 +1004,22 @@ 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));
|
||||
for tr in traits::elaborate_trait_ref(tcx, principal) {
|
||||
match tr {
|
||||
ty::Predicate::Trait(pred) => {
|
||||
associated_types.extend(tcx.associated_items(pred.def_id())
|
||||
.filter(|item| item.kind == ty::AssociatedKind::Type)
|
||||
.map(|item| item.def_id));
|
||||
}
|
||||
ty::Predicate::Projection(pred) => {
|
||||
// Include projections defined on supertraits.
|
||||
projection_bounds.push((pred, DUMMY_SP))
|
||||
}
|
||||
_ => ()
|
||||
}
|
||||
}
|
||||
|
||||
for (projection_bound, _) in &projection_bounds {
|
||||
@ -1046,11 +1038,26 @@ 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,
|
||||
}
|
||||
})
|
||||
});
|
||||
|
||||
// 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,8 +1135,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o {
|
||||
span)
|
||||
}
|
||||
|
||||
|
||||
// Checks that bounds contains exactly one element and reports appropriate
|
||||
// Checks that `bounds` contains exactly one element and reports appropriate
|
||||
// errors otherwise.
|
||||
fn one_bound_for_assoc_type<I>(&self,
|
||||
mut bounds: I,
|
||||
@ -1186,11 +1192,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 +1216,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 +1367,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 +1404,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 +1412,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()
|
||||
|
@ -28,9 +28,9 @@ use errors::{DiagnosticBuilder, DiagnosticId};
|
||||
use rustc::hir::intravisit::{self, Visitor, NestedVisitorMap};
|
||||
use rustc::hir;
|
||||
|
||||
/// Helper type of a temporary returned by .for_item(...).
|
||||
/// Helper type of a temporary returned by `.for_item(...)`.
|
||||
/// Necessary because we can't write the following bound:
|
||||
/// F: for<'b, 'tcx> where 'gcx: 'tcx FnOnce(FnCtxt<'b, 'gcx, 'tcx>).
|
||||
/// `F: for<'b, 'tcx> where 'gcx: 'tcx FnOnce(FnCtxt<'b, 'gcx, 'tcx>)`.
|
||||
struct CheckWfFcxBuilder<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
|
||||
inherited: super::InheritedBuilder<'a, 'gcx, 'tcx>,
|
||||
id: ast::NodeId,
|
||||
@ -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]
|
||||
|
@ -1978,9 +1978,9 @@ pub enum SizedByDefault {
|
||||
No,
|
||||
}
|
||||
|
||||
/// Translate the AST's notion of ty param bounds (which are an enum consisting of a newtyped Ty or
|
||||
/// a region) to ty's notion of ty param bounds, which can either be user-defined traits, or the
|
||||
/// built-in trait (formerly known as kind): Send.
|
||||
/// Translate the AST's notion of ty param bounds (which are an enum consisting of a newtyped `Ty`
|
||||
/// or a region) to ty's notion of ty param bounds, which can either be user-defined traits, or the
|
||||
/// built-in trait `Send`.
|
||||
pub fn compute_bounds<'gcx: 'tcx, 'tcx>(
|
||||
astconv: &dyn AstConv<'gcx, 'tcx>,
|
||||
param_ty: Ty<'tcx>,
|
||||
@ -1988,8 +1988,8 @@ pub fn compute_bounds<'gcx: 'tcx, 'tcx>(
|
||||
sized_by_default: SizedByDefault,
|
||||
span: Span,
|
||||
) -> Bounds<'tcx> {
|
||||
let mut region_bounds = vec![];
|
||||
let mut trait_bounds = vec![];
|
||||
let mut region_bounds = Vec::new();
|
||||
let mut trait_bounds = Vec::new();
|
||||
|
||||
for ast_bound in ast_bounds {
|
||||
match *ast_bound {
|
||||
@ -1999,7 +1999,7 @@ pub fn compute_bounds<'gcx: 'tcx, 'tcx>(
|
||||
}
|
||||
}
|
||||
|
||||
let mut projection_bounds = vec![];
|
||||
let mut projection_bounds = Vec::new();
|
||||
|
||||
let mut trait_bounds: Vec<_> = trait_bounds.iter().map(|&bound| {
|
||||
(astconv.instantiate_poly_trait_ref(bound, param_ty, &mut projection_bounds), bound.span)
|
||||
|
@ -4909,4 +4909,5 @@ register_diagnostics! {
|
||||
E0641, // cannot cast to/from a pointer with an unknown kind
|
||||
E0645, // trait aliases not finished
|
||||
E0698, // type inside generator must be known in this context
|
||||
E0719, // duplicate values for associated type binding
|
||||
}
|
||||
|
@ -0,0 +1,16 @@
|
||||
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
trait Foo: Iterator<Item = i32> {}
|
||||
trait Bar: Foo {}
|
||||
|
||||
fn main() {
|
||||
let _: &dyn Bar;
|
||||
}
|
22
src/test/run-pass/issues/issue-24010.rs
Normal file
22
src/test/run-pass/issues/issue-24010.rs
Normal file
@ -0,0 +1,22 @@
|
||||
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
trait Foo: Fn(i32) -> i32 + Send {}
|
||||
|
||||
impl<T: ?Sized + Fn(i32) -> i32 + Send> Foo for T {}
|
||||
|
||||
fn wants_foo(f: Box<Foo>) -> i32 {
|
||||
f(42)
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let f = Box::new(|x| x);
|
||||
assert_eq!(wants_foo(f), 42);
|
||||
}
|
@ -21,7 +21,6 @@ pub fn main() {
|
||||
let b = Box::new(456) as Box<dyn Foo>;
|
||||
assert!(*b == 456);
|
||||
|
||||
// FIXME(alexreg): associated type should be gotten from trait alias definition
|
||||
// let c: &dyn I32Iterator = &vec![123].into_iter();
|
||||
// assert_eq!(c.next(), Some(123));
|
||||
let c: &mut dyn I32Iterator = &mut vec![123].into_iter();
|
||||
assert_eq!(c.next(), Some(123));
|
||||
}
|
@ -0,0 +1,17 @@
|
||||
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
#![feature(trait_alias)]
|
||||
|
||||
trait I32Iterator = Iterator<Item = i32>;
|
||||
|
||||
fn main() {
|
||||
let _: &I32Iterator<Item = u32> = &vec![42].into_iter();
|
||||
}
|
@ -0,0 +1,13 @@
|
||||
error[E0271]: type mismatch resolving `<std::vec::IntoIter<u32> as std::iter::Iterator>::Item == i32`
|
||||
--> $DIR/associated-types-overridden-binding-2.rs:16:39
|
||||
|
|
||||
LL | let _: &I32Iterator<Item = u32> = &vec![42].into_iter();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^ expected u32, found i32
|
||||
|
|
||||
= note: expected type `u32`
|
||||
found type `i32`
|
||||
= note: required for the cast to the object type `dyn I32Iterator<Item=u32, Item=i32>`
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0271`.
|
@ -0,0 +1,21 @@
|
||||
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
#![feature(trait_alias)]
|
||||
|
||||
trait Foo: Iterator<Item = i32> {}
|
||||
trait Bar: Foo<Item = u32> {}
|
||||
|
||||
trait I32Iterator = Iterator<Item = i32>;
|
||||
trait U32Iterator = I32Iterator<Item = u32>;
|
||||
|
||||
fn main() {
|
||||
let _: &I32Iterator<Item = u32>;
|
||||
}
|
@ -0,0 +1,15 @@
|
||||
error[E0284]: type annotations required: cannot resolve `<Self as std::iter::Iterator>::Item == i32`
|
||||
--> $DIR/associated-types-overridden-binding.rs:14:1
|
||||
|
|
||||
LL | trait Bar: Foo<Item = u32> {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
note: required by `Foo`
|
||||
--> $DIR/associated-types-overridden-binding.rs:13:1
|
||||
|
|
||||
LL | trait Foo: Iterator<Item = i32> {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0284`.
|
@ -14,5 +14,4 @@ trait Trait {
|
||||
|
||||
type Foo = Trait; //~ ERROR E0191
|
||||
|
||||
fn main() {
|
||||
}
|
||||
fn main() {}
|
||||
|
@ -8,16 +8,15 @@
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// compile-pass
|
||||
|
||||
use std::iter::Iterator;
|
||||
trait Foo: Iterator<Item = i32, Item = i32> {}
|
||||
|
||||
type Unit = ();
|
||||
|
||||
fn test() -> Box<Iterator<Item = (), Item = Unit>> {
|
||||
fn test() -> Box<Iterator<Item = (), Item = Unit>> {
|
||||
Box::new(None.into_iter())
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let _: &Iterator<Item = i32, Item = i32>;
|
||||
test();
|
||||
}
|
19
src/test/ui/error-codes/E0719.stderr
Normal file
19
src/test/ui/error-codes/E0719.stderr
Normal file
@ -0,0 +1,19 @@
|
||||
error[E0719]: the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified
|
||||
--> $DIR/E0719.rs:11:33
|
||||
|
|
||||
LL | trait Foo: Iterator<Item = i32, Item = i32> {}
|
||||
| ---------- ^^^^^^^^^^ re-bound here
|
||||
| |
|
||||
| `Item` bound here first
|
||||
|
||||
error[E0719]: the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified
|
||||
--> $DIR/E0719.rs:15:38
|
||||
|
|
||||
LL | fn test() -> Box<Iterator<Item = (), Item = Unit>> {
|
||||
| --------- ^^^^^^^^^^^ re-bound here
|
||||
| |
|
||||
| `Item` bound here first
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0719`.
|
@ -1,17 +0,0 @@
|
||||
// compile-pass
|
||||
|
||||
#![crate_type = "lib"]
|
||||
#![feature(linkage)]
|
||||
|
||||
// MergeFunctions will merge these via an anonymous internal
|
||||
// backing function, which must be named if ThinLTO buffers are used
|
||||
|
||||
#[linkage = "weak"]
|
||||
pub fn fn1(a: u32, b: u32, c: u32) -> u32 {
|
||||
a + b + c
|
||||
}
|
||||
|
||||
#[linkage = "weak"]
|
||||
pub fn fn2(a: u32, b: u32, c: u32) -> u32 {
|
||||
a + b + c
|
||||
}
|
27
src/test/ui/issues/issue-51947.rs
Normal file
27
src/test/ui/issues/issue-51947.rs
Normal file
@ -0,0 +1,27 @@
|
||||
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// compile-pass
|
||||
|
||||
#![crate_type = "lib"]
|
||||
#![feature(linkage)]
|
||||
|
||||
// MergeFunctions will merge these via an anonymous internal
|
||||
// backing function, which must be named if ThinLTO buffers are used
|
||||
|
||||
#[linkage = "weak"]
|
||||
pub fn fn1(a: u32, b: u32, c: u32) -> u32 {
|
||||
a + b + c
|
||||
}
|
||||
|
||||
#[linkage = "weak"]
|
||||
pub fn fn2(a: u32, b: u32, c: u32) -> u32 {
|
||||
a + b + c
|
||||
}
|
@ -1,23 +0,0 @@
|
||||
warning: associated type binding `Item` specified more than once
|
||||
--> $DIR/issue-50589-multiple-associated-types.rs:17:39
|
||||
|
|
||||
LL | fn test() -> Box<Iterator<Item = (), Item = Unit>> {
|
||||
| --------- ^^^^^^^^^^^ used more than once
|
||||
| |
|
||||
| first use of `Item`
|
||||
|
|
||||
= note: #[warn(duplicate_associated_type_bindings)] on by default
|
||||
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
||||
= note: for more information, see issue #50589 <https://github.com/rust-lang/rust/issues/50589>
|
||||
|
||||
warning: associated type binding `Item` specified more than once
|
||||
--> $DIR/issue-50589-multiple-associated-types.rs:17:39
|
||||
|
|
||||
LL | fn test() -> Box<Iterator<Item = (), Item = Unit>> {
|
||||
| --------- ^^^^^^^^^^^ used more than once
|
||||
| |
|
||||
| first use of `Item`
|
||||
|
|
||||
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
||||
= note: for more information, see issue #50589 <https://github.com/rust-lang/rust/issues/50589>
|
||||
|
@ -1,5 +1,5 @@
|
||||
error[E0038]: the trait `EqAlias` cannot be made into an object
|
||||
--> $DIR/trait-alias-objects.rs:17:13
|
||||
--> $DIR/trait-alias-object.rs:17:13
|
||||
|
|
||||
LL | let _: &dyn EqAlias = &123;
|
||||
| ^^^^^^^^^^^ the trait `EqAlias` cannot be made into an object
|
||||
@ -7,7 +7,7 @@ LL | let _: &dyn EqAlias = &123;
|
||||
= note: the trait cannot use `Self` as a type parameter in the supertraits or where-clauses
|
||||
|
||||
error[E0191]: the value of the associated type `Item` (from the trait `std::iter::Iterator`) must be specified
|
||||
--> $DIR/trait-alias-objects.rs:18:13
|
||||
--> $DIR/trait-alias-object.rs:18:13
|
||||
|
|
||||
LL | let _: &dyn IteratorAlias = &vec![123].into_iter();
|
||||
| ^^^^^^^^^^^^^^^^^ missing associated type `Item` value
|
Loading…
x
Reference in New Issue
Block a user