Default auto traits: revert to the default supertraits
This commit is contained in:
@@ -174,12 +174,6 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
if let Node::TraitItem(item) = node {
|
|
||||||
let mut bounds = Vec::new();
|
|
||||||
icx.lowerer().add_default_trait_item_bounds(item, &mut bounds);
|
|
||||||
predicates.extend(bounds);
|
|
||||||
}
|
|
||||||
|
|
||||||
let generics = tcx.generics_of(def_id);
|
let generics = tcx.generics_of(def_id);
|
||||||
|
|
||||||
// Below we'll consider the bounds on the type parameters (including `Self`)
|
// Below we'll consider the bounds on the type parameters (including `Self`)
|
||||||
|
|||||||
@@ -1,12 +1,13 @@
|
|||||||
|
use std::assert_matches::assert_matches;
|
||||||
use std::ops::ControlFlow;
|
use std::ops::ControlFlow;
|
||||||
|
|
||||||
use rustc_data_structures::fx::{FxIndexMap, FxIndexSet};
|
use rustc_data_structures::fx::{FxIndexMap, FxIndexSet};
|
||||||
use rustc_errors::codes::*;
|
use rustc_errors::codes::*;
|
||||||
use rustc_errors::struct_span_code_err;
|
use rustc_errors::struct_span_code_err;
|
||||||
use rustc_hir as hir;
|
use rustc_hir as hir;
|
||||||
|
use rustc_hir::PolyTraitRef;
|
||||||
use rustc_hir::def::{DefKind, Res};
|
use rustc_hir::def::{DefKind, Res};
|
||||||
use rustc_hir::def_id::{CRATE_DEF_ID, DefId, LocalDefId};
|
use rustc_hir::def_id::{CRATE_DEF_ID, DefId, LocalDefId};
|
||||||
use rustc_hir::{AmbigArg, PolyTraitRef};
|
|
||||||
use rustc_middle::bug;
|
use rustc_middle::bug;
|
||||||
use rustc_middle::ty::{
|
use rustc_middle::ty::{
|
||||||
self as ty, IsSuggestable, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitableExt,
|
self as ty, IsSuggestable, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitableExt,
|
||||||
@@ -230,122 +231,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Checks whether `Self: DefaultAutoTrait` bounds should be added on trait super bounds
|
/// Adds `experimental_default_bounds` bounds to the supertrait bounds.
|
||||||
/// or associated items.
|
|
||||||
///
|
|
||||||
/// To keep backward compatibility with existing code, `experimental_default_bounds` bounds
|
|
||||||
/// should be added everywhere, including super bounds. However this causes a huge performance
|
|
||||||
/// costs. For optimization purposes instead of adding default supertraits, bounds
|
|
||||||
/// are added to the associated items:
|
|
||||||
///
|
|
||||||
/// ```ignore(illustrative)
|
|
||||||
/// // Default bounds are generated in the following way:
|
|
||||||
/// trait Trait {
|
|
||||||
/// fn foo(&self) where Self: Leak {}
|
|
||||||
/// }
|
|
||||||
///
|
|
||||||
/// // instead of this:
|
|
||||||
/// trait Trait: Leak {
|
|
||||||
/// fn foo(&self) {}
|
|
||||||
/// }
|
|
||||||
/// ```
|
|
||||||
/// It is not always possible to do this because of backward compatibility:
|
|
||||||
///
|
|
||||||
/// ```ignore(illustrative)
|
|
||||||
/// pub trait Trait<Rhs = Self> {}
|
|
||||||
/// pub trait Trait1 : Trait {}
|
|
||||||
/// //~^ ERROR: `Rhs` requires `DefaultAutoTrait`, but `Self` is not `DefaultAutoTrait`
|
|
||||||
/// ```
|
|
||||||
///
|
|
||||||
/// or:
|
|
||||||
///
|
|
||||||
/// ```ignore(illustrative)
|
|
||||||
/// trait Trait {
|
|
||||||
/// type Type where Self: Sized;
|
|
||||||
/// }
|
|
||||||
/// trait Trait2<T> : Trait<Type = T> {}
|
|
||||||
/// //~^ ERROR: `DefaultAutoTrait` required for `Trait2`, by implicit `Self: DefaultAutoTrait` in `Trait::Type`
|
|
||||||
/// ```
|
|
||||||
///
|
|
||||||
/// Therefore, `experimental_default_bounds` are still being added to supertraits if
|
|
||||||
/// the `SelfTyParam` or `AssocItemConstraint` were found in a trait header.
|
|
||||||
fn requires_default_supertraits(
|
|
||||||
&self,
|
|
||||||
hir_bounds: &'tcx [hir::GenericBound<'tcx>],
|
|
||||||
hir_generics: &'tcx hir::Generics<'tcx>,
|
|
||||||
) -> bool {
|
|
||||||
struct TraitInfoCollector;
|
|
||||||
|
|
||||||
impl<'tcx> hir::intravisit::Visitor<'tcx> for TraitInfoCollector {
|
|
||||||
type Result = ControlFlow<()>;
|
|
||||||
|
|
||||||
fn visit_assoc_item_constraint(
|
|
||||||
&mut self,
|
|
||||||
_constraint: &'tcx hir::AssocItemConstraint<'tcx>,
|
|
||||||
) -> Self::Result {
|
|
||||||
ControlFlow::Break(())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn visit_ty(&mut self, t: &'tcx hir::Ty<'tcx, AmbigArg>) -> Self::Result {
|
|
||||||
if matches!(
|
|
||||||
&t.kind,
|
|
||||||
hir::TyKind::Path(hir::QPath::Resolved(
|
|
||||||
_,
|
|
||||||
hir::Path { res: hir::def::Res::SelfTyParam { .. }, .. },
|
|
||||||
))
|
|
||||||
) {
|
|
||||||
return ControlFlow::Break(());
|
|
||||||
}
|
|
||||||
hir::intravisit::walk_ty(self, t)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut found = false;
|
|
||||||
for bound in hir_bounds {
|
|
||||||
found |= hir::intravisit::walk_param_bound(&mut TraitInfoCollector, bound).is_break();
|
|
||||||
}
|
|
||||||
found |= hir::intravisit::walk_generics(&mut TraitInfoCollector, hir_generics).is_break();
|
|
||||||
found
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Implicitly add `Self: DefaultAutoTrait` clauses on trait associated items if
|
|
||||||
/// they are not added as super trait bounds to the trait itself. See
|
|
||||||
/// `requires_default_supertraits` for more information.
|
|
||||||
pub(crate) fn add_default_trait_item_bounds(
|
|
||||||
&self,
|
|
||||||
trait_item: &hir::TraitItem<'tcx>,
|
|
||||||
bounds: &mut Vec<(ty::Clause<'tcx>, Span)>,
|
|
||||||
) {
|
|
||||||
let tcx = self.tcx();
|
|
||||||
if !tcx.sess.opts.unstable_opts.experimental_default_bounds {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
let parent = tcx.local_parent(trait_item.hir_id().owner.def_id);
|
|
||||||
let hir::Node::Item(parent_trait) = tcx.hir_node_by_def_id(parent) else {
|
|
||||||
unreachable!();
|
|
||||||
};
|
|
||||||
|
|
||||||
let (trait_generics, trait_bounds) = match parent_trait.kind {
|
|
||||||
hir::ItemKind::Trait(_, _, _, _, generics, supertraits, _) => (generics, supertraits),
|
|
||||||
hir::ItemKind::TraitAlias(_, generics, supertraits) => (generics, supertraits),
|
|
||||||
_ => unreachable!(),
|
|
||||||
};
|
|
||||||
|
|
||||||
if !self.requires_default_supertraits(trait_bounds, trait_generics) {
|
|
||||||
let self_ty_where_predicates = (parent, trait_item.generics.predicates);
|
|
||||||
self.add_default_traits(
|
|
||||||
bounds,
|
|
||||||
tcx.types.self_param,
|
|
||||||
&[],
|
|
||||||
Some(self_ty_where_predicates),
|
|
||||||
trait_item.span,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Lazily sets `experimental_default_bounds` to true on trait super bounds.
|
|
||||||
/// See `requires_default_supertraits` for more information.
|
|
||||||
pub(crate) fn add_default_super_traits(
|
pub(crate) fn add_default_super_traits(
|
||||||
&self,
|
&self,
|
||||||
trait_def_id: LocalDefId,
|
trait_def_id: LocalDefId,
|
||||||
@@ -354,21 +240,21 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
|||||||
hir_generics: &'tcx hir::Generics<'tcx>,
|
hir_generics: &'tcx hir::Generics<'tcx>,
|
||||||
span: Span,
|
span: Span,
|
||||||
) {
|
) {
|
||||||
if !self.tcx().sess.opts.unstable_opts.experimental_default_bounds {
|
assert_matches!(self.tcx().def_kind(trait_def_id), DefKind::Trait | DefKind::TraitAlias);
|
||||||
|
|
||||||
|
// Supertraits for auto trait are unsound according to the unstable book:
|
||||||
|
// https://doc.rust-lang.org/beta/unstable-book/language-features/auto-traits.html#supertraits
|
||||||
|
if self.tcx().trait_is_auto(trait_def_id.to_def_id()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
assert!(matches!(self.tcx().def_kind(trait_def_id), DefKind::Trait | DefKind::TraitAlias));
|
self.add_default_traits(
|
||||||
if self.requires_default_supertraits(hir_bounds, hir_generics) {
|
bounds,
|
||||||
let self_ty_where_predicates = (trait_def_id, hir_generics.predicates);
|
self.tcx().types.self_param,
|
||||||
self.add_default_traits(
|
hir_bounds,
|
||||||
bounds,
|
Some((trait_def_id, hir_generics.predicates)),
|
||||||
self.tcx().types.self_param,
|
span,
|
||||||
hir_bounds,
|
);
|
||||||
Some(self_ty_where_predicates),
|
|
||||||
span,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn add_default_traits(
|
pub(crate) fn add_default_traits(
|
||||||
|
|||||||
@@ -47,7 +47,8 @@ impl<'tcx> LateLintPass<'tcx> for MultipleSupertraitUpcastable {
|
|||||||
.explicit_super_predicates_of(def_id)
|
.explicit_super_predicates_of(def_id)
|
||||||
.iter_identity_copied()
|
.iter_identity_copied()
|
||||||
.filter_map(|(pred, _)| pred.as_trait_clause())
|
.filter_map(|(pred, _)| pred.as_trait_clause())
|
||||||
.filter(|pred| !cx.tcx.is_lang_item(pred.def_id(), hir::LangItem::MetaSized));
|
.filter(|pred| !cx.tcx.is_lang_item(pred.def_id(), hir::LangItem::MetaSized))
|
||||||
|
.filter(|pred| !cx.tcx.is_default_trait(pred.def_id()));
|
||||||
if direct_super_traits_iter.count() > 1 {
|
if direct_super_traits_iter.count() > 1 {
|
||||||
cx.emit_span_lint(
|
cx.emit_span_lint(
|
||||||
MULTIPLE_SUPERTRAIT_UPCASTABLE,
|
MULTIPLE_SUPERTRAIT_UPCASTABLE,
|
||||||
|
|||||||
@@ -1,31 +0,0 @@
|
|||||||
//@ check-pass
|
|
||||||
//@ compile-flags: -Zexperimental-default-bounds
|
|
||||||
|
|
||||||
#![feature(auto_traits, lang_items, no_core, rustc_attrs, trait_alias)]
|
|
||||||
#![no_std]
|
|
||||||
#![no_core]
|
|
||||||
|
|
||||||
#[lang = "pointee_sized"]
|
|
||||||
trait PointeeSized {}
|
|
||||||
|
|
||||||
#[lang = "meta_sized"]
|
|
||||||
trait MetaSized: PointeeSized {}
|
|
||||||
|
|
||||||
#[lang = "sized"]
|
|
||||||
trait Sized: MetaSized {}
|
|
||||||
|
|
||||||
#[lang = "default_trait1"]
|
|
||||||
auto trait DefaultTrait1 {}
|
|
||||||
|
|
||||||
#[lang = "default_trait2"]
|
|
||||||
auto trait DefaultTrait2 {}
|
|
||||||
|
|
||||||
trait Trait<Rhs: ?Sized = Self> {}
|
|
||||||
trait Trait1 : Trait {}
|
|
||||||
|
|
||||||
trait Trait2 {
|
|
||||||
type Type;
|
|
||||||
}
|
|
||||||
trait Trait3<T> = Trait2<Type = T>;
|
|
||||||
|
|
||||||
fn main() {}
|
|
||||||
@@ -13,32 +13,37 @@
|
|||||||
#![no_core]
|
#![no_core]
|
||||||
|
|
||||||
#[lang = "pointee_sized"]
|
#[lang = "pointee_sized"]
|
||||||
trait PointeeSized {}
|
trait PointeeSized: ?Leak {}
|
||||||
|
|
||||||
#[lang = "meta_sized"]
|
#[lang = "meta_sized"]
|
||||||
trait MetaSized: PointeeSized {}
|
trait MetaSized: PointeeSized + ?Leak {}
|
||||||
|
|
||||||
#[lang = "sized"]
|
#[lang = "sized"]
|
||||||
trait Sized: MetaSized {}
|
trait Sized: MetaSized + ?Leak {}
|
||||||
|
|
||||||
#[lang = "copy"]
|
#[lang = "copy"]
|
||||||
pub trait Copy {}
|
pub trait Copy: ?Leak {}
|
||||||
impl<'a, T: ?Sized> Copy for &'a T {}
|
impl<'a, T: ?Sized> Copy for &'a T {}
|
||||||
|
|
||||||
#[lang = "legacy_receiver"]
|
#[lang = "legacy_receiver"]
|
||||||
trait Receiver {}
|
trait Receiver: ?Leak {}
|
||||||
impl<T: ?Sized + ?Leak> Receiver for &T {}
|
impl<T: ?Sized + ?Leak> Receiver for &T {}
|
||||||
|
impl<T: ?Sized + ?Leak> Receiver for &mut T {}
|
||||||
|
|
||||||
#[lang = "unsize"]
|
#[lang = "unsize"]
|
||||||
trait Unsize<T: ?Sized + ?Leak> {}
|
trait Unsize<T: ?Sized + ?Leak>: ?Leak {}
|
||||||
|
|
||||||
#[lang = "coerce_unsized"]
|
#[lang = "coerce_unsized"]
|
||||||
trait CoerceUnsized<T: ?Leak + ?Sized> {}
|
trait CoerceUnsized<T: ?Leak + ?Sized>: ?Leak {}
|
||||||
impl<'a, 'b: 'a, T: ?Sized + ?Leak + Unsize<U>, U: ?Sized + ?Leak> CoerceUnsized<&'a U> for &'b T {}
|
impl<'a, 'b: 'a, T: ?Sized + ?Leak + Unsize<U>, U: ?Sized + ?Leak> CoerceUnsized<&'a U> for &'b T {}
|
||||||
|
// Omit `T: ?Leak` and `U: ?Leak`.
|
||||||
|
impl<'a, 'b: 'a, T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<&'a mut U> for &'b mut T {}
|
||||||
|
|
||||||
#[lang = "dispatch_from_dyn"]
|
#[lang = "dispatch_from_dyn"]
|
||||||
trait DispatchFromDyn<T: ?Leak> {}
|
trait DispatchFromDyn<T: ?Leak>: ?Leak {}
|
||||||
impl<'a, T: ?Sized + ?Leak + Unsize<U>, U: ?Sized + ?Leak> DispatchFromDyn<&'a U> for &'a T {}
|
impl<'a, T: ?Sized + ?Leak + Unsize<U>, U: ?Sized + ?Leak> DispatchFromDyn<&'a U> for &'a T {}
|
||||||
|
// Omit `T: ?Leak` and `U: ?Leak`.
|
||||||
|
impl<'a, T: ?Sized + Unsize<U>, U: ?Sized> DispatchFromDyn<&'a mut U> for &'a mut T {}
|
||||||
|
|
||||||
#[lang = "default_trait1"]
|
#[lang = "default_trait1"]
|
||||||
auto trait Leak {}
|
auto trait Leak {}
|
||||||
@@ -47,25 +52,52 @@ struct NonLeakS;
|
|||||||
impl !Leak for NonLeakS {}
|
impl !Leak for NonLeakS {}
|
||||||
struct LeakS;
|
struct LeakS;
|
||||||
|
|
||||||
trait Trait {
|
fn bounds_check() {
|
||||||
fn leak_foo(&self) {}
|
trait LeakTr {}
|
||||||
fn maybe_leak_foo(&self) where Self: ?Leak {}
|
|
||||||
|
trait MaybeLeakTr: ?Leak {}
|
||||||
|
|
||||||
|
impl MaybeLeakTr for NonLeakS {}
|
||||||
|
|
||||||
|
impl LeakTr for LeakS {}
|
||||||
|
impl MaybeLeakTr for LeakS {}
|
||||||
|
|
||||||
|
let _: &dyn LeakTr = &NonLeakS;
|
||||||
|
//~^ ERROR the trait bound `NonLeakS: bounds_check::LeakTr` is not satisfied
|
||||||
|
let _: &dyn LeakTr = &LeakS;
|
||||||
|
|
||||||
|
let _: &(dyn LeakTr + ?Leak) = &NonLeakS;
|
||||||
|
let _: &(dyn LeakTr + ?Leak) = &LeakS;
|
||||||
|
|
||||||
|
let _: &dyn MaybeLeakTr = &NonLeakS;
|
||||||
|
let _: &dyn MaybeLeakTr = &LeakS;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Trait for NonLeakS {}
|
fn dyn_compat_check() {
|
||||||
impl Trait for LeakS {}
|
trait DynCompatCheck1: ?Leak {
|
||||||
|
fn foo(&self) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
trait DynCompatCheck2: ?Leak {
|
||||||
|
fn mut_foo(&mut self) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl DynCompatCheck1 for NonLeakS {}
|
||||||
|
impl DynCompatCheck2 for NonLeakS {}
|
||||||
|
|
||||||
|
let _: &(dyn DynCompatCheck1 + ?Leak) = &NonLeakS;
|
||||||
|
// There is no `?Leak` bound on corresponding `DispatchFromDyn` impl.
|
||||||
|
let _: &dyn DynCompatCheck2 = &NonLeakS;
|
||||||
|
//~^ ERROR the trait `DynCompatCheck2` is not dyn compatible
|
||||||
|
}
|
||||||
|
|
||||||
|
fn args_check() {
|
||||||
|
trait LeakTr {}
|
||||||
|
|
||||||
fn main() {
|
|
||||||
let _: &dyn Trait = &NonLeakS;
|
|
||||||
//~^ ERROR the trait bound `NonLeakS: Leak` is not satisfied
|
|
||||||
let _: &dyn Trait = &LeakS;
|
|
||||||
let _: &(dyn Trait + ?Leak) = &LeakS;
|
|
||||||
let x: &(dyn Trait + ?Leak) = &NonLeakS;
|
|
||||||
x.leak_foo();
|
|
||||||
//~^ ERROR the trait bound `dyn Trait: Leak` is not satisfied
|
|
||||||
x.maybe_leak_foo();
|
|
||||||
// Ensure that we validate the generic args of relaxed bounds in trait object types.
|
// Ensure that we validate the generic args of relaxed bounds in trait object types.
|
||||||
let _: dyn Trait + ?Leak<(), Undefined = ()>;
|
let _: dyn LeakTr + ?Leak<(), Undefined = ()>;
|
||||||
//~^ ERROR trait takes 0 generic arguments but 1 generic argument was supplied
|
//~^ ERROR trait takes 0 generic arguments but 1 generic argument was supplied
|
||||||
//~| ERROR associated type `Undefined` not found for `Leak`
|
//~| ERROR associated type `Undefined` not found for `Leak`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn main() {}
|
||||||
|
|||||||
@@ -1,49 +1,57 @@
|
|||||||
error[E0277]: the trait bound `NonLeakS: Leak` is not satisfied
|
error[E0277]: the trait bound `NonLeakS: bounds_check::LeakTr` is not satisfied
|
||||||
--> $DIR/maybe-bounds-in-dyn-traits.rs:59:25
|
--> $DIR/maybe-bounds-in-dyn-traits.rs:65:26
|
||||||
|
|
|
|
||||||
LL | let _: &dyn Trait = &NonLeakS;
|
LL | let _: &dyn LeakTr = &NonLeakS;
|
||||||
| ^^^^^^^^^ unsatisfied trait bound
|
| ^^^^^^^^^ unsatisfied trait bound
|
||||||
|
|
|
|
||||||
help: the trait `Leak` is not implemented for `NonLeakS`
|
help: the trait `bounds_check::LeakTr` is not implemented for `NonLeakS`
|
||||||
--> $DIR/maybe-bounds-in-dyn-traits.rs:46:1
|
--> $DIR/maybe-bounds-in-dyn-traits.rs:51:1
|
||||||
|
|
|
|
||||||
LL | struct NonLeakS;
|
LL | struct NonLeakS;
|
||||||
| ^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^
|
||||||
= note: required for the cast from `&NonLeakS` to `&dyn Trait + Leak`
|
= help: the trait `bounds_check::LeakTr` is implemented for `LeakS`
|
||||||
|
= note: required for the cast from `&NonLeakS` to `&dyn bounds_check::LeakTr + Leak`
|
||||||
|
|
||||||
error[E0277]: the trait bound `dyn Trait: Leak` is not satisfied
|
error[E0038]: the trait `DynCompatCheck2` is not dyn compatible
|
||||||
--> $DIR/maybe-bounds-in-dyn-traits.rs:64:7
|
--> $DIR/maybe-bounds-in-dyn-traits.rs:90:17
|
||||||
|
|
|
|
||||||
LL | x.leak_foo();
|
LL | fn mut_foo(&mut self) {}
|
||||||
| ^^^^^^^^ the trait `Leak` is not implemented for `dyn Trait`
|
| --------- help: consider changing method `mut_foo`'s `self` parameter to be `&self`: `&Self`
|
||||||
|
...
|
||||||
|
LL | let _: &dyn DynCompatCheck2 = &NonLeakS;
|
||||||
|
| ^^^^^^^^^^^^^^^ `DynCompatCheck2` is not dyn compatible
|
||||||
|
|
|
|
||||||
note: required by a bound in `Trait::leak_foo`
|
note: for a trait to be dyn compatible it needs to allow building a vtable
|
||||||
--> $DIR/maybe-bounds-in-dyn-traits.rs:51:5
|
for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
|
||||||
|
--> $DIR/maybe-bounds-in-dyn-traits.rs:82:20
|
||||||
|
|
|
|
||||||
LL | fn leak_foo(&self) {}
|
LL | trait DynCompatCheck2: ?Leak {
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Trait::leak_foo`
|
| --------------- this trait is not dyn compatible...
|
||||||
|
LL | fn mut_foo(&mut self) {}
|
||||||
|
| ^^^^^^^^^ ...because method `mut_foo`'s `self` parameter cannot be dispatched on
|
||||||
|
= help: only type `NonLeakS` implements `DynCompatCheck2`; consider using it directly instead.
|
||||||
|
|
||||||
error[E0107]: trait takes 0 generic arguments but 1 generic argument was supplied
|
error[E0107]: trait takes 0 generic arguments but 1 generic argument was supplied
|
||||||
--> $DIR/maybe-bounds-in-dyn-traits.rs:68:25
|
--> $DIR/maybe-bounds-in-dyn-traits.rs:98:26
|
||||||
|
|
|
|
||||||
LL | let _: dyn Trait + ?Leak<(), Undefined = ()>;
|
LL | let _: dyn LeakTr + ?Leak<(), Undefined = ()>;
|
||||||
| ^^^^-------------------- help: remove the unnecessary generics
|
| ^^^^-------------------- help: remove the unnecessary generics
|
||||||
| |
|
| |
|
||||||
| expected 0 generic arguments
|
| expected 0 generic arguments
|
||||||
|
|
|
|
||||||
note: trait defined here, with 0 generic parameters
|
note: trait defined here, with 0 generic parameters
|
||||||
--> $DIR/maybe-bounds-in-dyn-traits.rs:44:12
|
--> $DIR/maybe-bounds-in-dyn-traits.rs:49:12
|
||||||
|
|
|
|
||||||
LL | auto trait Leak {}
|
LL | auto trait Leak {}
|
||||||
| ^^^^
|
| ^^^^
|
||||||
|
|
||||||
error[E0220]: associated type `Undefined` not found for `Leak`
|
error[E0220]: associated type `Undefined` not found for `Leak`
|
||||||
--> $DIR/maybe-bounds-in-dyn-traits.rs:68:34
|
--> $DIR/maybe-bounds-in-dyn-traits.rs:98:35
|
||||||
|
|
|
|
||||||
LL | let _: dyn Trait + ?Leak<(), Undefined = ()>;
|
LL | let _: dyn LeakTr + ?Leak<(), Undefined = ()>;
|
||||||
| ^^^^^^^^^ associated type `Undefined` not found
|
| ^^^^^^^^^ associated type `Undefined` not found
|
||||||
|
|
||||||
error: aborting due to 4 previous errors
|
error: aborting due to 4 previous errors
|
||||||
|
|
||||||
Some errors have detailed explanations: E0107, E0220, E0277.
|
Some errors have detailed explanations: E0038, E0107, E0220, E0277.
|
||||||
For more information about an error, try `rustc --explain E0107`.
|
For more information about an error, try `rustc --explain E0038`.
|
||||||
|
|||||||
@@ -14,18 +14,22 @@
|
|||||||
#![no_std]
|
#![no_std]
|
||||||
#![no_core]
|
#![no_core]
|
||||||
|
|
||||||
|
#[lang = "copy"]
|
||||||
|
pub trait Copy: ?Leak {}
|
||||||
|
|
||||||
#[lang = "pointee_sized"]
|
#[lang = "pointee_sized"]
|
||||||
trait PointeeSized {}
|
trait PointeeSized: ?Leak {}
|
||||||
|
|
||||||
#[lang = "meta_sized"]
|
#[lang = "meta_sized"]
|
||||||
trait MetaSized: PointeeSized {}
|
trait MetaSized: PointeeSized + ?Leak {}
|
||||||
|
|
||||||
#[lang = "sized"]
|
#[lang = "sized"]
|
||||||
trait Sized: MetaSized {}
|
trait Sized: MetaSized + ?Leak {}
|
||||||
|
|
||||||
#[lang = "legacy_receiver"]
|
#[lang = "legacy_receiver"]
|
||||||
trait LegacyReceiver {}
|
trait LegacyReceiver: ?Leak {}
|
||||||
impl<T: ?Sized + ?Leak> LegacyReceiver for &T {}
|
impl<T: ?Sized + ?Leak> LegacyReceiver for &T {}
|
||||||
|
// Omit `T: ?Leak`.
|
||||||
impl<T: ?Sized> LegacyReceiver for &mut T {}
|
impl<T: ?Sized> LegacyReceiver for &mut T {}
|
||||||
|
|
||||||
#[lang = "default_trait1"]
|
#[lang = "default_trait1"]
|
||||||
@@ -43,78 +47,38 @@ mod supertraits {
|
|||||||
|
|
||||||
impl MaybeLeakT1 for NonLeakS {}
|
impl MaybeLeakT1 for NonLeakS {}
|
||||||
impl MaybeLeakT2 for NonLeakS {}
|
impl MaybeLeakT2 for NonLeakS {}
|
||||||
|
|
||||||
|
trait LeakT {}
|
||||||
|
impl LeakT for NonLeakS {}
|
||||||
|
//~^ ERROR the trait bound `NonLeakS: Leak` is not satisfied
|
||||||
}
|
}
|
||||||
|
|
||||||
mod maybe_self_assoc_type {
|
mod assoc_type_maybe_bounds {
|
||||||
use crate::*;
|
use crate::*;
|
||||||
|
|
||||||
trait TestBase1<T: ?Sized> {}
|
trait Test1 {
|
||||||
trait TestBase2<T: ?Leak + ?Sized> {}
|
|
||||||
|
|
||||||
trait Test1<T> {
|
|
||||||
type MaybeLeakSelf: TestBase1<Self> where Self: ?Leak;
|
|
||||||
//~^ ERROR the trait bound `Self: Leak` is not satisfied
|
|
||||||
type LeakSelf: TestBase1<Self>;
|
|
||||||
}
|
|
||||||
|
|
||||||
trait Test2<T> {
|
|
||||||
type MaybeLeakSelf: TestBase2<Self> where Self: ?Leak;
|
|
||||||
type LeakSelf: TestBase2<Self>;
|
|
||||||
}
|
|
||||||
|
|
||||||
trait Test3 {
|
|
||||||
type Leak1 = LeakS;
|
type Leak1 = LeakS;
|
||||||
type Leak2 = NonLeakS;
|
type Leak2 = NonLeakS;
|
||||||
//~^ ERROR the trait bound `NonLeakS: Leak` is not satisfied
|
//~^ ERROR the trait bound `NonLeakS: Leak` is not satisfied
|
||||||
}
|
}
|
||||||
|
|
||||||
trait Test4 {
|
trait Test2 {
|
||||||
type MaybeLeak1: ?Leak = LeakS;
|
type MaybeLeak1: ?Leak = LeakS;
|
||||||
type MaybeLeak2: ?Leak = NonLeakS;
|
type MaybeLeak2: ?Leak = NonLeakS;
|
||||||
}
|
}
|
||||||
|
|
||||||
trait Test5: ?Leak {
|
|
||||||
// ok, because assoc types have implicit where Self: Leak
|
|
||||||
type MaybeLeakSelf1: TestBase1<Self>;
|
|
||||||
type MaybeLeakSelf2: TestBase2<Self>;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
mod maybe_self_assoc_const {
|
|
||||||
use crate::*;
|
|
||||||
|
|
||||||
const fn size_of<T: ?Sized>() -> usize {
|
|
||||||
0
|
|
||||||
}
|
|
||||||
|
|
||||||
trait Trait {
|
|
||||||
const CLeak: usize = size_of::<Self>();
|
|
||||||
const CNonLeak: usize = size_of::<Self>() where Self: ?Leak;
|
|
||||||
//~^ ERROR the trait bound `Self: Leak` is not satisfied
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
mod methods {
|
mod methods {
|
||||||
use crate::*;
|
use crate::*;
|
||||||
|
|
||||||
trait Trait {
|
trait ReceiveCheck1: ?Leak {
|
||||||
fn leak_foo(&self) {}
|
fn foo(&self) {}
|
||||||
fn maybe_leak_foo(&self) where Self: ?Leak {}
|
|
||||||
fn mut_leak_foo(&mut self) {}
|
|
||||||
// there is no relax bound on corresponding Receiver impl
|
|
||||||
fn mut_maybe_leak_foo(&mut self) where Self: ?Leak {}
|
|
||||||
//~^ ERROR `&mut Self` cannot be used as the type of `self` without the `arbitrary_self_types`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Trait for NonLeakS {}
|
trait ReceiveCheck2: ?Leak {
|
||||||
impl Trait for LeakS {}
|
// There is no `?Leak` bound on corresponding `LegacyReceiver` impl.
|
||||||
|
fn mut_foo(&mut self) {}
|
||||||
fn foo() {
|
//~^ ERROR `&mut Self` cannot be used as the type of `self` without the `arbitrary_self_types`
|
||||||
LeakS.leak_foo();
|
|
||||||
LeakS.maybe_leak_foo();
|
|
||||||
NonLeakS.leak_foo();
|
|
||||||
//~^ ERROR the trait bound `NonLeakS: Leak` is not satisfied
|
|
||||||
NonLeakS.maybe_leak_foo();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,81 +1,49 @@
|
|||||||
error[E0277]: the trait bound `NonLeakS: Leak` is not satisfied
|
error[E0277]: the trait bound `NonLeakS: Leak` is not satisfied
|
||||||
--> $DIR/maybe-bounds-in-traits.rs:67:22
|
--> $DIR/maybe-bounds-in-traits.rs:52:20
|
||||||
|
|
|
||||||
|
LL | impl LeakT for NonLeakS {}
|
||||||
|
| ^^^^^^^^ unsatisfied trait bound
|
||||||
|
|
|
||||||
|
help: the trait `Leak` is not implemented for `NonLeakS`
|
||||||
|
--> $DIR/maybe-bounds-in-traits.rs:38:1
|
||||||
|
|
|
||||||
|
LL | struct NonLeakS;
|
||||||
|
| ^^^^^^^^^^^^^^^
|
||||||
|
note: required by a bound in `LeakT`
|
||||||
|
--> $DIR/maybe-bounds-in-traits.rs:51:5
|
||||||
|
|
|
||||||
|
LL | trait LeakT {}
|
||||||
|
| ^^^^^^^^^^^^^^ required by this bound in `LeakT`
|
||||||
|
|
||||||
|
error[E0277]: the trait bound `NonLeakS: Leak` is not satisfied
|
||||||
|
--> $DIR/maybe-bounds-in-traits.rs:61:22
|
||||||
|
|
|
|
||||||
LL | type Leak2 = NonLeakS;
|
LL | type Leak2 = NonLeakS;
|
||||||
| ^^^^^^^^ unsatisfied trait bound
|
| ^^^^^^^^ unsatisfied trait bound
|
||||||
|
|
|
|
||||||
help: the trait `Leak` is not implemented for `NonLeakS`
|
help: the trait `Leak` is not implemented for `NonLeakS`
|
||||||
--> $DIR/maybe-bounds-in-traits.rs:34:1
|
--> $DIR/maybe-bounds-in-traits.rs:38:1
|
||||||
|
|
|
|
||||||
LL | struct NonLeakS;
|
LL | struct NonLeakS;
|
||||||
| ^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^
|
||||||
note: required by a bound in `Test3::Leak2`
|
note: required by a bound in `Test1::Leak2`
|
||||||
--> $DIR/maybe-bounds-in-traits.rs:67:9
|
--> $DIR/maybe-bounds-in-traits.rs:61:9
|
||||||
|
|
|
|
||||||
LL | type Leak2 = NonLeakS;
|
LL | type Leak2 = NonLeakS;
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Test3::Leak2`
|
| ^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Test1::Leak2`
|
||||||
|
|
||||||
error[E0277]: the trait bound `Self: Leak` is not satisfied
|
|
||||||
--> $DIR/maybe-bounds-in-traits.rs:55:29
|
|
||||||
|
|
|
||||||
LL | type MaybeLeakSelf: TestBase1<Self> where Self: ?Leak;
|
|
||||||
| ^^^^^^^^^^^^^^^ the trait `Leak` is not implemented for `Self`
|
|
||||||
|
|
|
||||||
note: required by a bound in `TestBase1`
|
|
||||||
--> $DIR/maybe-bounds-in-traits.rs:51:21
|
|
||||||
|
|
|
||||||
LL | trait TestBase1<T: ?Sized> {}
|
|
||||||
| ^ required by this bound in `TestBase1`
|
|
||||||
help: consider further restricting `Self`
|
|
||||||
|
|
|
||||||
LL | trait Test1<T>: Leak {
|
|
||||||
| ++++++
|
|
||||||
|
|
||||||
error[E0658]: `&mut Self` cannot be used as the type of `self` without the `arbitrary_self_types` feature
|
error[E0658]: `&mut Self` cannot be used as the type of `self` without the `arbitrary_self_types` feature
|
||||||
--> $DIR/maybe-bounds-in-traits.rs:105:31
|
--> $DIR/maybe-bounds-in-traits.rs:80:20
|
||||||
|
|
|
|
||||||
LL | fn mut_maybe_leak_foo(&mut self) where Self: ?Leak {}
|
LL | fn mut_foo(&mut self) {}
|
||||||
| ^^^^^^^^^
|
| ^^^^^^^^^
|
||||||
|
|
|
|
||||||
= note: see issue #44874 <https://github.com/rust-lang/rust/issues/44874> for more information
|
= note: see issue #44874 <https://github.com/rust-lang/rust/issues/44874> for more information
|
||||||
= help: add `#![feature(arbitrary_self_types)]` to the crate attributes to enable
|
= help: add `#![feature(arbitrary_self_types)]` to the crate attributes to enable
|
||||||
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
|
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
|
||||||
= help: consider changing to `self`, `&self`, `&mut self`, or a type implementing `Receiver` such as `self: Box<Self>`, `self: Rc<Self>`, or `self: Arc<Self>`
|
= help: consider changing to `self`, `&self`, `&mut self`, or a type implementing `Receiver` such as `self: Box<Self>`, `self: Rc<Self>`, or `self: Arc<Self>`
|
||||||
|
|
||||||
error[E0277]: the trait bound `Self: Leak` is not satisfied
|
error: aborting due to 3 previous errors
|
||||||
--> $DIR/maybe-bounds-in-traits.rs:92:43
|
|
||||||
|
|
|
||||||
LL | const CNonLeak: usize = size_of::<Self>() where Self: ?Leak;
|
|
||||||
| ^^^^ the trait `Leak` is not implemented for `Self`
|
|
||||||
|
|
|
||||||
note: required by a bound in `size_of`
|
|
||||||
--> $DIR/maybe-bounds-in-traits.rs:86:22
|
|
||||||
|
|
|
||||||
LL | const fn size_of<T: ?Sized>() -> usize {
|
|
||||||
| ^ required by this bound in `size_of`
|
|
||||||
help: consider further restricting `Self`
|
|
||||||
|
|
|
||||||
LL | trait Trait: Leak {
|
|
||||||
| ++++++
|
|
||||||
|
|
||||||
error[E0277]: the trait bound `NonLeakS: Leak` is not satisfied
|
|
||||||
--> $DIR/maybe-bounds-in-traits.rs:115:18
|
|
||||||
|
|
|
||||||
LL | NonLeakS.leak_foo();
|
|
||||||
| ^^^^^^^^ unsatisfied trait bound
|
|
||||||
|
|
|
||||||
help: the trait `Leak` is not implemented for `NonLeakS`
|
|
||||||
--> $DIR/maybe-bounds-in-traits.rs:34:1
|
|
||||||
|
|
|
||||||
LL | struct NonLeakS;
|
|
||||||
| ^^^^^^^^^^^^^^^
|
|
||||||
note: required by a bound in `methods::Trait::leak_foo`
|
|
||||||
--> $DIR/maybe-bounds-in-traits.rs:101:9
|
|
||||||
|
|
|
||||||
LL | fn leak_foo(&self) {}
|
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Trait::leak_foo`
|
|
||||||
|
|
||||||
error: aborting due to 5 previous errors
|
|
||||||
|
|
||||||
Some errors have detailed explanations: E0277, E0658.
|
Some errors have detailed explanations: E0277, E0658.
|
||||||
For more information about an error, try `rustc --explain E0277`.
|
For more information about an error, try `rustc --explain E0277`.
|
||||||
|
|||||||
Reference in New Issue
Block a user