Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 438e259

Browse files
committedFeb 27, 2024
add polarity
1 parent 6f72620 commit 438e259

File tree

29 files changed

+197
-87
lines changed

29 files changed

+197
-87
lines changed
 

‎compiler/rustc_ast_lowering/src/lib.rs

+13-15
Original file line numberDiff line numberDiff line change
@@ -1255,6 +1255,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
12551255
itctx,
12561256
TraitBoundModifiers::NONE,
12571257
);
1258+
let bound = (bound, hir::TraitBoundModifier::None);
12581259
let bounds = this.arena.alloc_from_iter([bound]);
12591260
let lifetime_bound = this.elided_dyn_bound(t.span);
12601261
(bounds, lifetime_bound)
@@ -1386,21 +1387,17 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
13861387
// We can safely ignore constness here since AST validation
13871388
// takes care of rejecting invalid modifier combinations and
13881389
// const trait bounds in trait object types.
1389-
GenericBound::Trait(ty, modifiers) => match modifiers.polarity {
1390-
BoundPolarity::Positive | BoundPolarity::Negative(_) => {
1391-
Some(this.lower_poly_trait_ref(
1392-
ty,
1393-
itctx,
1394-
// Still, don't pass along the constness here; we don't want to
1395-
// synthesize any host effect args, it'd only cause problems.
1396-
TraitBoundModifiers {
1397-
constness: BoundConstness::Never,
1398-
..*modifiers
1399-
},
1400-
))
1401-
}
1402-
BoundPolarity::Maybe(_) => None,
1403-
},
1390+
GenericBound::Trait(ty, modifiers) => {
1391+
// Still, don't pass along the constness here; we don't want to
1392+
// synthesize any host effect args, it'd only cause problems.
1393+
let modifiers = TraitBoundModifiers {
1394+
constness: BoundConstness::Never,
1395+
..*modifiers
1396+
};
1397+
let trait_ref = this.lower_poly_trait_ref(ty, itctx, modifiers);
1398+
let polarity = this.lower_trait_bound_modifiers(modifiers);
1399+
Some((trait_ref, polarity))
1400+
}
14041401
GenericBound::Outlives(lifetime) => {
14051402
if lifetime_bound.is_none() {
14061403
lifetime_bound = Some(this.lower_lifetime(lifetime));
@@ -2502,6 +2499,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
25022499
trait_ref: hir::TraitRef { path, hir_ref_id: hir_id },
25032500
span: self.lower_span(span),
25042501
};
2502+
let principal = (principal, hir::TraitBoundModifier::None);
25052503

25062504
// The original ID is taken by the `PolyTraitRef`,
25072505
// so the `Ty` itself needs a different one.

‎compiler/rustc_ast_passes/messages.ftl

-5
Original file line numberDiff line numberDiff line change
@@ -202,11 +202,6 @@ ast_passes_nomangle_ascii = `#[no_mangle]` requires ASCII identifier
202202
ast_passes_obsolete_auto = `impl Trait for .. {"{}"}` is an obsolete syntax
203203
.help = use `auto trait Trait {"{}"}` instead
204204
205-
ast_passes_optional_trait_object = `?Trait` is not permitted in trait object types
206-
207-
ast_passes_optional_trait_supertrait = `?Trait` is not permitted in supertraits
208-
.note = traits are `?{$path_str}` by default
209-
210205
ast_passes_out_of_order_params = {$param_ord} parameters must be declared prior to {$max_param} parameters
211206
.suggestion = reorder the parameters: lifetimes, then consts and types
212207

‎compiler/rustc_ast_passes/src/ast_validation.rs

+1-9
Original file line numberDiff line numberDiff line change
@@ -1259,16 +1259,8 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
12591259

12601260
fn visit_param_bound(&mut self, bound: &'a GenericBound, ctxt: BoundKind) {
12611261
if let GenericBound::Trait(poly, modifiers) = bound {
1262+
// Some of the arms are feature-gated. See `feature_gate::PostExpansionVisitor`.
12621263
match (ctxt, modifiers.constness, modifiers.polarity) {
1263-
(BoundKind::SuperTraits, BoundConstness::Never, BoundPolarity::Maybe(_)) => {
1264-
self.dcx().emit_err(errors::OptionalTraitSupertrait {
1265-
span: poly.span,
1266-
path_str: pprust::path_to_string(&poly.trait_ref.path),
1267-
});
1268-
}
1269-
(BoundKind::TraitObject, BoundConstness::Never, BoundPolarity::Maybe(_)) => {
1270-
self.dcx().emit_err(errors::OptionalTraitObject { span: poly.span });
1271-
}
12721264
(BoundKind::TraitObject, BoundConstness::Always(_), BoundPolarity::Positive) => {
12731265
self.dcx().emit_err(errors::ConstBoundTraitObject { span: poly.span });
12741266
}

‎compiler/rustc_ast_passes/src/errors.rs

-16
Original file line numberDiff line numberDiff line change
@@ -536,22 +536,6 @@ pub struct NestedLifetimes {
536536
pub span: Span,
537537
}
538538

539-
#[derive(Diagnostic)]
540-
#[diag(ast_passes_optional_trait_supertrait)]
541-
#[note]
542-
pub struct OptionalTraitSupertrait {
543-
#[primary_span]
544-
pub span: Span,
545-
pub path_str: String,
546-
}
547-
548-
#[derive(Diagnostic)]
549-
#[diag(ast_passes_optional_trait_object)]
550-
pub struct OptionalTraitObject {
551-
#[primary_span]
552-
pub span: Span,
553-
}
554-
555539
#[derive(Diagnostic)]
556540
#[diag(ast_passes_const_bound_trait_object)]
557541
pub struct ConstBoundTraitObject {

‎compiler/rustc_ast_passes/src/feature_gate.rs

+21
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,27 @@ impl<'a> PostExpansionVisitor<'a> {
166166
}
167167

168168
impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
169+
fn visit_param_bound(&mut self, bound: &'a ast::GenericBound, ctxt: visit::BoundKind) {
170+
use ast::visit::BoundKind;
171+
use ast::{BoundConstness, BoundPolarity};
172+
if let ast::GenericBound::Trait(poly, modifiers) = bound {
173+
let gate = |descr| {
174+
gate!(&self, allow_maybe_polarity, poly.span, descr);
175+
};
176+
177+
match (ctxt, modifiers.constness, modifiers.polarity) {
178+
(BoundKind::TraitObject, BoundConstness::Never, BoundPolarity::Maybe(_)) => {
179+
gate("`?Trait` is not permitted in trait object types");
180+
}
181+
(BoundKind::SuperTraits, BoundConstness::Never, BoundPolarity::Maybe(_)) => {
182+
gate("`?Trait` is not permitted in supertraits");
183+
}
184+
_ => {}
185+
}
186+
}
187+
visit::walk_param_bound(self, bound);
188+
}
189+
169190
fn visit_attribute(&mut self, attr: &ast::Attribute) {
170191
let attr_info = attr.ident().and_then(|ident| BUILTIN_ATTRIBUTE_MAP.get(&ident.name));
171192
// Check feature gates for built-in attributes.

‎compiler/rustc_feature/src/unstable.rs

+2
Original file line numberDiff line numberDiff line change
@@ -191,6 +191,8 @@ declare_features! (
191191
/// below (it has to be checked before expansion possibly makes
192192
/// macros disappear).
193193
(internal, allow_internal_unstable, "1.0.0", None),
194+
/// Allows using `?Trait` trait bound.
195+
(internal, allow_maybe_polarity, "CURRENT_RUSTC_VERSION", None),
194196
/// Allows using anonymous lifetimes in argument-position impl-trait.
195197
(unstable, anonymous_lifetime_in_impl_trait, "1.63.0", None),
196198
/// Allows identifying the `compiler_builtins` crate.

‎compiler/rustc_hir/src/hir.rs

+5-1
Original file line numberDiff line numberDiff line change
@@ -2603,7 +2603,11 @@ pub enum TyKind<'hir> {
26032603
OpaqueDef(ItemId, &'hir [GenericArg<'hir>], bool),
26042604
/// A trait object type `Bound1 + Bound2 + Bound3`
26052605
/// where `Bound` is a trait or a lifetime.
2606-
TraitObject(&'hir [PolyTraitRef<'hir>], &'hir Lifetime, TraitObjectSyntax),
2606+
TraitObject(
2607+
&'hir [(PolyTraitRef<'hir>, TraitBoundModifier)],
2608+
&'hir Lifetime,
2609+
TraitObjectSyntax,
2610+
),
26072611
/// Unused for now.
26082612
Typeof(AnonConst),
26092613
/// `TyKind::Infer` means the type should be inferred instead of it having been

‎compiler/rustc_hir/src/intravisit.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -845,7 +845,7 @@ pub fn walk_ty<'v, V: Visitor<'v>>(visitor: &mut V, typ: &'v Ty<'v>) {
845845
visitor.visit_array_length(length)
846846
}
847847
TyKind::TraitObject(bounds, ref lifetime, _syntax) => {
848-
for bound in bounds {
848+
for (bound, _) in bounds {
849849
visitor.visit_poly_trait_ref(bound);
850850
}
851851
visitor.visit_lifetime(lifetime);

‎compiler/rustc_hir_analysis/src/astconv/bounds.rs

+8-6
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ impl<'tcx> dyn AstConv<'tcx> + '_ {
6666
}
6767
}
6868

69-
if unbounds.len() > 1 {
69+
if unbounds.len() > 1 && !tcx.features().allow_maybe_polarity {
7070
tcx.dcx().emit_err(errors::MultipleRelaxedDefaultBounds {
7171
spans: unbounds.iter().map(|ptr| ptr.span).collect(),
7272
});
@@ -80,12 +80,14 @@ impl<'tcx> dyn AstConv<'tcx> + '_ {
8080
seen_sized_unbound = true;
8181
continue;
8282
}
83-
// There was a `?Trait` bound, but it was not `?Sized`; warn.
84-
tcx.dcx().span_warn(
85-
unbound.span,
86-
"relaxing a default bound only does something for `?Sized`; \
83+
if !tcx.features().allow_maybe_polarity {
84+
// There was a `?Trait` bound, but it was not `?Sized`; warn.
85+
tcx.dcx().span_warn(
86+
unbound.span,
87+
"relaxing a default bound only does something for `?Sized`; \
8788
all other traits are not bound by default",
88-
);
89+
);
90+
}
8991
}
9092

9193
if seen_sized_unbound || seen_negative_sized_bound || seen_positive_sized_bound {

‎compiler/rustc_hir_analysis/src/astconv/errors.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -592,7 +592,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
592592
&self,
593593
associated_types: FxIndexMap<Span, FxIndexSet<DefId>>,
594594
potential_assoc_types: Vec<Span>,
595-
trait_bounds: &[hir::PolyTraitRef<'_>],
595+
trait_bounds: &[(hir::PolyTraitRef<'_>, hir::TraitBoundModifier)],
596596
) {
597597
if associated_types.values().all(|v| v.is_empty()) {
598598
return;
@@ -634,7 +634,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
634634
if object_safety_violations {
635635
return;
636636
}
637-
if let ([], [bound]) = (&potential_assoc_types[..], &trait_bounds) {
637+
if let ([], [(bound, _)]) = (&potential_assoc_types[..], &trait_bounds) {
638638
match bound.trait_ref.path.segments {
639639
// FIXME: `trait_ref.path.span` can point to a full path with multiple
640640
// segments, even though `trait_ref.path.segments` is of length `1`. Work
@@ -676,7 +676,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
676676
// and we can then use their span to indicate this to the user.
677677
let bound_names = trait_bounds
678678
.iter()
679-
.filter_map(|poly_trait_ref| {
679+
.filter_map(|(poly_trait_ref, _)| {
680680
let path = poly_trait_ref.trait_ref.path.segments.last()?;
681681
let args = path.args?;
682682

‎compiler/rustc_hir_analysis/src/astconv/lint.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
9797
let mut is_downgradable = true;
9898
let is_object_safe = match self_ty.kind {
9999
hir::TyKind::TraitObject(objects, ..) => {
100-
objects.iter().all(|o| match o.trait_ref.path.res {
100+
objects.iter().all(|(o, _)| match o.trait_ref.path.res {
101101
Res::Def(DefKind::Trait, id) => {
102102
if Some(id) == owner {
103103
// For recursive traits, don't downgrade the error. (#119652)
@@ -188,7 +188,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
188188

189189
pub(super) fn maybe_lint_bare_trait(&self, self_ty: &hir::Ty<'_>, in_path: bool) {
190190
let tcx = self.tcx();
191-
if let hir::TyKind::TraitObject([poly_trait_ref, ..], _, TraitObjectSyntax::None) =
191+
if let hir::TyKind::TraitObject([(poly_trait_ref, _), ..], _, TraitObjectSyntax::None) =
192192
self_ty.kind
193193
{
194194
let needs_bracket = in_path

‎compiler/rustc_hir_analysis/src/astconv/object_safety.rs

+6-3
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
2222
&self,
2323
span: Span,
2424
hir_id: hir::HirId,
25-
hir_trait_bounds: &[hir::PolyTraitRef<'tcx>],
25+
hir_trait_bounds: &[(hir::PolyTraitRef<'tcx>, hir::TraitBoundModifier)],
2626
lifetime: &hir::Lifetime,
2727
borrowed: bool,
2828
representation: DynKind,
@@ -32,7 +32,10 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
3232
let mut bounds = Bounds::default();
3333
let mut potential_assoc_types = Vec::new();
3434
let dummy_self = self.tcx().types.trait_object_dummy_self;
35-
for trait_bound in hir_trait_bounds.iter().rev() {
35+
for (trait_bound, modifier) in hir_trait_bounds.iter().rev() {
36+
if *modifier == hir::TraitBoundModifier::Maybe {
37+
continue;
38+
}
3639
if let GenericArgCountResult {
3740
correct:
3841
Err(GenericArgCountMismatch { invalid_args: cur_potential_assoc_types, .. }),
@@ -279,7 +282,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
279282
let args = tcx.mk_args(&args);
280283

281284
let span = i.bottom().1;
282-
let empty_generic_args = hir_trait_bounds.iter().any(|hir_bound| {
285+
let empty_generic_args = hir_trait_bounds.iter().any(|(hir_bound, _)| {
283286
hir_bound.trait_ref.path.res == Res::Def(DefKind::Trait, trait_ref.def_id)
284287
&& hir_bound.span.contains(span)
285288
});

‎compiler/rustc_hir_analysis/src/check/wfcheck.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -834,7 +834,7 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for GATArgsCollector<'tcx> {
834834

835835
fn could_be_self(trait_def_id: LocalDefId, ty: &hir::Ty<'_>) -> bool {
836836
match ty.kind {
837-
hir::TyKind::TraitObject([trait_ref], ..) => match trait_ref.trait_ref.path.segments {
837+
hir::TyKind::TraitObject([(trait_ref, _)], ..) => match trait_ref.trait_ref.path.segments {
838838
[s] => s.res.opt_def_id() == Some(trait_def_id.to_def_id()),
839839
_ => false,
840840
},

‎compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -638,7 +638,10 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> {
638638
debug!(?bounds, ?lifetime, "TraitObject");
639639
let scope = Scope::TraitRefBoundary { s: self.scope };
640640
self.with(scope, |this| {
641-
for bound in bounds {
641+
for (bound, modifier) in bounds {
642+
if *modifier == hir::TraitBoundModifier::Maybe {
643+
continue;
644+
}
642645
this.visit_poly_trait_ref_inner(
643646
bound,
644647
NonLifetimeBinderAllowed::Deny("trait object types"),

‎compiler/rustc_hir_pretty/src/lib.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -293,13 +293,16 @@ impl<'a> State<'a> {
293293
self.word_space("dyn");
294294
}
295295
let mut first = true;
296-
for bound in bounds {
296+
for (bound, modifier) in bounds {
297297
if first {
298298
first = false;
299299
} else {
300300
self.nbsp();
301301
self.word_space("+");
302302
}
303+
if *modifier == TraitBoundModifier::Maybe {
304+
self.word("?");
305+
}
303306
self.print_poly_trait_ref(bound);
304307
}
305308
if !lifetime.is_elided() {

‎compiler/rustc_infer/src/infer/error_reporting/nice_region_error/find_anon_type.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ impl<'tcx> Visitor<'tcx> for FindNestedTypeVisitor<'tcx> {
8888
}
8989

9090
hir::TyKind::TraitObject(bounds, ..) => {
91-
for bound in bounds {
91+
for (bound, _) in bounds {
9292
self.current_index.shift_in(1);
9393
self.visit_poly_trait_ref(bound);
9494
self.current_index.shift_out(1);

‎compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -569,7 +569,7 @@ impl<'a, 'tcx> Visitor<'tcx> for HirTraitObjectVisitor<'a> {
569569
_,
570570
) = t.kind
571571
{
572-
for ptr in poly_trait_refs {
572+
for (ptr, _) in poly_trait_refs {
573573
if Some(self.1) == ptr.trait_ref.trait_def_id() {
574574
self.0.push(ptr.span);
575575
}

‎compiler/rustc_infer/src/traits/error_reporting/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ pub fn report_object_safety_error<'tcx>(
6262

6363
if let Some(hir_id) = hir_id
6464
&& let hir::Node::Ty(ty) = tcx.hir_node(hir_id)
65-
&& let hir::TyKind::TraitObject([trait_ref, ..], ..) = ty.kind
65+
&& let hir::TyKind::TraitObject([(trait_ref, _), ..], ..) = ty.kind
6666
{
6767
let mut hir_id = hir_id;
6868
while let hir::Node::Ty(ty) = tcx.parent_hir_node(hir_id) {

‎compiler/rustc_lint/src/traits.rs

+4-2
Original file line numberDiff line numberDiff line change
@@ -112,9 +112,11 @@ impl<'tcx> LateLintPass<'tcx> for DropTraitConstraints {
112112

113113
fn check_ty(&mut self, cx: &LateContext<'_>, ty: &'tcx hir::Ty<'tcx>) {
114114
let hir::TyKind::TraitObject(bounds, _lifetime, _syntax) = &ty.kind else { return };
115-
for bound in &bounds[..] {
115+
for (bound, modifier) in &bounds[..] {
116116
let def_id = bound.trait_ref.trait_def_id();
117-
if cx.tcx.lang_items().drop_trait() == def_id {
117+
if cx.tcx.lang_items().drop_trait() == def_id
118+
&& *modifier != hir::TraitBoundModifier::Maybe
119+
{
118120
let Some(def_id) = cx.tcx.get_diagnostic_item(sym::needs_drop) else { return };
119121
cx.emit_span_lint(DYN_DROP, bound.span, DropGlue { tcx: cx.tcx, def_id });
120122
}

‎compiler/rustc_span/src/symbol.rs

+1
Original file line numberDiff line numberDiff line change
@@ -377,6 +377,7 @@ symbols! {
377377
allow_fail,
378378
allow_internal_unsafe,
379379
allow_internal_unstable,
380+
allow_maybe_polarity,
380381
alu32,
381382
always,
382383
and,

‎compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -2983,11 +2983,11 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
29832983
match ty.kind {
29842984
hir::TyKind::TraitObject(traits, _, _) => {
29852985
let (span, kw) = match traits {
2986-
[first, ..] if first.span.lo() == ty.span.lo() => {
2986+
[(first, _), ..] if first.span.lo() == ty.span.lo() => {
29872987
// Missing `dyn` in front of trait object.
29882988
(ty.span.shrink_to_lo(), "dyn ")
29892989
}
2990-
[first, ..] => (ty.span.until(first.span), ""),
2990+
[(first, _), ..] => (ty.span.until(first.span), ""),
29912991
[] => span_bug!(ty.span, "trait object with no traits: {ty:?}"),
29922992
};
29932993
let needs_parens = traits.len() != 1;

‎src/librustdoc/clean/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1859,7 +1859,7 @@ pub(crate) fn clean_ty<'tcx>(ty: &hir::Ty<'tcx>, cx: &mut DocContext<'tcx>) -> T
18591859
}
18601860
TyKind::Path(_) => clean_qpath(ty, cx),
18611861
TyKind::TraitObject(bounds, ref lifetime, _) => {
1862-
let bounds = bounds.iter().map(|bound| clean_poly_trait_ref(bound, cx)).collect();
1862+
let bounds = bounds.iter().map(|(bound, _)| clean_poly_trait_ref(bound, cx)).collect();
18631863
let lifetime =
18641864
if !lifetime.is_elided() { Some(clean_lifetime(*lifetime, cx)) } else { None };
18651865
DynTrait(bounds, lifetime)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
#![feature(auto_traits)]
2+
3+
trait Trait1 {}
4+
auto trait Trait2 {}
5+
trait Trait3: ?Trait1 {}
6+
//~^ ERROR `?Trait` is not permitted in supertraits
7+
8+
fn foo(_: Box<dyn Trait1 + ?Trait2>) {}
9+
//~^ ERROR `?Trait` is not permitted in trait object types
10+
fn bar<T: ?Trait1>(_: T) {}
11+
//~^ WARN relaxing a default bound only does something for `?Sized`; all other traits are not bound by default
12+
13+
fn main() {}
There was a problem loading the remainder of the diff.

0 commit comments

Comments
 (0)
Failed to load comments.