Skip to content

Commit b7435de

Browse files
committed
add polarity
1 parent 9afdb8d commit b7435de

File tree

39 files changed

+236
-118
lines changed

39 files changed

+236
-118
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
@@ -1260,16 +1260,8 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
12601260

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

compiler/rustc_ast_passes/src/errors.rs

-16
Original file line numberDiff line numberDiff line change
@@ -543,22 +543,6 @@ pub struct NestedLifetimes {
543543
pub span: Span,
544544
}
545545

546-
#[derive(Diagnostic)]
547-
#[diag(ast_passes_optional_trait_supertrait)]
548-
#[note]
549-
pub struct OptionalTraitSupertrait {
550-
#[primary_span]
551-
pub span: Span,
552-
pub path_str: String,
553-
}
554-
555-
#[derive(Diagnostic)]
556-
#[diag(ast_passes_optional_trait_object)]
557-
pub struct OptionalTraitObject {
558-
#[primary_span]
559-
pub span: Span,
560-
}
561-
562546
#[derive(Diagnostic)]
563547
#[diag(ast_passes_const_bound_trait_object)]
564548
pub struct ConstBoundTraitObject {

compiler/rustc_ast_passes/src/feature_gate.rs

+21
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,27 @@ impl<'a> PostExpansionVisitor<'a> {
169169
}
170170

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

compiler/rustc_error_codes/src/error_codes/E0203.md

+4-2
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
1+
#### Note: this error code is no longer emitted by the compiler.
2+
13
Having multiple relaxed default bounds is unsupported.
24

3-
Erroneous code example:
5+
Previously erroneous code example:
46

5-
```compile_fail,E0203
7+
```compile_fail
68
struct Bad<T: ?Sized + ?Send>{
79
inner: T
810
}

compiler/rustc_error_codes/src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -575,6 +575,7 @@ E0797: 0797,
575575
// E0190, // deprecated: can only cast a &-pointer to an &-object
576576
// E0194, // merged into E0403
577577
// E0196, // cannot determine a type for this closure
578+
// E0203 // replaced with a `allow_maybe_polarity` feature gate
578579
// E0209, // builtin traits can only be implemented on structs or enums
579580
// E0213, // associated types are not accepted in this context
580581
// E0215, // angle-bracket notation is not stable with `Fn`

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

+3-1
Original file line numberDiff line numberDiff line change
@@ -873,7 +873,9 @@ pub fn walk_ty<'v, V: Visitor<'v>>(visitor: &mut V, typ: &'v Ty<'v>) -> V::Resul
873873
try_visit!(visitor.visit_array_length(length));
874874
}
875875
TyKind::TraitObject(bounds, ref lifetime, _syntax) => {
876-
walk_list!(visitor, visit_poly_trait_ref, bounds);
876+
for (bound, _) in bounds {
877+
try_visit!(visitor.visit_poly_trait_ref(bound));
878+
}
877879
try_visit!(visitor.visit_lifetime(lifetime));
878880
}
879881
TyKind::Typeof(ref expression) => try_visit!(visitor.visit_anon_const(expression)),

compiler/rustc_hir_analysis/messages.ftl

-3
Original file line numberDiff line numberDiff line change
@@ -275,9 +275,6 @@ hir_analysis_missing_type_params =
275275
} to {$parameters}
276276
.note = because of the default `Self` reference, type parameters must be specified on object types
277277
278-
hir_analysis_multiple_relaxed_default_bounds =
279-
type parameter has more than one relaxed default bound, only one is supported
280-
281278
hir_analysis_must_be_name_of_associated_function = must be a name of an associated function
282279
283280
hir_analysis_must_implement_not_function = not a function

compiler/rustc_hir_analysis/src/astconv/bounds.rs

+17-10
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,9 @@ use rustc_hir as hir;
44
use rustc_hir::def::{DefKind, Res};
55
use rustc_hir::def_id::{DefId, LocalDefId};
66
use rustc_middle::ty::{self as ty, Ty};
7+
use rustc_session::parse::feature_err;
78
use rustc_span::symbol::Ident;
8-
use rustc_span::{ErrorGuaranteed, Span};
9+
use rustc_span::{sym, ErrorGuaranteed, Span};
910
use rustc_trait_selection::traits;
1011
use smallvec::SmallVec;
1112

@@ -66,10 +67,14 @@ impl<'tcx> dyn AstConv<'tcx> + '_ {
6667
}
6768
}
6869

69-
if unbounds.len() > 1 {
70-
tcx.dcx().emit_err(errors::MultipleRelaxedDefaultBounds {
71-
spans: unbounds.iter().map(|ptr| ptr.span).collect(),
72-
});
70+
if unbounds.len() > 1 && !tcx.features().allow_maybe_polarity {
71+
feature_err(
72+
tcx.sess,
73+
sym::allow_maybe_polarity,
74+
unbounds.iter().map(|ptr| ptr.span).collect::<Vec<Span>>(),
75+
"type parameter has more than one relaxed default bound, only one is supported",
76+
)
77+
.emit();
7378
}
7479

7580
let mut seen_sized_unbound = false;
@@ -80,12 +85,14 @@ impl<'tcx> dyn AstConv<'tcx> + '_ {
8085
seen_sized_unbound = true;
8186
continue;
8287
}
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`; \
88+
if !tcx.features().allow_maybe_polarity {
89+
// There was a `?Trait` bound, but it was not `?Sized`; warn.
90+
tcx.dcx().span_warn(
91+
unbound.span,
92+
"relaxing a default bound only does something for `?Sized`; \
8793
all other traits are not bound by default",
88-
);
94+
);
95+
}
8996
}
9097

9198
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
@@ -101,7 +101,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
101101
let mut is_downgradable = true;
102102
let is_object_safe = match self_ty.kind {
103103
hir::TyKind::TraitObject(objects, ..) => {
104-
objects.iter().all(|o| match o.trait_ref.path.res {
104+
objects.iter().all(|(o, _)| match o.trait_ref.path.res {
105105
Res::Def(DefKind::Trait, id) => {
106106
if Some(id) == owner {
107107
// For recursive traits, don't downgrade the error. (#119652)
@@ -192,7 +192,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
192192

193193
pub(super) fn maybe_lint_bare_trait(&self, self_ty: &hir::Ty<'_>, in_path: bool) {
194194
let tcx = self.tcx();
195-
if let hir::TyKind::TraitObject([poly_trait_ref, ..], _, TraitObjectSyntax::None) =
195+
if let hir::TyKind::TraitObject([(poly_trait_ref, _), ..], _, TraitObjectSyntax::None) =
196196
self_ty.kind
197197
{
198198
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_analysis/src/errors.rs

-7
Original file line numberDiff line numberDiff line change
@@ -246,13 +246,6 @@ pub struct CopyImplOnTypeWithDtor {
246246
pub span: Span,
247247
}
248248

249-
#[derive(Diagnostic)]
250-
#[diag(hir_analysis_multiple_relaxed_default_bounds, code = E0203)]
251-
pub struct MultipleRelaxedDefaultBounds {
252-
#[primary_span]
253-
pub spans: Vec<Span>,
254-
}
255-
256249
#[derive(Diagnostic)]
257250
#[diag(hir_analysis_copy_impl_on_non_adt, code = E0206)]
258251
pub struct CopyImplOnNonAdt {

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) {

0 commit comments

Comments
 (0)