Skip to content

Commit 438e259

Browse files
committed
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

Lines changed: 13 additions & 15 deletions
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

Lines changed: 0 additions & 5 deletions
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

Lines changed: 1 addition & 9 deletions
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

Lines changed: 0 additions & 16 deletions
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

Lines changed: 21 additions & 0 deletions
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

Lines changed: 2 additions & 0 deletions
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

Lines changed: 5 additions & 1 deletion
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

Lines changed: 1 addition & 1 deletion
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

Lines changed: 8 additions & 6 deletions
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

Lines changed: 3 additions & 3 deletions
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

0 commit comments

Comments
 (0)