Auto merge of #121676 - Bryanskiy:polarity, r=petrochenkov
Support ?Trait bounds in supertraits and dyn Trait under a feature gate This patch allows `maybe` polarity bounds under a feature gate. The only language change here is that corresponding hard errors are replaced by feature gates. Example: ```rust #![feature(allow_maybe_polarity)] ... trait Trait1 : ?Trait { ... } // ok fn foo(_: Box<(dyn Trait2 + ?Trait)>) {} // ok fn bar<T: ?Sized + ?Trait>(_: &T) {} // ok ``` Maybe bounds still don't do anything (except for `Sized` trait), however this patch will allow us to [experiment with default auto traits](https://github.com/rust-lang/rust/pull/120706#issuecomment-1934006762). This is a part of the [MCP: Low level components for async drop](https://github.com/rust-lang/compiler-team/issues/727)
This commit is contained in:
commit
7c2012d0ec
@ -1525,8 +1525,14 @@ fn lower_generics<T>(
|
||||
continue;
|
||||
}
|
||||
let is_param = *is_param.get_or_insert_with(compute_is_param);
|
||||
if !is_param {
|
||||
self.dcx().emit_err(MisplacedRelaxTraitBound { span: bound.span() });
|
||||
if !is_param && !self.tcx.features().more_maybe_bounds {
|
||||
self.tcx
|
||||
.sess
|
||||
.create_feature_err(
|
||||
MisplacedRelaxTraitBound { span: bound.span() },
|
||||
sym::more_maybe_bounds,
|
||||
)
|
||||
.emit();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1216,6 +1216,7 @@ fn lower_path_ty(
|
||||
itctx,
|
||||
TraitBoundModifiers::NONE,
|
||||
);
|
||||
let bound = (bound, hir::TraitBoundModifier::None);
|
||||
let bounds = this.arena.alloc_from_iter([bound]);
|
||||
let lifetime_bound = this.elided_dyn_bound(t.span);
|
||||
(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
|
||||
// takes care of rejecting invalid modifier combinations and
|
||||
// const trait bounds in trait object types.
|
||||
GenericBound::Trait(ty, modifiers) => match modifiers.polarity {
|
||||
BoundPolarity::Positive | BoundPolarity::Negative(_) => {
|
||||
Some(this.lower_poly_trait_ref(
|
||||
ty,
|
||||
itctx,
|
||||
// Still, don't pass along the constness here; we don't want to
|
||||
// synthesize any host effect args, it'd only cause problems.
|
||||
TraitBoundModifiers {
|
||||
constness: BoundConstness::Never,
|
||||
..*modifiers
|
||||
},
|
||||
))
|
||||
}
|
||||
BoundPolarity::Maybe(_) => None,
|
||||
},
|
||||
GenericBound::Trait(ty, modifiers) => {
|
||||
// Still, don't pass along the constness here; we don't want to
|
||||
// synthesize any host effect args, it'd only cause problems.
|
||||
let modifiers = TraitBoundModifiers {
|
||||
constness: BoundConstness::Never,
|
||||
..*modifiers
|
||||
};
|
||||
let trait_ref = this.lower_poly_trait_ref(ty, itctx, modifiers);
|
||||
let polarity = this.lower_trait_bound_modifiers(modifiers);
|
||||
Some((trait_ref, polarity))
|
||||
}
|
||||
GenericBound::Outlives(lifetime) => {
|
||||
if lifetime_bound.is_none() {
|
||||
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 },
|
||||
span: self.lower_span(span),
|
||||
};
|
||||
let principal = (principal, hir::TraitBoundModifier::None);
|
||||
|
||||
// The original ID is taken by the `PolyTraitRef`,
|
||||
// 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 {
|
||||
GenericBound::Trait(trait_ref, modifiers) => {
|
||||
match (ctxt, modifiers.constness, modifiers.polarity) {
|
||||
(BoundKind::SuperTraits, BoundConstness::Never, BoundPolarity::Maybe(_)) => {
|
||||
self.dcx().emit_err(errors::OptionalTraitSupertrait {
|
||||
span: trait_ref.span,
|
||||
path_str: pprust::path_to_string(&trait_ref.trait_ref.path),
|
||||
});
|
||||
(BoundKind::SuperTraits, BoundConstness::Never, BoundPolarity::Maybe(_))
|
||||
if !self.features.more_maybe_bounds =>
|
||||
{
|
||||
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(_)) => {
|
||||
self.dcx().emit_err(errors::OptionalTraitObject { span: trait_ref.span });
|
||||
(BoundKind::TraitObject, BoundConstness::Never, BoundPolarity::Maybe(_))
|
||||
if !self.features.more_maybe_bounds =>
|
||||
{
|
||||
self.session
|
||||
.create_feature_err(
|
||||
errors::OptionalTraitObject { span: trait_ref.span },
|
||||
sym::more_maybe_bounds,
|
||||
)
|
||||
.emit();
|
||||
}
|
||||
(
|
||||
BoundKind::TraitObject,
|
||||
|
@ -205,6 +205,8 @@ pub fn internal(&self, feature: Symbol) -> bool {
|
||||
(unstable, lifetime_capture_rules_2024, "1.76.0", None),
|
||||
/// Allows `#[link(..., cfg(..))]`; perma-unstable per #37406
|
||||
(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.
|
||||
(unstable, multiple_supertrait_upcastable, "1.69.0", None),
|
||||
/// 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),
|
||||
/// A trait object type `Bound1 + Bound2 + Bound3`
|
||||
/// 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.
|
||||
Typeof(&'hir AnonConst),
|
||||
/// `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));
|
||||
}
|
||||
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));
|
||||
}
|
||||
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 {
|
||||
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()),
|
||||
_ => false,
|
||||
},
|
||||
|
@ -652,7 +652,7 @@ fn visit_ty(&mut self, ty: &'tcx hir::Ty<'tcx>) {
|
||||
debug!(?bounds, ?lifetime, "TraitObject");
|
||||
let scope = Scope::TraitRefBoundary { s: self.scope };
|
||||
self.with(scope, |this| {
|
||||
for bound in bounds {
|
||||
for (bound, _) in bounds {
|
||||
this.visit_poly_trait_ref_inner(
|
||||
bound,
|
||||
NonLifetimeBinderAllowed::Deny("trait object types"),
|
||||
|
@ -8,7 +8,7 @@
|
||||
use rustc_middle::bug;
|
||||
use rustc_middle::ty::{self as ty, IsSuggestable, Ty, TyCtxt};
|
||||
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_type_ir::visit::{TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor};
|
||||
use smallvec::SmallVec;
|
||||
@ -73,10 +73,22 @@ pub(crate) fn add_sized_bound(
|
||||
}
|
||||
}
|
||||
|
||||
let mut unique_bounds = FxIndexSet::default();
|
||||
let mut seen_repeat = false;
|
||||
for unbound in &unbounds {
|
||||
if let Res::Def(DefKind::Trait, unbound_def_id) = unbound.trait_ref.path.res {
|
||||
seen_repeat |= !unique_bounds.insert(unbound_def_id);
|
||||
}
|
||||
}
|
||||
if unbounds.len() > 1 {
|
||||
self.dcx().emit_err(errors::MultipleRelaxedDefaultBounds {
|
||||
let err = errors::MultipleRelaxedDefaultBounds {
|
||||
spans: unbounds.iter().map(|ptr| ptr.span).collect(),
|
||||
});
|
||||
};
|
||||
if seen_repeat {
|
||||
self.dcx().emit_err(err);
|
||||
} else if !tcx.features().more_maybe_bounds {
|
||||
self.tcx().sess.create_feature_err(err, sym::more_maybe_bounds).emit();
|
||||
};
|
||||
}
|
||||
|
||||
let mut seen_sized_unbound = false;
|
||||
|
@ -719,7 +719,7 @@ pub(crate) fn complain_about_missing_assoc_tys(
|
||||
&self,
|
||||
associated_types: FxIndexMap<Span, FxIndexSet<DefId>>,
|
||||
potential_assoc_types: Vec<usize>,
|
||||
trait_bounds: &[hir::PolyTraitRef<'_>],
|
||||
trait_bounds: &[(hir::PolyTraitRef<'_>, hir::TraitBoundModifier)],
|
||||
) {
|
||||
if associated_types.values().all(|v| v.is_empty()) {
|
||||
return;
|
||||
@ -765,12 +765,12 @@ pub(crate) fn complain_about_missing_assoc_tys(
|
||||
// related to issue #91997, turbofishes added only when in an expr or pat
|
||||
let mut in_expr_or_pat = false;
|
||||
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 {
|
||||
hir::Node::Expr(_) | hir::Node::Pat(_) => true,
|
||||
_ => 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
|
||||
// segments, even though `trait_ref.path.segments` is of length `1`. Work
|
||||
// around that bug here, even though it should be fixed elsewhere.
|
||||
@ -811,7 +811,7 @@ pub(crate) fn complain_about_missing_assoc_tys(
|
||||
// and we can then use their span to indicate this to the user.
|
||||
let bound_names = trait_bounds
|
||||
.iter()
|
||||
.filter_map(|poly_trait_ref| {
|
||||
.filter_map(|(poly_trait_ref, _)| {
|
||||
let path = poly_trait_ref.trait_ref.path.segments.last()?;
|
||||
let args = path.args?;
|
||||
|
||||
|
@ -34,7 +34,7 @@ pub(super) fn prohibit_or_lint_bare_trait_object_ty(
|
||||
.ok()
|
||||
.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![(
|
||||
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 is_object_safe = match self_ty.kind {
|
||||
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) => {
|
||||
if Some(id) == owner {
|
||||
// For recursive traits, don't downgrade the error. (#119652)
|
||||
|
@ -27,7 +27,7 @@ pub(super) fn lower_trait_object_ty(
|
||||
&self,
|
||||
span: Span,
|
||||
hir_id: hir::HirId,
|
||||
hir_trait_bounds: &[hir::PolyTraitRef<'tcx>],
|
||||
hir_trait_bounds: &[(hir::PolyTraitRef<'tcx>, hir::TraitBoundModifier)],
|
||||
lifetime: &hir::Lifetime,
|
||||
borrowed: bool,
|
||||
representation: DynKind,
|
||||
@ -37,7 +37,10 @@ pub(super) fn lower_trait_object_ty(
|
||||
let mut bounds = Bounds::default();
|
||||
let mut potential_assoc_types = Vec::new();
|
||||
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 {
|
||||
correct:
|
||||
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 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.span.contains(span)
|
||||
});
|
||||
|
@ -300,13 +300,16 @@ fn print_type(&mut self, ty: &hir::Ty<'_>) {
|
||||
self.word_space("dyn");
|
||||
}
|
||||
let mut first = true;
|
||||
for bound in bounds {
|
||||
for (bound, modifier) in bounds {
|
||||
if first {
|
||||
first = false;
|
||||
} else {
|
||||
self.nbsp();
|
||||
self.word_space("+");
|
||||
}
|
||||
if *modifier == TraitBoundModifier::Maybe {
|
||||
self.word("?");
|
||||
}
|
||||
self.print_poly_trait_ref(bound);
|
||||
}
|
||||
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)
|
||||
}
|
||||
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,
|
||||
impl_parent,
|
||||
impl_parent_parent,
|
||||
@ -527,7 +527,7 @@ fn self_ty_kind_for_diagnostic(ty: &rustc_hir::Ty<'_>, tcx: TyCtxt<'_>) -> (Span
|
||||
.to_string(),
|
||||
),
|
||||
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.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>) {
|
||||
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();
|
||||
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 };
|
||||
cx.emit_span_lint(DYN_DROP, bound.span, DropGlue { tcx: cx.tcx, def_id });
|
||||
}
|
||||
|
@ -1230,6 +1230,7 @@
|
||||
modifiers,
|
||||
module,
|
||||
module_path,
|
||||
more_maybe_bounds,
|
||||
more_qualified_paths,
|
||||
more_struct_aliases,
|
||||
movbe_target_feature,
|
||||
|
@ -84,7 +84,7 @@ fn visit_ty(&mut self, arg: &'tcx hir::Ty<'tcx>) -> Self::Result {
|
||||
}
|
||||
|
||||
hir::TyKind::TraitObject(bounds, ..) => {
|
||||
for bound in bounds {
|
||||
for (bound, _) in bounds {
|
||||
self.current_index.shift_in(1);
|
||||
self.visit_poly_trait_ref(bound);
|
||||
self.current_index.shift_out(1);
|
||||
|
@ -607,7 +607,7 @@ fn visit_ty(&mut self, t: &'tcx hir::Ty<'tcx>) {
|
||||
_,
|
||||
) = t.kind
|
||||
{
|
||||
for ptr in poly_trait_refs {
|
||||
for (ptr, _) in poly_trait_refs {
|
||||
if Some(self.1) == ptr.trait_ref.trait_def_id() {
|
||||
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() {
|
||||
// Do not suggest `impl Trait` when dealing with things like super-traits.
|
||||
err.span_suggestion_verbose(
|
||||
ty.span.until(trait_ref.span),
|
||||
ty.span.until(trait_ref.0.span),
|
||||
"consider using an opaque type instead",
|
||||
"impl ",
|
||||
Applicability::MaybeIncorrect,
|
||||
|
@ -3040,11 +3040,11 @@ pub(super) fn note_obligation_cause_code<G: EmissionGuarantee, T>(
|
||||
match ty.kind {
|
||||
hir::TyKind::TraitObject(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.
|
||||
(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:?}"),
|
||||
};
|
||||
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::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 =
|
||||
if !lifetime.is_elided() { Some(clean_lifetime(*lifetime, cx)) } else { None };
|
||||
DynTrait(bounds, lifetime)
|
||||
|
@ -543,7 +543,7 @@ fn visit_ty(&mut self, ty: &'tcx Ty<'_>) {
|
||||
if !lt.is_elided() {
|
||||
self.unelided_trait_object_lifetime = true;
|
||||
}
|
||||
for bound in bounds {
|
||||
for (bound, _) in bounds {
|
||||
self.visit_poly_trait_ref(bound);
|
||||
}
|
||||
},
|
||||
|
@ -183,7 +183,7 @@ fn check_ty(&mut self, cx: &LateContext<'tcx>, ty: &'tcx Ty<'tcx>) {
|
||||
|
||||
// Iterate the bounds and add them to our seen hash
|
||||
// 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 {
|
||||
continue;
|
||||
};
|
||||
@ -198,9 +198,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,
|
||||
// there must be 1 or more duplicates
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -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.
|
||||
fn is_any_trait(cx: &LateContext<'_>, t: &hir::Ty<'_>) -> bool {
|
||||
if let TyKind::TraitObject(traits, ..) = t.kind
|
||||
&& !traits.is_empty()
|
||||
&& let Some(trait_did) = traits[0].trait_ref.trait_def_id()
|
||||
// Only Send/Sync can be used as additional traits, so it is enough to
|
||||
// check only the first trait.
|
||||
&& cx.tcx.is_diagnostic_item(sym::Any, trait_did)
|
||||
{
|
||||
return true;
|
||||
if let TyKind::TraitObject(traits, ..) = t.kind {
|
||||
return traits
|
||||
.iter()
|
||||
.any(|(bound, _)| {
|
||||
if let Some(trait_did) = bound.trait_ref.trait_def_id()
|
||||
&& cx.tcx.is_diagnostic_item(sym::Any, trait_did)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
false
|
||||
});
|
||||
}
|
||||
|
||||
false
|
||||
|
@ -55,6 +55,7 @@ fn visit_ty(&mut self, ty: &'tcx hir::Ty<'_>) {
|
||||
TyKind::TraitObject(param_bounds, _, _) => {
|
||||
let has_lifetime_parameters = param_bounds.iter().any(|bound| {
|
||||
bound
|
||||
.0
|
||||
.bound_generic_params
|
||||
.iter()
|
||||
.any(|param| matches!(param.kind, GenericParamKind::Lifetime { .. }))
|
||||
|
24
tests/ui/feature-gates/feature-gate-more-maybe-bounds.rs
Normal file
24
tests/ui/feature-gates/feature-gate-more-maybe-bounds.rs
Normal file
@ -0,0 +1,24 @@
|
||||
#![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
|
||||
|
||||
trait Trait {}
|
||||
// Do not suggest `#![feature(more_maybe_bounds)]` for repetitions
|
||||
fn baz<T: ?Trait + ?Trait>(_ : 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() {}
|
71
tests/ui/feature-gates/feature-gate-more-maybe-bounds.stderr
Normal file
71
tests/ui/feature-gates/feature-gate-more-maybe-bounds.stderr
Normal file
@ -0,0 +1,71 @@
|
||||
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[E0203]: type parameter has more than one relaxed default bound, only one is supported
|
||||
--> $DIR/feature-gate-more-maybe-bounds.rs:19:11
|
||||
|
|
||||
LL | fn baz<T: ?Trait + ?Trait>(_ : 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:19:11
|
||||
|
|
||||
LL | fn baz<T: ?Trait + ?Trait>(_ : 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:19:20
|
||||
|
|
||||
LL | fn baz<T: ?Trait + ?Trait>(_ : T) {}
|
||||
| ^^^^^^
|
||||
|
||||
error: aborting due to 5 previous errors; 4 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
|
||||
|
|
||||
LL | trait Tr: ?Sized {}
|
||||
| ^^^^^^
|
||||
|
|
||||
= 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
|
||||
|
|
||||
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
|
||||
|
|
||||
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
|
||||
|
||||
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
|
||||
|
|
||||
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
|
||||
|
|
||||
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
|
||||
|
|
||||
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
|
||||
--> $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
|
||||
|
||||
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
|
||||
|
9
tests/ui/traits/maybe-polarity-repeated.rs
Normal file
9
tests/ui/traits/maybe-polarity-repeated.rs
Normal file
@ -0,0 +1,9 @@
|
||||
#![feature(more_maybe_bounds)]
|
||||
|
||||
trait Trait {}
|
||||
fn foo<T: ?Trait + ?Trait>(_: 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() {}
|
21
tests/ui/traits/maybe-polarity-repeated.stderr
Normal file
21
tests/ui/traits/maybe-polarity-repeated.stderr
Normal file
@ -0,0 +1,21 @@
|
||||
error[E0203]: type parameter has more than one relaxed default bound, only one is supported
|
||||
--> $DIR/maybe-polarity-repeated.rs:4:11
|
||||
|
|
||||
LL | fn foo<T: ?Trait + ?Trait>(_: T) {}
|
||||
| ^^^^^^ ^^^^^^
|
||||
|
||||
warning: relaxing a default bound only does something for `?Sized`; all other traits are not bound by default
|
||||
--> $DIR/maybe-polarity-repeated.rs:4:11
|
||||
|
|
||||
LL | fn foo<T: ?Trait + ?Trait>(_: T) {}
|
||||
| ^^^^^^
|
||||
|
||||
warning: relaxing a default bound only does something for `?Sized`; all other traits are not bound by default
|
||||
--> $DIR/maybe-polarity-repeated.rs:4:20
|
||||
|
|
||||
LL | fn foo<T: ?Trait + ?Trait>(_: T) {}
|
||||
| ^^^^^^
|
||||
|
||||
error: aborting due to 1 previous error; 2 warnings emitted
|
||||
|
||||
For more information about this error, try `rustc --explain E0203`.
|
@ -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
|
||||
|
|
||||
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
|
||||
|
|
||||
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
|
||||
|
|
||||
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
|
||||
|
|
||||
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
|
||||
|
|
||||
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
|
||||
|
||||
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
|
||||
|
|
||||
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
|
||||
--> $DIR/only-maybe-bound.rs:3:11
|
||||
@ -12,4 +15,5 @@ LL | type _0 = dyn ?Sized;
|
||||
|
||||
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
|
||||
|
|
||||
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
|
||||
|
|
||||
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
|
||||
|
|
||||
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
|
||||
|
|
||||
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
|
||||
|
|
||||
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
|
||||
--> $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;
|
||||
| ^^^^^^^^^^^^^^^ ^^^^^^
|
||||
|
|
||||
= 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/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
|
||||
|
||||
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