Support ?Trait bounds in supertraits and dyn Trait under a feature gate
This commit is contained in:
parent
28e684b470
commit
2a73553513
@ -1525,8 +1525,14 @@ fn lower_generics<T>(
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
let is_param = *is_param.get_or_insert_with(compute_is_param);
|
let is_param = *is_param.get_or_insert_with(compute_is_param);
|
||||||
if !is_param {
|
if !is_param && !self.tcx.features().more_maybe_bounds {
|
||||||
self.dcx().emit_err(MisplacedRelaxTraitBound { span: bound.span() });
|
self.tcx
|
||||||
|
.sess
|
||||||
|
.create_feature_err(
|
||||||
|
MisplacedRelaxTraitBound { span: bound.span() },
|
||||||
|
sym::more_maybe_bounds,
|
||||||
|
)
|
||||||
|
.emit();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1216,6 +1216,7 @@ fn lower_path_ty(
|
|||||||
itctx,
|
itctx,
|
||||||
TraitBoundModifiers::NONE,
|
TraitBoundModifiers::NONE,
|
||||||
);
|
);
|
||||||
|
let bound = (bound, hir::TraitBoundModifier::None);
|
||||||
let bounds = this.arena.alloc_from_iter([bound]);
|
let bounds = this.arena.alloc_from_iter([bound]);
|
||||||
let lifetime_bound = this.elided_dyn_bound(t.span);
|
let lifetime_bound = this.elided_dyn_bound(t.span);
|
||||||
(bounds, lifetime_bound)
|
(bounds, lifetime_bound)
|
||||||
@ -1348,21 +1349,17 @@ fn lower_ty_direct(&mut self, t: &Ty, itctx: ImplTraitContext) -> hir::Ty<'hir>
|
|||||||
// We can safely ignore constness here since AST validation
|
// We can safely ignore constness here since AST validation
|
||||||
// takes care of rejecting invalid modifier combinations and
|
// takes care of rejecting invalid modifier combinations and
|
||||||
// const trait bounds in trait object types.
|
// const trait bounds in trait object types.
|
||||||
GenericBound::Trait(ty, modifiers) => match modifiers.polarity {
|
GenericBound::Trait(ty, modifiers) => {
|
||||||
BoundPolarity::Positive | BoundPolarity::Negative(_) => {
|
// Still, don't pass along the constness here; we don't want to
|
||||||
Some(this.lower_poly_trait_ref(
|
// synthesize any host effect args, it'd only cause problems.
|
||||||
ty,
|
let modifiers = TraitBoundModifiers {
|
||||||
itctx,
|
constness: BoundConstness::Never,
|
||||||
// Still, don't pass along the constness here; we don't want to
|
..*modifiers
|
||||||
// synthesize any host effect args, it'd only cause problems.
|
};
|
||||||
TraitBoundModifiers {
|
let trait_ref = this.lower_poly_trait_ref(ty, itctx, modifiers);
|
||||||
constness: BoundConstness::Never,
|
let polarity = this.lower_trait_bound_modifiers(modifiers);
|
||||||
..*modifiers
|
Some((trait_ref, polarity))
|
||||||
},
|
}
|
||||||
))
|
|
||||||
}
|
|
||||||
BoundPolarity::Maybe(_) => None,
|
|
||||||
},
|
|
||||||
GenericBound::Outlives(lifetime) => {
|
GenericBound::Outlives(lifetime) => {
|
||||||
if lifetime_bound.is_none() {
|
if lifetime_bound.is_none() {
|
||||||
lifetime_bound = Some(this.lower_lifetime(lifetime));
|
lifetime_bound = Some(this.lower_lifetime(lifetime));
|
||||||
@ -2688,6 +2685,7 @@ fn ty_path(&mut self, mut hir_id: HirId, span: Span, qpath: hir::QPath<'hir>) ->
|
|||||||
trait_ref: hir::TraitRef { path, hir_ref_id: hir_id },
|
trait_ref: hir::TraitRef { path, hir_ref_id: hir_id },
|
||||||
span: self.lower_span(span),
|
span: self.lower_span(span),
|
||||||
};
|
};
|
||||||
|
let principal = (principal, hir::TraitBoundModifier::None);
|
||||||
|
|
||||||
// The original ID is taken by the `PolyTraitRef`,
|
// The original ID is taken by the `PolyTraitRef`,
|
||||||
// so the `Ty` itself needs a different one.
|
// so the `Ty` itself needs a different one.
|
||||||
|
@ -1345,14 +1345,28 @@ fn visit_param_bound(&mut self, bound: &'a GenericBound, ctxt: BoundKind) {
|
|||||||
match bound {
|
match bound {
|
||||||
GenericBound::Trait(trait_ref, modifiers) => {
|
GenericBound::Trait(trait_ref, modifiers) => {
|
||||||
match (ctxt, modifiers.constness, modifiers.polarity) {
|
match (ctxt, modifiers.constness, modifiers.polarity) {
|
||||||
(BoundKind::SuperTraits, BoundConstness::Never, BoundPolarity::Maybe(_)) => {
|
(BoundKind::SuperTraits, BoundConstness::Never, BoundPolarity::Maybe(_))
|
||||||
self.dcx().emit_err(errors::OptionalTraitSupertrait {
|
if !self.features.more_maybe_bounds =>
|
||||||
span: trait_ref.span,
|
{
|
||||||
path_str: pprust::path_to_string(&trait_ref.trait_ref.path),
|
self.session
|
||||||
});
|
.create_feature_err(
|
||||||
|
errors::OptionalTraitSupertrait {
|
||||||
|
span: trait_ref.span,
|
||||||
|
path_str: pprust::path_to_string(&trait_ref.trait_ref.path),
|
||||||
|
},
|
||||||
|
sym::more_maybe_bounds,
|
||||||
|
)
|
||||||
|
.emit();
|
||||||
}
|
}
|
||||||
(BoundKind::TraitObject, BoundConstness::Never, BoundPolarity::Maybe(_)) => {
|
(BoundKind::TraitObject, BoundConstness::Never, BoundPolarity::Maybe(_))
|
||||||
self.dcx().emit_err(errors::OptionalTraitObject { span: trait_ref.span });
|
if !self.features.more_maybe_bounds =>
|
||||||
|
{
|
||||||
|
self.session
|
||||||
|
.create_feature_err(
|
||||||
|
errors::OptionalTraitObject { span: trait_ref.span },
|
||||||
|
sym::more_maybe_bounds,
|
||||||
|
)
|
||||||
|
.emit();
|
||||||
}
|
}
|
||||||
(
|
(
|
||||||
BoundKind::TraitObject,
|
BoundKind::TraitObject,
|
||||||
|
@ -205,6 +205,8 @@ pub fn internal(&self, feature: Symbol) -> bool {
|
|||||||
(unstable, lifetime_capture_rules_2024, "1.76.0", None),
|
(unstable, lifetime_capture_rules_2024, "1.76.0", None),
|
||||||
/// Allows `#[link(..., cfg(..))]`; perma-unstable per #37406
|
/// Allows `#[link(..., cfg(..))]`; perma-unstable per #37406
|
||||||
(unstable, link_cfg, "1.14.0", None),
|
(unstable, link_cfg, "1.14.0", None),
|
||||||
|
/// Allows using `?Trait` trait bounds in more contexts.
|
||||||
|
(internal, more_maybe_bounds, "CURRENT_RUSTC_VERSION", None),
|
||||||
/// Allows the `multiple_supertrait_upcastable` lint.
|
/// Allows the `multiple_supertrait_upcastable` lint.
|
||||||
(unstable, multiple_supertrait_upcastable, "1.69.0", None),
|
(unstable, multiple_supertrait_upcastable, "1.69.0", None),
|
||||||
/// Allow negative trait bounds. This is an internal-only feature for testing the trait solver!
|
/// Allow negative trait bounds. This is an internal-only feature for testing the trait solver!
|
||||||
|
@ -2832,7 +2832,11 @@ pub enum TyKind<'hir> {
|
|||||||
OpaqueDef(ItemId, &'hir [GenericArg<'hir>], bool),
|
OpaqueDef(ItemId, &'hir [GenericArg<'hir>], bool),
|
||||||
/// A trait object type `Bound1 + Bound2 + Bound3`
|
/// A trait object type `Bound1 + Bound2 + Bound3`
|
||||||
/// where `Bound` is a trait or a lifetime.
|
/// where `Bound` is a trait or a lifetime.
|
||||||
TraitObject(&'hir [PolyTraitRef<'hir>], &'hir Lifetime, TraitObjectSyntax),
|
TraitObject(
|
||||||
|
&'hir [(PolyTraitRef<'hir>, TraitBoundModifier)],
|
||||||
|
&'hir Lifetime,
|
||||||
|
TraitObjectSyntax,
|
||||||
|
),
|
||||||
/// Unused for now.
|
/// Unused for now.
|
||||||
Typeof(&'hir AnonConst),
|
Typeof(&'hir AnonConst),
|
||||||
/// `TyKind::Infer` means the type should be inferred instead of it having been
|
/// `TyKind::Infer` means the type should be inferred instead of it having been
|
||||||
|
@ -902,7 +902,9 @@ pub fn walk_ty<'v, V: Visitor<'v>>(visitor: &mut V, typ: &'v Ty<'v>) -> V::Resul
|
|||||||
try_visit!(visitor.visit_array_length(length));
|
try_visit!(visitor.visit_array_length(length));
|
||||||
}
|
}
|
||||||
TyKind::TraitObject(bounds, ref lifetime, _syntax) => {
|
TyKind::TraitObject(bounds, ref lifetime, _syntax) => {
|
||||||
walk_list!(visitor, visit_poly_trait_ref, bounds);
|
for (bound, _modifier) in bounds {
|
||||||
|
try_visit!(visitor.visit_poly_trait_ref(bound));
|
||||||
|
}
|
||||||
try_visit!(visitor.visit_lifetime(lifetime));
|
try_visit!(visitor.visit_lifetime(lifetime));
|
||||||
}
|
}
|
||||||
TyKind::Typeof(ref expression) => try_visit!(visitor.visit_anon_const(expression)),
|
TyKind::Typeof(ref expression) => try_visit!(visitor.visit_anon_const(expression)),
|
||||||
|
@ -831,7 +831,7 @@ fn visit_ty(&mut self, t: Ty<'tcx>) {
|
|||||||
|
|
||||||
fn could_be_self(trait_def_id: LocalDefId, ty: &hir::Ty<'_>) -> bool {
|
fn could_be_self(trait_def_id: LocalDefId, ty: &hir::Ty<'_>) -> bool {
|
||||||
match ty.kind {
|
match ty.kind {
|
||||||
hir::TyKind::TraitObject([trait_ref], ..) => match trait_ref.trait_ref.path.segments {
|
hir::TyKind::TraitObject([(trait_ref, _)], ..) => match trait_ref.trait_ref.path.segments {
|
||||||
[s] => s.res.opt_def_id() == Some(trait_def_id.to_def_id()),
|
[s] => s.res.opt_def_id() == Some(trait_def_id.to_def_id()),
|
||||||
_ => false,
|
_ => false,
|
||||||
},
|
},
|
||||||
|
@ -652,7 +652,7 @@ fn visit_ty(&mut self, ty: &'tcx hir::Ty<'tcx>) {
|
|||||||
debug!(?bounds, ?lifetime, "TraitObject");
|
debug!(?bounds, ?lifetime, "TraitObject");
|
||||||
let scope = Scope::TraitRefBoundary { s: self.scope };
|
let scope = Scope::TraitRefBoundary { s: self.scope };
|
||||||
self.with(scope, |this| {
|
self.with(scope, |this| {
|
||||||
for bound in bounds {
|
for (bound, _) in bounds {
|
||||||
this.visit_poly_trait_ref_inner(
|
this.visit_poly_trait_ref_inner(
|
||||||
bound,
|
bound,
|
||||||
NonLifetimeBinderAllowed::Deny("trait object types"),
|
NonLifetimeBinderAllowed::Deny("trait object types"),
|
||||||
|
@ -9,7 +9,7 @@
|
|||||||
use rustc_middle::ty::print::PrintTraitRefExt as _;
|
use rustc_middle::ty::print::PrintTraitRefExt as _;
|
||||||
use rustc_middle::ty::{self as ty, IsSuggestable, Ty, TyCtxt};
|
use rustc_middle::ty::{self as ty, IsSuggestable, Ty, TyCtxt};
|
||||||
use rustc_span::symbol::Ident;
|
use rustc_span::symbol::Ident;
|
||||||
use rustc_span::{ErrorGuaranteed, Span, Symbol};
|
use rustc_span::{sym, ErrorGuaranteed, Span, Symbol};
|
||||||
use rustc_trait_selection::traits;
|
use rustc_trait_selection::traits;
|
||||||
use rustc_type_ir::visit::{TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor};
|
use rustc_type_ir::visit::{TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor};
|
||||||
use smallvec::SmallVec;
|
use smallvec::SmallVec;
|
||||||
@ -75,10 +75,16 @@ pub(crate) fn add_sized_bound(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if unbounds.len() > 1 {
|
if unbounds.len() > 1 && !tcx.features().more_maybe_bounds {
|
||||||
self.dcx().emit_err(errors::MultipleRelaxedDefaultBounds {
|
self.tcx()
|
||||||
spans: unbounds.iter().map(|ptr| ptr.span).collect(),
|
.sess
|
||||||
});
|
.create_feature_err(
|
||||||
|
errors::MultipleRelaxedDefaultBounds {
|
||||||
|
spans: unbounds.iter().map(|ptr| ptr.span).collect(),
|
||||||
|
},
|
||||||
|
sym::more_maybe_bounds,
|
||||||
|
)
|
||||||
|
.emit();
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut seen_sized_unbound = false;
|
let mut seen_sized_unbound = false;
|
||||||
|
@ -698,7 +698,7 @@ pub(crate) fn complain_about_missing_assoc_tys(
|
|||||||
&self,
|
&self,
|
||||||
associated_types: FxIndexMap<Span, FxIndexSet<DefId>>,
|
associated_types: FxIndexMap<Span, FxIndexSet<DefId>>,
|
||||||
potential_assoc_types: Vec<usize>,
|
potential_assoc_types: Vec<usize>,
|
||||||
trait_bounds: &[hir::PolyTraitRef<'_>],
|
trait_bounds: &[(hir::PolyTraitRef<'_>, hir::TraitBoundModifier)],
|
||||||
) {
|
) {
|
||||||
if associated_types.values().all(|v| v.is_empty()) {
|
if associated_types.values().all(|v| v.is_empty()) {
|
||||||
return;
|
return;
|
||||||
@ -744,12 +744,12 @@ pub(crate) fn complain_about_missing_assoc_tys(
|
|||||||
// related to issue #91997, turbofishes added only when in an expr or pat
|
// related to issue #91997, turbofishes added only when in an expr or pat
|
||||||
let mut in_expr_or_pat = false;
|
let mut in_expr_or_pat = false;
|
||||||
if let ([], [bound]) = (&potential_assoc_types[..], &trait_bounds) {
|
if let ([], [bound]) = (&potential_assoc_types[..], &trait_bounds) {
|
||||||
let grandparent = tcx.parent_hir_node(tcx.parent_hir_id(bound.trait_ref.hir_ref_id));
|
let grandparent = tcx.parent_hir_node(tcx.parent_hir_id(bound.0.trait_ref.hir_ref_id));
|
||||||
in_expr_or_pat = match grandparent {
|
in_expr_or_pat = match grandparent {
|
||||||
Node::Expr(_) | Node::Pat(_) => true,
|
Node::Expr(_) | Node::Pat(_) => true,
|
||||||
_ => false,
|
_ => false,
|
||||||
};
|
};
|
||||||
match bound.trait_ref.path.segments {
|
match bound.0.trait_ref.path.segments {
|
||||||
// FIXME: `trait_ref.path.span` can point to a full path with multiple
|
// FIXME: `trait_ref.path.span` can point to a full path with multiple
|
||||||
// segments, even though `trait_ref.path.segments` is of length `1`. Work
|
// segments, even though `trait_ref.path.segments` is of length `1`. Work
|
||||||
// around that bug here, even though it should be fixed elsewhere.
|
// around that bug here, even though it should be fixed elsewhere.
|
||||||
@ -790,7 +790,7 @@ pub(crate) fn complain_about_missing_assoc_tys(
|
|||||||
// and we can then use their span to indicate this to the user.
|
// and we can then use their span to indicate this to the user.
|
||||||
let bound_names = trait_bounds
|
let bound_names = trait_bounds
|
||||||
.iter()
|
.iter()
|
||||||
.filter_map(|poly_trait_ref| {
|
.filter_map(|(poly_trait_ref, _)| {
|
||||||
let path = poly_trait_ref.trait_ref.path.segments.last()?;
|
let path = poly_trait_ref.trait_ref.path.segments.last()?;
|
||||||
let args = path.args?;
|
let args = path.args?;
|
||||||
|
|
||||||
|
@ -34,7 +34,7 @@ pub(super) fn prohibit_or_lint_bare_trait_object_ty(
|
|||||||
.ok()
|
.ok()
|
||||||
.is_some_and(|s| s.trim_end().ends_with('<'));
|
.is_some_and(|s| s.trim_end().ends_with('<'));
|
||||||
|
|
||||||
let is_global = poly_trait_ref.trait_ref.path.is_global();
|
let is_global = poly_trait_ref.0.trait_ref.path.is_global();
|
||||||
|
|
||||||
let mut sugg = vec![(
|
let mut sugg = vec![(
|
||||||
self_ty.span.shrink_to_lo(),
|
self_ty.span.shrink_to_lo(),
|
||||||
@ -176,7 +176,7 @@ fn maybe_suggest_impl_trait(&self, self_ty: &hir::Ty<'_>, diag: &mut Diag<'_>) -
|
|||||||
let mut is_downgradable = true;
|
let mut is_downgradable = true;
|
||||||
let is_object_safe = match self_ty.kind {
|
let is_object_safe = match self_ty.kind {
|
||||||
hir::TyKind::TraitObject(objects, ..) => {
|
hir::TyKind::TraitObject(objects, ..) => {
|
||||||
objects.iter().all(|o| match o.trait_ref.path.res {
|
objects.iter().all(|(o, _)| match o.trait_ref.path.res {
|
||||||
Res::Def(DefKind::Trait, id) => {
|
Res::Def(DefKind::Trait, id) => {
|
||||||
if Some(id) == owner {
|
if Some(id) == owner {
|
||||||
// For recursive traits, don't downgrade the error. (#119652)
|
// For recursive traits, don't downgrade the error. (#119652)
|
||||||
|
@ -27,7 +27,7 @@ pub(super) fn lower_trait_object_ty(
|
|||||||
&self,
|
&self,
|
||||||
span: Span,
|
span: Span,
|
||||||
hir_id: hir::HirId,
|
hir_id: hir::HirId,
|
||||||
hir_trait_bounds: &[hir::PolyTraitRef<'tcx>],
|
hir_trait_bounds: &[(hir::PolyTraitRef<'tcx>, hir::TraitBoundModifier)],
|
||||||
lifetime: &hir::Lifetime,
|
lifetime: &hir::Lifetime,
|
||||||
borrowed: bool,
|
borrowed: bool,
|
||||||
representation: DynKind,
|
representation: DynKind,
|
||||||
@ -37,7 +37,10 @@ pub(super) fn lower_trait_object_ty(
|
|||||||
let mut bounds = Bounds::default();
|
let mut bounds = Bounds::default();
|
||||||
let mut potential_assoc_types = Vec::new();
|
let mut potential_assoc_types = Vec::new();
|
||||||
let dummy_self = self.tcx().types.trait_object_dummy_self;
|
let dummy_self = self.tcx().types.trait_object_dummy_self;
|
||||||
for trait_bound in hir_trait_bounds.iter().rev() {
|
for (trait_bound, modifier) in hir_trait_bounds.iter().rev() {
|
||||||
|
if *modifier == hir::TraitBoundModifier::Maybe {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
if let GenericArgCountResult {
|
if let GenericArgCountResult {
|
||||||
correct:
|
correct:
|
||||||
Err(GenericArgCountMismatch { invalid_args: cur_potential_assoc_types, .. }),
|
Err(GenericArgCountMismatch { invalid_args: cur_potential_assoc_types, .. }),
|
||||||
@ -249,7 +252,7 @@ pub(super) fn lower_trait_object_ty(
|
|||||||
let args = tcx.mk_args(&args);
|
let args = tcx.mk_args(&args);
|
||||||
|
|
||||||
let span = i.bottom().1;
|
let span = i.bottom().1;
|
||||||
let empty_generic_args = hir_trait_bounds.iter().any(|hir_bound| {
|
let empty_generic_args = hir_trait_bounds.iter().any(|(hir_bound, _)| {
|
||||||
hir_bound.trait_ref.path.res == Res::Def(DefKind::Trait, trait_ref.def_id)
|
hir_bound.trait_ref.path.res == Res::Def(DefKind::Trait, trait_ref.def_id)
|
||||||
&& hir_bound.span.contains(span)
|
&& hir_bound.span.contains(span)
|
||||||
});
|
});
|
||||||
|
@ -300,13 +300,16 @@ fn print_type(&mut self, ty: &hir::Ty<'_>) {
|
|||||||
self.word_space("dyn");
|
self.word_space("dyn");
|
||||||
}
|
}
|
||||||
let mut first = true;
|
let mut first = true;
|
||||||
for bound in bounds {
|
for (bound, modifier) in bounds {
|
||||||
if first {
|
if first {
|
||||||
first = false;
|
first = false;
|
||||||
} else {
|
} else {
|
||||||
self.nbsp();
|
self.nbsp();
|
||||||
self.word_space("+");
|
self.word_space("+");
|
||||||
}
|
}
|
||||||
|
if *modifier == TraitBoundModifier::Maybe {
|
||||||
|
self.word("?");
|
||||||
|
}
|
||||||
self.print_poly_trait_ref(bound);
|
self.print_poly_trait_ref(bound);
|
||||||
}
|
}
|
||||||
if !lifetime.is_elided() {
|
if !lifetime.is_elided() {
|
||||||
|
@ -429,7 +429,7 @@ fn ty_has_local_parent(
|
|||||||
path_has_local_parent(ty_path, cx, impl_parent, impl_parent_parent)
|
path_has_local_parent(ty_path, cx, impl_parent, impl_parent_parent)
|
||||||
}
|
}
|
||||||
TyKind::TraitObject([principle_poly_trait_ref, ..], _, _) => path_has_local_parent(
|
TyKind::TraitObject([principle_poly_trait_ref, ..], _, _) => path_has_local_parent(
|
||||||
principle_poly_trait_ref.trait_ref.path,
|
principle_poly_trait_ref.0.trait_ref.path,
|
||||||
cx,
|
cx,
|
||||||
impl_parent,
|
impl_parent,
|
||||||
impl_parent_parent,
|
impl_parent_parent,
|
||||||
@ -527,7 +527,7 @@ fn self_ty_kind_for_diagnostic(ty: &rustc_hir::Ty<'_>, tcx: TyCtxt<'_>) -> (Span
|
|||||||
.to_string(),
|
.to_string(),
|
||||||
),
|
),
|
||||||
TyKind::TraitObject([principle_poly_trait_ref, ..], _, _) => {
|
TyKind::TraitObject([principle_poly_trait_ref, ..], _, _) => {
|
||||||
let path = &principle_poly_trait_ref.trait_ref.path;
|
let path = &principle_poly_trait_ref.0.trait_ref.path;
|
||||||
(
|
(
|
||||||
path_span_without_args(path),
|
path_span_without_args(path),
|
||||||
path.res
|
path.res
|
||||||
|
@ -113,9 +113,11 @@ fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::Item<'tcx>) {
|
|||||||
|
|
||||||
fn check_ty(&mut self, cx: &LateContext<'_>, ty: &'tcx hir::Ty<'tcx>) {
|
fn check_ty(&mut self, cx: &LateContext<'_>, ty: &'tcx hir::Ty<'tcx>) {
|
||||||
let hir::TyKind::TraitObject(bounds, _lifetime, _syntax) = &ty.kind else { return };
|
let hir::TyKind::TraitObject(bounds, _lifetime, _syntax) = &ty.kind else { return };
|
||||||
for bound in &bounds[..] {
|
for (bound, modifier) in &bounds[..] {
|
||||||
let def_id = bound.trait_ref.trait_def_id();
|
let def_id = bound.trait_ref.trait_def_id();
|
||||||
if cx.tcx.lang_items().drop_trait() == def_id {
|
if cx.tcx.lang_items().drop_trait() == def_id
|
||||||
|
&& *modifier != hir::TraitBoundModifier::Maybe
|
||||||
|
{
|
||||||
let Some(def_id) = cx.tcx.get_diagnostic_item(sym::needs_drop) else { return };
|
let Some(def_id) = cx.tcx.get_diagnostic_item(sym::needs_drop) else { return };
|
||||||
cx.emit_span_lint(DYN_DROP, bound.span, DropGlue { tcx: cx.tcx, def_id });
|
cx.emit_span_lint(DYN_DROP, bound.span, DropGlue { tcx: cx.tcx, def_id });
|
||||||
}
|
}
|
||||||
|
@ -1229,6 +1229,7 @@
|
|||||||
modifiers,
|
modifiers,
|
||||||
module,
|
module,
|
||||||
module_path,
|
module_path,
|
||||||
|
more_maybe_bounds,
|
||||||
more_qualified_paths,
|
more_qualified_paths,
|
||||||
more_struct_aliases,
|
more_struct_aliases,
|
||||||
movbe_target_feature,
|
movbe_target_feature,
|
||||||
|
@ -84,7 +84,7 @@ fn visit_ty(&mut self, arg: &'tcx hir::Ty<'tcx>) -> Self::Result {
|
|||||||
}
|
}
|
||||||
|
|
||||||
hir::TyKind::TraitObject(bounds, ..) => {
|
hir::TyKind::TraitObject(bounds, ..) => {
|
||||||
for bound in bounds {
|
for (bound, _) in bounds {
|
||||||
self.current_index.shift_in(1);
|
self.current_index.shift_in(1);
|
||||||
self.visit_poly_trait_ref(bound);
|
self.visit_poly_trait_ref(bound);
|
||||||
self.current_index.shift_out(1);
|
self.current_index.shift_out(1);
|
||||||
|
@ -607,7 +607,7 @@ fn visit_ty(&mut self, t: &'tcx hir::Ty<'tcx>) {
|
|||||||
_,
|
_,
|
||||||
) = t.kind
|
) = t.kind
|
||||||
{
|
{
|
||||||
for ptr in poly_trait_refs {
|
for (ptr, _) in poly_trait_refs {
|
||||||
if Some(self.1) == ptr.trait_ref.trait_def_id() {
|
if Some(self.1) == ptr.trait_ref.trait_def_id() {
|
||||||
self.0.push(ptr.span);
|
self.0.push(ptr.span);
|
||||||
}
|
}
|
||||||
|
@ -437,7 +437,7 @@ pub fn report_object_safety_error<'tcx>(
|
|||||||
if tcx.parent_hir_node(hir_id).fn_sig().is_some() {
|
if tcx.parent_hir_node(hir_id).fn_sig().is_some() {
|
||||||
// Do not suggest `impl Trait` when dealing with things like super-traits.
|
// Do not suggest `impl Trait` when dealing with things like super-traits.
|
||||||
err.span_suggestion_verbose(
|
err.span_suggestion_verbose(
|
||||||
ty.span.until(trait_ref.span),
|
ty.span.until(trait_ref.0.span),
|
||||||
"consider using an opaque type instead",
|
"consider using an opaque type instead",
|
||||||
"impl ",
|
"impl ",
|
||||||
Applicability::MaybeIncorrect,
|
Applicability::MaybeIncorrect,
|
||||||
|
@ -3040,11 +3040,11 @@ pub(super) fn note_obligation_cause_code<G: EmissionGuarantee, T>(
|
|||||||
match ty.kind {
|
match ty.kind {
|
||||||
hir::TyKind::TraitObject(traits, _, _) => {
|
hir::TyKind::TraitObject(traits, _, _) => {
|
||||||
let (span, kw) = match traits {
|
let (span, kw) = match traits {
|
||||||
[first, ..] if first.span.lo() == ty.span.lo() => {
|
[(first, _), ..] if first.span.lo() == ty.span.lo() => {
|
||||||
// Missing `dyn` in front of trait object.
|
// Missing `dyn` in front of trait object.
|
||||||
(ty.span.shrink_to_lo(), "dyn ")
|
(ty.span.shrink_to_lo(), "dyn ")
|
||||||
}
|
}
|
||||||
[first, ..] => (ty.span.until(first.span), ""),
|
[(first, _), ..] => (ty.span.until(first.span), ""),
|
||||||
[] => span_bug!(ty.span, "trait object with no traits: {ty:?}"),
|
[] => span_bug!(ty.span, "trait object with no traits: {ty:?}"),
|
||||||
};
|
};
|
||||||
let needs_parens = traits.len() != 1;
|
let needs_parens = traits.len() != 1;
|
||||||
|
@ -1858,7 +1858,7 @@ pub(crate) fn clean_ty<'tcx>(ty: &hir::Ty<'tcx>, cx: &mut DocContext<'tcx>) -> T
|
|||||||
}
|
}
|
||||||
TyKind::Path(_) => clean_qpath(ty, cx),
|
TyKind::Path(_) => clean_qpath(ty, cx),
|
||||||
TyKind::TraitObject(bounds, ref lifetime, _) => {
|
TyKind::TraitObject(bounds, ref lifetime, _) => {
|
||||||
let bounds = bounds.iter().map(|bound| clean_poly_trait_ref(bound, cx)).collect();
|
let bounds = bounds.iter().map(|(bound, _)| clean_poly_trait_ref(bound, cx)).collect();
|
||||||
let lifetime =
|
let lifetime =
|
||||||
if !lifetime.is_elided() { Some(clean_lifetime(*lifetime, cx)) } else { None };
|
if !lifetime.is_elided() { Some(clean_lifetime(*lifetime, cx)) } else { None };
|
||||||
DynTrait(bounds, lifetime)
|
DynTrait(bounds, lifetime)
|
||||||
|
@ -545,7 +545,7 @@ fn visit_ty(&mut self, ty: &'tcx Ty<'_>) {
|
|||||||
if !lt.is_elided() {
|
if !lt.is_elided() {
|
||||||
self.unelided_trait_object_lifetime = true;
|
self.unelided_trait_object_lifetime = true;
|
||||||
}
|
}
|
||||||
for bound in bounds {
|
for (bound, _) in bounds {
|
||||||
self.visit_poly_trait_ref(bound);
|
self.visit_poly_trait_ref(bound);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -181,7 +181,7 @@ fn check_ty(&mut self, cx: &LateContext<'tcx>, ty: &'tcx Ty<'tcx>) {
|
|||||||
|
|
||||||
// Iterate the bounds and add them to our seen hash
|
// Iterate the bounds and add them to our seen hash
|
||||||
// If we haven't yet seen it, add it to the fixed traits
|
// If we haven't yet seen it, add it to the fixed traits
|
||||||
for bound in bounds {
|
for (bound, _) in bounds {
|
||||||
let Some(def_id) = bound.trait_ref.trait_def_id() else {
|
let Some(def_id) = bound.trait_ref.trait_def_id() else {
|
||||||
continue;
|
continue;
|
||||||
};
|
};
|
||||||
@ -196,9 +196,9 @@ fn check_ty(&mut self, cx: &LateContext<'tcx>, ty: &'tcx Ty<'tcx>) {
|
|||||||
// If the number of unique traits isn't the same as the number of traits in the bounds,
|
// If the number of unique traits isn't the same as the number of traits in the bounds,
|
||||||
// there must be 1 or more duplicates
|
// there must be 1 or more duplicates
|
||||||
if bounds.len() != unique_traits.len() {
|
if bounds.len() != unique_traits.len() {
|
||||||
let mut bounds_span = bounds[0].span;
|
let mut bounds_span = bounds[0].0.span;
|
||||||
|
|
||||||
for bound in bounds.iter().skip(1) {
|
for (bound, _) in bounds.iter().skip(1) {
|
||||||
bounds_span = bounds_span.to(bound.span);
|
bounds_span = bounds_span.to(bound.span);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -81,14 +81,17 @@ pub(super) fn check(cx: &LateContext<'_>, hir_ty: &hir::Ty<'_>, lt: &Lifetime, m
|
|||||||
|
|
||||||
// Returns true if given type is `Any` trait.
|
// Returns true if given type is `Any` trait.
|
||||||
fn is_any_trait(cx: &LateContext<'_>, t: &hir::Ty<'_>) -> bool {
|
fn is_any_trait(cx: &LateContext<'_>, t: &hir::Ty<'_>) -> bool {
|
||||||
if let TyKind::TraitObject(traits, ..) = t.kind
|
if let TyKind::TraitObject(traits, ..) = t.kind {
|
||||||
&& !traits.is_empty()
|
return traits
|
||||||
&& let Some(trait_did) = traits[0].trait_ref.trait_def_id()
|
.iter()
|
||||||
// Only Send/Sync can be used as additional traits, so it is enough to
|
.any(|(bound, _)| {
|
||||||
// check only the first trait.
|
if let Some(trait_did) = bound.trait_ref.trait_def_id()
|
||||||
&& cx.tcx.is_diagnostic_item(sym::Any, trait_did)
|
&& cx.tcx.is_diagnostic_item(sym::Any, trait_did)
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
|
}
|
||||||
|
false
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
false
|
false
|
||||||
|
@ -55,6 +55,7 @@ fn visit_ty(&mut self, ty: &'tcx hir::Ty<'_>) {
|
|||||||
TyKind::TraitObject(param_bounds, _, _) => {
|
TyKind::TraitObject(param_bounds, _, _) => {
|
||||||
let has_lifetime_parameters = param_bounds.iter().any(|bound| {
|
let has_lifetime_parameters = param_bounds.iter().any(|bound| {
|
||||||
bound
|
bound
|
||||||
|
.0
|
||||||
.bound_generic_params
|
.bound_generic_params
|
||||||
.iter()
|
.iter()
|
||||||
.any(|param| matches!(param.kind, GenericParamKind::Lifetime { .. }))
|
.any(|param| matches!(param.kind, GenericParamKind::Lifetime { .. }))
|
||||||
|
17
tests/ui/feature-gates/feature-gate-more-maybe-bounds.rs
Normal file
17
tests/ui/feature-gates/feature-gate-more-maybe-bounds.rs
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
#![feature(auto_traits)]
|
||||||
|
|
||||||
|
trait Trait1 {}
|
||||||
|
auto trait Trait2 {}
|
||||||
|
trait Trait3: ?Trait1 {}
|
||||||
|
//~^ ERROR `?Trait` is not permitted in supertraits
|
||||||
|
trait Trait4 where Self: ?Trait1 {}
|
||||||
|
//~^ ERROR ?Trait` bounds are only permitted at the point where a type parameter is declared
|
||||||
|
|
||||||
|
fn foo(_: Box<dyn Trait1 + ?Trait2>) {}
|
||||||
|
//~^ ERROR `?Trait` is not permitted in trait object types
|
||||||
|
fn bar<T: ?Trait1 + ?Trait2>(_: T) {}
|
||||||
|
//~^ ERROR type parameter has more than one relaxed default bound, only one is supported
|
||||||
|
//~| WARN relaxing a default bound only does something for `?Sized`; all other traits are not bound by default
|
||||||
|
//~| WARN relaxing a default bound only does something for `?Sized`; all other traits are not bound by default
|
||||||
|
|
||||||
|
fn main() {}
|
53
tests/ui/feature-gates/feature-gate-more-maybe-bounds.stderr
Normal file
53
tests/ui/feature-gates/feature-gate-more-maybe-bounds.stderr
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
error[E0658]: `?Trait` is not permitted in supertraits
|
||||||
|
--> $DIR/feature-gate-more-maybe-bounds.rs:5:15
|
||||||
|
|
|
||||||
|
LL | trait Trait3: ?Trait1 {}
|
||||||
|
| ^^^^^^^
|
||||||
|
|
|
||||||
|
= note: traits are `?Trait1` by default
|
||||||
|
= help: add `#![feature(more_maybe_bounds)]` to the crate attributes to enable
|
||||||
|
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
|
||||||
|
|
||||||
|
error[E0658]: `?Trait` is not permitted in trait object types
|
||||||
|
--> $DIR/feature-gate-more-maybe-bounds.rs:10:28
|
||||||
|
|
|
||||||
|
LL | fn foo(_: Box<dyn Trait1 + ?Trait2>) {}
|
||||||
|
| ^^^^^^^
|
||||||
|
|
|
||||||
|
= help: add `#![feature(more_maybe_bounds)]` to the crate attributes to enable
|
||||||
|
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
|
||||||
|
|
||||||
|
error[E0658]: `?Trait` bounds are only permitted at the point where a type parameter is declared
|
||||||
|
--> $DIR/feature-gate-more-maybe-bounds.rs:7:26
|
||||||
|
|
|
||||||
|
LL | trait Trait4 where Self: ?Trait1 {}
|
||||||
|
| ^^^^^^^
|
||||||
|
|
|
||||||
|
= help: add `#![feature(more_maybe_bounds)]` to the crate attributes to enable
|
||||||
|
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
|
||||||
|
|
||||||
|
error[E0203]: type parameter has more than one relaxed default bound, only one is supported
|
||||||
|
--> $DIR/feature-gate-more-maybe-bounds.rs:12:11
|
||||||
|
|
|
||||||
|
LL | fn bar<T: ?Trait1 + ?Trait2>(_: T) {}
|
||||||
|
| ^^^^^^^ ^^^^^^^
|
||||||
|
|
|
||||||
|
= help: add `#![feature(more_maybe_bounds)]` to the crate attributes to enable
|
||||||
|
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
|
||||||
|
|
||||||
|
warning: relaxing a default bound only does something for `?Sized`; all other traits are not bound by default
|
||||||
|
--> $DIR/feature-gate-more-maybe-bounds.rs:12:11
|
||||||
|
|
|
||||||
|
LL | fn bar<T: ?Trait1 + ?Trait2>(_: T) {}
|
||||||
|
| ^^^^^^^
|
||||||
|
|
||||||
|
warning: relaxing a default bound only does something for `?Sized`; all other traits are not bound by default
|
||||||
|
--> $DIR/feature-gate-more-maybe-bounds.rs:12:21
|
||||||
|
|
|
||||||
|
LL | fn bar<T: ?Trait1 + ?Trait2>(_: T) {}
|
||||||
|
| ^^^^^^^
|
||||||
|
|
||||||
|
error: aborting due to 4 previous errors; 2 warnings emitted
|
||||||
|
|
||||||
|
Some errors have detailed explanations: E0203, E0658.
|
||||||
|
For more information about an error, try `rustc --explain E0203`.
|
@ -1,22 +1,31 @@
|
|||||||
error: `?Trait` is not permitted in supertraits
|
error[E0658]: `?Trait` is not permitted in supertraits
|
||||||
--> $DIR/maybe-bounds.rs:1:11
|
--> $DIR/maybe-bounds.rs:1:11
|
||||||
|
|
|
|
||||||
LL | trait Tr: ?Sized {}
|
LL | trait Tr: ?Sized {}
|
||||||
| ^^^^^^
|
| ^^^^^^
|
||||||
|
|
|
|
||||||
= note: traits are `?Sized` by default
|
= note: traits are `?Sized` by default
|
||||||
|
= help: add `#![feature(more_maybe_bounds)]` to the crate attributes to enable
|
||||||
|
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
|
||||||
|
|
||||||
error: `?Trait` is not permitted in trait object types
|
error[E0658]: `?Trait` is not permitted in trait object types
|
||||||
--> $DIR/maybe-bounds.rs:4:20
|
--> $DIR/maybe-bounds.rs:4:20
|
||||||
|
|
|
|
||||||
LL | type A1 = dyn Tr + (?Sized);
|
LL | type A1 = dyn Tr + (?Sized);
|
||||||
| ^^^^^^^^
|
| ^^^^^^^^
|
||||||
|
|
|
||||||
|
= help: add `#![feature(more_maybe_bounds)]` to the crate attributes to enable
|
||||||
|
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
|
||||||
|
|
||||||
error: `?Trait` is not permitted in trait object types
|
error[E0658]: `?Trait` is not permitted in trait object types
|
||||||
--> $DIR/maybe-bounds.rs:6:28
|
--> $DIR/maybe-bounds.rs:6:28
|
||||||
|
|
|
|
||||||
LL | type A2 = dyn for<'a> Tr + (?Sized);
|
LL | type A2 = dyn for<'a> Tr + (?Sized);
|
||||||
| ^^^^^^^^
|
| ^^^^^^^^
|
||||||
|
|
|
||||||
|
= help: add `#![feature(more_maybe_bounds)]` to the crate attributes to enable
|
||||||
|
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
|
||||||
|
|
||||||
error: aborting due to 3 previous errors
|
error: aborting due to 3 previous errors
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0658`.
|
||||||
|
@ -1,20 +1,29 @@
|
|||||||
error: `?Trait` is not permitted in trait object types
|
error[E0658]: `?Trait` is not permitted in trait object types
|
||||||
--> $DIR/trait-object-trait-parens.rs:8:24
|
--> $DIR/trait-object-trait-parens.rs:8:24
|
||||||
|
|
|
|
||||||
LL | let _: Box<(Obj) + (?Sized) + (for<'a> Trait<'a>)>;
|
LL | let _: Box<(Obj) + (?Sized) + (for<'a> Trait<'a>)>;
|
||||||
| ^^^^^^^^
|
| ^^^^^^^^
|
||||||
|
|
|
||||||
|
= help: add `#![feature(more_maybe_bounds)]` to the crate attributes to enable
|
||||||
|
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
|
||||||
|
|
||||||
error: `?Trait` is not permitted in trait object types
|
error[E0658]: `?Trait` is not permitted in trait object types
|
||||||
--> $DIR/trait-object-trait-parens.rs:13:16
|
--> $DIR/trait-object-trait-parens.rs:13:16
|
||||||
|
|
|
|
||||||
LL | let _: Box<?Sized + (for<'a> Trait<'a>) + (Obj)>;
|
LL | let _: Box<?Sized + (for<'a> Trait<'a>) + (Obj)>;
|
||||||
| ^^^^^^
|
| ^^^^^^
|
||||||
|
|
|
||||||
|
= help: add `#![feature(more_maybe_bounds)]` to the crate attributes to enable
|
||||||
|
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
|
||||||
|
|
||||||
error: `?Trait` is not permitted in trait object types
|
error[E0658]: `?Trait` is not permitted in trait object types
|
||||||
--> $DIR/trait-object-trait-parens.rs:18:44
|
--> $DIR/trait-object-trait-parens.rs:18:44
|
||||||
|
|
|
|
||||||
LL | let _: Box<for<'a> Trait<'a> + (Obj) + (?Sized)>;
|
LL | let _: Box<for<'a> Trait<'a> + (Obj) + (?Sized)>;
|
||||||
| ^^^^^^^^
|
| ^^^^^^^^
|
||||||
|
|
|
||||||
|
= help: add `#![feature(more_maybe_bounds)]` to the crate attributes to enable
|
||||||
|
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
|
||||||
|
|
||||||
warning: trait objects without an explicit `dyn` are deprecated
|
warning: trait objects without an explicit `dyn` are deprecated
|
||||||
--> $DIR/trait-object-trait-parens.rs:8:16
|
--> $DIR/trait-object-trait-parens.rs:8:16
|
||||||
@ -91,4 +100,5 @@ LL | let _: Box<for<'a> Trait<'a> + (Obj) + (?Sized)>;
|
|||||||
|
|
||||||
error: aborting due to 6 previous errors; 3 warnings emitted
|
error: aborting due to 6 previous errors; 3 warnings emitted
|
||||||
|
|
||||||
For more information about this error, try `rustc --explain E0225`.
|
Some errors have detailed explanations: E0225, E0658.
|
||||||
|
For more information about an error, try `rustc --explain E0225`.
|
||||||
|
27
tests/ui/traits/maybe-polarity-pass.rs
Normal file
27
tests/ui/traits/maybe-polarity-pass.rs
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
//@ check-pass
|
||||||
|
|
||||||
|
#![feature(auto_traits)]
|
||||||
|
#![feature(more_maybe_bounds)]
|
||||||
|
#![feature(negative_impls)]
|
||||||
|
|
||||||
|
trait Trait1 {}
|
||||||
|
auto trait Trait2 {}
|
||||||
|
|
||||||
|
trait Trait3 : ?Trait1 {}
|
||||||
|
trait Trait4 where Self: Trait1 {}
|
||||||
|
|
||||||
|
fn foo(_: Box<(dyn Trait3 + ?Trait2)>) {}
|
||||||
|
fn bar<T: ?Sized + ?Trait2 + ?Trait1 + ?Trait4>(_: &T) {}
|
||||||
|
//~^ WARN relaxing a default bound only does something for `?Sized`; all other traits are not bound by default
|
||||||
|
//~| WARN relaxing a default bound only does something for `?Sized`; all other traits are not bound by default
|
||||||
|
//~| WARN relaxing a default bound only does something for `?Sized`; all other traits are not bound by default
|
||||||
|
|
||||||
|
struct S;
|
||||||
|
impl !Trait2 for S {}
|
||||||
|
impl Trait1 for S {}
|
||||||
|
impl Trait3 for S {}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
foo(Box::new(S));
|
||||||
|
bar(&S);
|
||||||
|
}
|
20
tests/ui/traits/maybe-polarity-pass.stderr
Normal file
20
tests/ui/traits/maybe-polarity-pass.stderr
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
warning: relaxing a default bound only does something for `?Sized`; all other traits are not bound by default
|
||||||
|
--> $DIR/maybe-polarity-pass.rs:14:20
|
||||||
|
|
|
||||||
|
LL | fn bar<T: ?Sized + ?Trait2 + ?Trait1 + ?Trait4>(_: &T) {}
|
||||||
|
| ^^^^^^^
|
||||||
|
|
||||||
|
warning: relaxing a default bound only does something for `?Sized`; all other traits are not bound by default
|
||||||
|
--> $DIR/maybe-polarity-pass.rs:14:30
|
||||||
|
|
|
||||||
|
LL | fn bar<T: ?Sized + ?Trait2 + ?Trait1 + ?Trait4>(_: &T) {}
|
||||||
|
| ^^^^^^^
|
||||||
|
|
||||||
|
warning: relaxing a default bound only does something for `?Sized`; all other traits are not bound by default
|
||||||
|
--> $DIR/maybe-polarity-pass.rs:14:40
|
||||||
|
|
|
||||||
|
LL | fn bar<T: ?Sized + ?Trait2 + ?Trait1 + ?Trait4>(_: &T) {}
|
||||||
|
| ^^^^^^^
|
||||||
|
|
||||||
|
warning: 3 warnings emitted
|
||||||
|
|
@ -1,32 +1,48 @@
|
|||||||
error: `?Trait` is not permitted in trait object types
|
error[E0658]: `?Trait` is not permitted in trait object types
|
||||||
--> $DIR/maybe-bound.rs:5:15
|
--> $DIR/maybe-bound.rs:5:15
|
||||||
|
|
|
|
||||||
LL | type _0 = dyn ?Sized + Foo;
|
LL | type _0 = dyn ?Sized + Foo;
|
||||||
| ^^^^^^
|
| ^^^^^^
|
||||||
|
|
|
||||||
|
= help: add `#![feature(more_maybe_bounds)]` to the crate attributes to enable
|
||||||
|
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
|
||||||
|
|
||||||
error: `?Trait` is not permitted in trait object types
|
error[E0658]: `?Trait` is not permitted in trait object types
|
||||||
--> $DIR/maybe-bound.rs:8:21
|
--> $DIR/maybe-bound.rs:8:21
|
||||||
|
|
|
|
||||||
LL | type _1 = dyn Foo + ?Sized;
|
LL | type _1 = dyn Foo + ?Sized;
|
||||||
| ^^^^^^
|
| ^^^^^^
|
||||||
|
|
|
||||||
|
= help: add `#![feature(more_maybe_bounds)]` to the crate attributes to enable
|
||||||
|
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
|
||||||
|
|
||||||
error: `?Trait` is not permitted in trait object types
|
error[E0658]: `?Trait` is not permitted in trait object types
|
||||||
--> $DIR/maybe-bound.rs:11:21
|
--> $DIR/maybe-bound.rs:11:21
|
||||||
|
|
|
|
||||||
LL | type _2 = dyn Foo + ?Sized + ?Sized;
|
LL | type _2 = dyn Foo + ?Sized + ?Sized;
|
||||||
| ^^^^^^
|
| ^^^^^^
|
||||||
|
|
|
||||||
|
= help: add `#![feature(more_maybe_bounds)]` to the crate attributes to enable
|
||||||
|
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
|
||||||
|
|
||||||
error: `?Trait` is not permitted in trait object types
|
error[E0658]: `?Trait` is not permitted in trait object types
|
||||||
--> $DIR/maybe-bound.rs:11:30
|
--> $DIR/maybe-bound.rs:11:30
|
||||||
|
|
|
|
||||||
LL | type _2 = dyn Foo + ?Sized + ?Sized;
|
LL | type _2 = dyn Foo + ?Sized + ?Sized;
|
||||||
| ^^^^^^
|
| ^^^^^^
|
||||||
|
|
|
||||||
|
= help: add `#![feature(more_maybe_bounds)]` to the crate attributes to enable
|
||||||
|
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
|
||||||
|
|
||||||
error: `?Trait` is not permitted in trait object types
|
error[E0658]: `?Trait` is not permitted in trait object types
|
||||||
--> $DIR/maybe-bound.rs:15:15
|
--> $DIR/maybe-bound.rs:15:15
|
||||||
|
|
|
|
||||||
LL | type _3 = dyn ?Sized + Foo;
|
LL | type _3 = dyn ?Sized + Foo;
|
||||||
| ^^^^^^
|
| ^^^^^^
|
||||||
|
|
|
||||||
|
= help: add `#![feature(more_maybe_bounds)]` to the crate attributes to enable
|
||||||
|
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
|
||||||
|
|
||||||
error: aborting due to 5 previous errors
|
error: aborting due to 5 previous errors
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0658`.
|
||||||
|
@ -1,8 +1,11 @@
|
|||||||
error: `?Trait` is not permitted in trait object types
|
error[E0658]: `?Trait` is not permitted in trait object types
|
||||||
--> $DIR/only-maybe-bound.rs:3:15
|
--> $DIR/only-maybe-bound.rs:3:15
|
||||||
|
|
|
|
||||||
LL | type _0 = dyn ?Sized;
|
LL | type _0 = dyn ?Sized;
|
||||||
| ^^^^^^
|
| ^^^^^^
|
||||||
|
|
|
||||||
|
= help: add `#![feature(more_maybe_bounds)]` to the crate attributes to enable
|
||||||
|
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
|
||||||
|
|
||||||
error[E0224]: at least one trait is required for an object type
|
error[E0224]: at least one trait is required for an object type
|
||||||
--> $DIR/only-maybe-bound.rs:3:11
|
--> $DIR/only-maybe-bound.rs:3:11
|
||||||
@ -12,4 +15,5 @@ LL | type _0 = dyn ?Sized;
|
|||||||
|
|
||||||
error: aborting due to 2 previous errors
|
error: aborting due to 2 previous errors
|
||||||
|
|
||||||
For more information about this error, try `rustc --explain E0224`.
|
Some errors have detailed explanations: E0224, E0658.
|
||||||
|
For more information about an error, try `rustc --explain E0224`.
|
||||||
|
@ -1,32 +1,47 @@
|
|||||||
error: `?Trait` bounds are only permitted at the point where a type parameter is declared
|
error[E0658]: `?Trait` bounds are only permitted at the point where a type parameter is declared
|
||||||
--> $DIR/maybe-bounds-where.rs:1:28
|
--> $DIR/maybe-bounds-where.rs:1:28
|
||||||
|
|
|
|
||||||
LL | struct S1<T>(T) where (T): ?Sized;
|
LL | struct S1<T>(T) where (T): ?Sized;
|
||||||
| ^^^^^^
|
| ^^^^^^
|
||||||
|
|
|
||||||
|
= help: add `#![feature(more_maybe_bounds)]` to the crate attributes to enable
|
||||||
|
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
|
||||||
|
|
||||||
error: `?Trait` bounds are only permitted at the point where a type parameter is declared
|
error[E0658]: `?Trait` bounds are only permitted at the point where a type parameter is declared
|
||||||
--> $DIR/maybe-bounds-where.rs:4:27
|
--> $DIR/maybe-bounds-where.rs:4:27
|
||||||
|
|
|
|
||||||
LL | struct S2<T>(T) where u8: ?Sized;
|
LL | struct S2<T>(T) where u8: ?Sized;
|
||||||
| ^^^^^^
|
| ^^^^^^
|
||||||
|
|
|
||||||
|
= help: add `#![feature(more_maybe_bounds)]` to the crate attributes to enable
|
||||||
|
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
|
||||||
|
|
||||||
error: `?Trait` bounds are only permitted at the point where a type parameter is declared
|
error[E0658]: `?Trait` bounds are only permitted at the point where a type parameter is declared
|
||||||
--> $DIR/maybe-bounds-where.rs:7:35
|
--> $DIR/maybe-bounds-where.rs:7:35
|
||||||
|
|
|
|
||||||
LL | struct S3<T>(T) where &'static T: ?Sized;
|
LL | struct S3<T>(T) where &'static T: ?Sized;
|
||||||
| ^^^^^^
|
| ^^^^^^
|
||||||
|
|
|
||||||
|
= help: add `#![feature(more_maybe_bounds)]` to the crate attributes to enable
|
||||||
|
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
|
||||||
|
|
||||||
error: `?Trait` bounds are only permitted at the point where a type parameter is declared
|
error[E0658]: `?Trait` bounds are only permitted at the point where a type parameter is declared
|
||||||
--> $DIR/maybe-bounds-where.rs:12:34
|
--> $DIR/maybe-bounds-where.rs:12:34
|
||||||
|
|
|
|
||||||
LL | struct S4<T>(T) where for<'a> T: ?Trait<'a>;
|
LL | struct S4<T>(T) where for<'a> T: ?Trait<'a>;
|
||||||
| ^^^^^^^^^^
|
| ^^^^^^^^^^
|
||||||
|
|
|
||||||
|
= help: add `#![feature(more_maybe_bounds)]` to the crate attributes to enable
|
||||||
|
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
|
||||||
|
|
||||||
error: `?Trait` bounds are only permitted at the point where a type parameter is declared
|
error[E0658]: `?Trait` bounds are only permitted at the point where a type parameter is declared
|
||||||
--> $DIR/maybe-bounds-where.rs:21:21
|
--> $DIR/maybe-bounds-where.rs:21:21
|
||||||
|
|
|
|
||||||
LL | fn f() where T: ?Sized {}
|
LL | fn f() where T: ?Sized {}
|
||||||
| ^^^^^^
|
| ^^^^^^
|
||||||
|
|
|
||||||
|
= help: add `#![feature(more_maybe_bounds)]` to the crate attributes to enable
|
||||||
|
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
|
||||||
|
|
||||||
warning: relaxing a default bound only does something for `?Sized`; all other traits are not bound by default
|
warning: relaxing a default bound only does something for `?Sized`; all other traits are not bound by default
|
||||||
--> $DIR/maybe-bounds-where.rs:12:34
|
--> $DIR/maybe-bounds-where.rs:12:34
|
||||||
@ -39,6 +54,9 @@ error[E0203]: type parameter has more than one relaxed default bound, only one i
|
|||||||
|
|
|
|
||||||
LL | struct S5<T>(*const T) where T: ?Trait<'static> + ?Sized;
|
LL | struct S5<T>(*const T) where T: ?Trait<'static> + ?Sized;
|
||||||
| ^^^^^^^^^^^^^^^ ^^^^^^
|
| ^^^^^^^^^^^^^^^ ^^^^^^
|
||||||
|
|
|
||||||
|
= help: add `#![feature(more_maybe_bounds)]` to the crate attributes to enable
|
||||||
|
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
|
||||||
|
|
||||||
warning: relaxing a default bound only does something for `?Sized`; all other traits are not bound by default
|
warning: relaxing a default bound only does something for `?Sized`; all other traits are not bound by default
|
||||||
--> $DIR/maybe-bounds-where.rs:16:33
|
--> $DIR/maybe-bounds-where.rs:16:33
|
||||||
@ -48,4 +66,5 @@ LL | struct S5<T>(*const T) where T: ?Trait<'static> + ?Sized;
|
|||||||
|
|
||||||
error: aborting due to 6 previous errors; 2 warnings emitted
|
error: aborting due to 6 previous errors; 2 warnings emitted
|
||||||
|
|
||||||
For more information about this error, try `rustc --explain E0203`.
|
Some errors have detailed explanations: E0203, E0658.
|
||||||
|
For more information about an error, try `rustc --explain E0203`.
|
||||||
|
Loading…
Reference in New Issue
Block a user