diff options
| author | bors <bors@rust-lang.org> | 2024-07-26 20:14:16 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2024-07-26 20:14:16 +0000 |
| commit | 7c2012d0ec3aae89fefc40e5d6b317a0949cda36 (patch) | |
| tree | 50993e684ae086ee44409abd47a29e0ff5dcca36 /compiler/rustc_hir_analysis/src | |
| parent | 47243b335e02c341528dd3beb77fa0e030d7ccda (diff) | |
| parent | fd9d0bfbacc2d5af183ba394ca16cb2581dab02d (diff) | |
| download | rust-7c2012d0ec3aae89fefc40e5d6b317a0949cda36.tar.gz rust-7c2012d0ec3aae89fefc40e5d6b317a0949cda36.zip | |
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)
Diffstat (limited to 'compiler/rustc_hir_analysis/src')
6 files changed, 29 insertions, 14 deletions
diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs index 0316ef69bf8..456dc4e4e07 100644 --- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs +++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs @@ -831,7 +831,7 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for GATArgsCollector<'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, }, diff --git a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs index 349dc9ad00e..02ea95852f0 100644 --- a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs +++ b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs @@ -652,7 +652,7 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, '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"), diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs index 214eb6b2f06..30c04aa47a3 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs @@ -8,7 +8,7 @@ use rustc_hir::def_id::{DefId, LocalDefId}; 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 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { } } + 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; diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs index 56f508a2d43..20f06d77489 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs @@ -719,7 +719,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { &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 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { // 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 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { // 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?; diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/lint.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/lint.rs index 29c71c3fa50..e7aad0a29c5 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/lint.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/lint.rs @@ -34,7 +34,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { .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 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { 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) diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/object_safety.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/object_safety.rs index aafadc7f9cb..b3c7a1ff8a8 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/object_safety.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/object_safety.rs @@ -27,7 +27,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { &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 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { 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 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { 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) }); |
