Skip to content

Commit cb98565

Browse files
authored
Unrolled build for rust-lang#119354
Rollup merge of rust-lang#119354 - fmease:negative_bounds-fixes, r=compiler-errors Make `negative_bounds` internal & fix some of its issues r? compiler-errors
2 parents b8c2074 + 977546d commit cb98565

16 files changed

+251
-90
lines changed

compiler/rustc_ast_passes/messages.ftl

+3
Original file line numberDiff line numberDiff line change
@@ -188,6 +188,9 @@ ast_passes_module_nonascii = trying to load file for module `{$name}` with non-a
188188
ast_passes_negative_bound_not_supported =
189189
negative bounds are not supported
190190
191+
ast_passes_negative_bound_with_parenthetical_notation =
192+
parenthetical notation may not be used for negative bounds
193+
191194
ast_passes_nested_impl_trait = nested `impl Trait` is not allowed
192195
.outer = outer `impl Trait`
193196
.inner = nested `impl Trait` here

compiler/rustc_ast_passes/src/ast_validation.rs

+16-5
Original file line numberDiff line numberDiff line change
@@ -1312,13 +1312,24 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
13121312
if let GenericBound::Trait(trait_ref, modifiers) = bound
13131313
&& let BoundPolarity::Negative(_) = modifiers.polarity
13141314
&& let Some(segment) = trait_ref.trait_ref.path.segments.last()
1315-
&& let Some(ast::GenericArgs::AngleBracketed(args)) = segment.args.as_deref()
13161315
{
1317-
for arg in &args.args {
1318-
if let ast::AngleBracketedArg::Constraint(constraint) = arg {
1319-
self.dcx()
1320-
.emit_err(errors::ConstraintOnNegativeBound { span: constraint.span });
1316+
match segment.args.as_deref() {
1317+
Some(ast::GenericArgs::AngleBracketed(args)) => {
1318+
for arg in &args.args {
1319+
if let ast::AngleBracketedArg::Constraint(constraint) = arg {
1320+
self.dcx().emit_err(errors::ConstraintOnNegativeBound {
1321+
span: constraint.span,
1322+
});
1323+
}
1324+
}
1325+
}
1326+
// The lowered form of parenthesized generic args contains a type binding.
1327+
Some(ast::GenericArgs::Parenthesized(args)) => {
1328+
self.dcx().emit_err(errors::NegativeBoundWithParentheticalNotation {
1329+
span: args.span,
1330+
});
13211331
}
1332+
None => {}
13221333
}
13231334
}
13241335

compiler/rustc_ast_passes/src/errors.rs

+7
Original file line numberDiff line numberDiff line change
@@ -763,6 +763,13 @@ pub struct ConstraintOnNegativeBound {
763763
pub span: Span,
764764
}
765765

766+
#[derive(Diagnostic)]
767+
#[diag(ast_passes_negative_bound_with_parenthetical_notation)]
768+
pub struct NegativeBoundWithParentheticalNotation {
769+
#[primary_span]
770+
pub span: Span,
771+
}
772+
766773
#[derive(Diagnostic)]
767774
#[diag(ast_passes_invalid_unnamed_field_ty)]
768775
pub struct InvalidUnnamedFieldTy {

compiler/rustc_feature/src/unstable.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -210,7 +210,7 @@ declare_features! (
210210
/// Allows the `multiple_supertrait_upcastable` lint.
211211
(unstable, multiple_supertrait_upcastable, "1.69.0", None),
212212
/// Allow negative trait bounds. This is an internal-only feature for testing the trait solver!
213-
(incomplete, negative_bounds, "1.71.0", None),
213+
(internal, negative_bounds, "1.71.0", None),
214214
/// Allows using `#[omit_gdb_pretty_printer_section]`.
215215
(internal, omit_gdb_pretty_printer_section, "1.5.0", None),
216216
/// Allows using `#[prelude_import]` on glob `use` items.

compiler/rustc_hir_analysis/src/astconv/bounds.rs

+30-22
Original file line numberDiff line numberDiff line change
@@ -26,23 +26,36 @@ impl<'tcx> dyn AstConv<'tcx> + '_ {
2626
span: Span,
2727
) {
2828
let tcx = self.tcx();
29+
let sized_def_id = tcx.lang_items().sized_trait();
30+
let mut seen_negative_sized_bound = false;
2931

3032
// Try to find an unbound in bounds.
3133
let mut unbounds: SmallVec<[_; 1]> = SmallVec::new();
3234
let mut search_bounds = |ast_bounds: &'tcx [hir::GenericBound<'tcx>]| {
3335
for ab in ast_bounds {
34-
if let hir::GenericBound::Trait(ptr, hir::TraitBoundModifier::Maybe) = ab {
35-
unbounds.push(ptr)
36+
let hir::GenericBound::Trait(ptr, modifier) = ab else {
37+
continue;
38+
};
39+
match modifier {
40+
hir::TraitBoundModifier::Maybe => unbounds.push(ptr),
41+
hir::TraitBoundModifier::Negative => {
42+
if let Some(sized_def_id) = sized_def_id
43+
&& ptr.trait_ref.path.res == Res::Def(DefKind::Trait, sized_def_id)
44+
{
45+
seen_negative_sized_bound = true;
46+
}
47+
}
48+
_ => {}
3649
}
3750
}
3851
};
3952
search_bounds(ast_bounds);
4053
if let Some((self_ty, where_clause)) = self_ty_where_predicates {
4154
for clause in where_clause {
42-
if let hir::WherePredicate::BoundPredicate(pred) = clause {
43-
if pred.is_param_bound(self_ty.to_def_id()) {
44-
search_bounds(pred.bounds);
45-
}
55+
if let hir::WherePredicate::BoundPredicate(pred) = clause
56+
&& pred.is_param_bound(self_ty.to_def_id())
57+
{
58+
search_bounds(pred.bounds);
4659
}
4760
}
4861
}
@@ -53,15 +66,13 @@ impl<'tcx> dyn AstConv<'tcx> + '_ {
5366
});
5467
}
5568

56-
let sized_def_id = tcx.lang_items().sized_trait();
57-
5869
let mut seen_sized_unbound = false;
5970
for unbound in unbounds {
60-
if let Some(sized_def_id) = sized_def_id {
61-
if unbound.trait_ref.path.res == Res::Def(DefKind::Trait, sized_def_id) {
62-
seen_sized_unbound = true;
63-
continue;
64-
}
71+
if let Some(sized_def_id) = sized_def_id
72+
&& unbound.trait_ref.path.res == Res::Def(DefKind::Trait, sized_def_id)
73+
{
74+
seen_sized_unbound = true;
75+
continue;
6576
}
6677
// There was a `?Trait` bound, but it was not `?Sized`; warn.
6778
tcx.dcx().span_warn(
@@ -71,15 +82,12 @@ impl<'tcx> dyn AstConv<'tcx> + '_ {
7182
);
7283
}
7384

74-
// If the above loop finished there was no `?Sized` bound; add implicitly sized if `Sized` is available.
75-
if sized_def_id.is_none() {
76-
// No lang item for `Sized`, so we can't add it as a bound.
77-
return;
78-
}
79-
if seen_sized_unbound {
80-
// There was in fact a `?Sized` bound, return without doing anything
81-
} else {
82-
// There was no `?Sized` bound; add implicitly sized if `Sized` is available.
85+
if seen_sized_unbound || seen_negative_sized_bound {
86+
// There was in fact a `?Sized` or `!Sized` bound;
87+
// we don't need to do anything.
88+
} else if sized_def_id.is_some() {
89+
// There was no `?Sized` or `!Sized` bound;
90+
// add `Sized` if it's available.
8391
bounds.push_sized(tcx, self_ty, span);
8492
}
8593
}

compiler/rustc_middle/src/ty/print/pretty.rs

+51-21
Original file line numberDiff line numberDiff line change
@@ -912,7 +912,8 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
912912

913913
let mut traits = FxIndexMap::default();
914914
let mut fn_traits = FxIndexMap::default();
915-
let mut is_sized = false;
915+
let mut has_sized_bound = false;
916+
let mut has_negative_sized_bound = false;
916917
let mut lifetimes = SmallVec::<[ty::Region<'tcx>; 1]>::new();
917918

918919
for (predicate, _) in bounds.iter_instantiated_copied(tcx, args) {
@@ -922,13 +923,24 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
922923
ty::ClauseKind::Trait(pred) => {
923924
let trait_ref = bound_predicate.rebind(pred.trait_ref);
924925

925-
// Don't print + Sized, but rather + ?Sized if absent.
926+
// Don't print `+ Sized`, but rather `+ ?Sized` if absent.
926927
if Some(trait_ref.def_id()) == tcx.lang_items().sized_trait() {
927-
is_sized = true;
928-
continue;
928+
match pred.polarity {
929+
ty::ImplPolarity::Positive | ty::ImplPolarity::Reservation => {
930+
has_sized_bound = true;
931+
continue;
932+
}
933+
ty::ImplPolarity::Negative => has_negative_sized_bound = true,
934+
}
929935
}
930936

931-
self.insert_trait_and_projection(trait_ref, None, &mut traits, &mut fn_traits);
937+
self.insert_trait_and_projection(
938+
trait_ref,
939+
pred.polarity,
940+
None,
941+
&mut traits,
942+
&mut fn_traits,
943+
);
932944
}
933945
ty::ClauseKind::Projection(pred) => {
934946
let proj_ref = bound_predicate.rebind(pred);
@@ -939,6 +951,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
939951

940952
self.insert_trait_and_projection(
941953
trait_ref,
954+
ty::ImplPolarity::Positive,
942955
Some(proj_ty),
943956
&mut traits,
944957
&mut fn_traits,
@@ -955,7 +968,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
955968

956969
let mut first = true;
957970
// Insert parenthesis around (Fn(A, B) -> C) if the opaque ty has more than one other trait
958-
let paren_needed = fn_traits.len() > 1 || traits.len() > 0 || !is_sized;
971+
let paren_needed = fn_traits.len() > 1 || traits.len() > 0 || !has_sized_bound;
959972

960973
for (fn_once_trait_ref, entry) in fn_traits {
961974
write!(self, "{}", if first { "" } else { " + " })?;
@@ -1002,18 +1015,21 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
10021015
// trait_refs we collected in the OpaqueFnEntry as normal trait refs.
10031016
_ => {
10041017
if entry.has_fn_once {
1005-
traits.entry(fn_once_trait_ref).or_default().extend(
1006-
// Group the return ty with its def id, if we had one.
1007-
entry
1008-
.return_ty
1009-
.map(|ty| (tcx.require_lang_item(LangItem::FnOnce, None), ty)),
1010-
);
1018+
traits
1019+
.entry((fn_once_trait_ref, ty::ImplPolarity::Positive))
1020+
.or_default()
1021+
.extend(
1022+
// Group the return ty with its def id, if we had one.
1023+
entry.return_ty.map(|ty| {
1024+
(tcx.require_lang_item(LangItem::FnOnce, None), ty)
1025+
}),
1026+
);
10111027
}
10121028
if let Some(trait_ref) = entry.fn_mut_trait_ref {
1013-
traits.entry(trait_ref).or_default();
1029+
traits.entry((trait_ref, ty::ImplPolarity::Positive)).or_default();
10141030
}
10151031
if let Some(trait_ref) = entry.fn_trait_ref {
1016-
traits.entry(trait_ref).or_default();
1032+
traits.entry((trait_ref, ty::ImplPolarity::Positive)).or_default();
10171033
}
10181034
}
10191035
}
@@ -1023,11 +1039,15 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
10231039
}
10241040

10251041
// Print the rest of the trait types (that aren't Fn* family of traits)
1026-
for (trait_ref, assoc_items) in traits {
1042+
for ((trait_ref, polarity), assoc_items) in traits {
10271043
write!(self, "{}", if first { "" } else { " + " })?;
10281044

10291045
self.wrap_binder(&trait_ref, |trait_ref, cx| {
10301046
define_scoped_cx!(cx);
1047+
1048+
if polarity == ty::ImplPolarity::Negative {
1049+
p!("!");
1050+
}
10311051
p!(print(trait_ref.print_only_trait_name()));
10321052

10331053
let generics = tcx.generics_of(trait_ref.def_id);
@@ -1094,9 +1114,15 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
10941114
})?;
10951115
}
10961116

1097-
if !is_sized {
1098-
write!(self, "{}?Sized", if first { "" } else { " + " })?;
1099-
} else if first {
1117+
let add_sized = has_sized_bound && (first || has_negative_sized_bound);
1118+
let add_maybe_sized = !has_sized_bound && !has_negative_sized_bound;
1119+
if add_sized || add_maybe_sized {
1120+
if !first {
1121+
write!(self, " + ")?;
1122+
}
1123+
if add_maybe_sized {
1124+
write!(self, "?")?;
1125+
}
11001126
write!(self, "Sized")?;
11011127
}
11021128

@@ -1128,9 +1154,10 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
11281154
fn insert_trait_and_projection(
11291155
&mut self,
11301156
trait_ref: ty::PolyTraitRef<'tcx>,
1157+
polarity: ty::ImplPolarity,
11311158
proj_ty: Option<(DefId, ty::Binder<'tcx, Term<'tcx>>)>,
11321159
traits: &mut FxIndexMap<
1133-
ty::PolyTraitRef<'tcx>,
1160+
(ty::PolyTraitRef<'tcx>, ty::ImplPolarity),
11341161
FxIndexMap<DefId, ty::Binder<'tcx, Term<'tcx>>>,
11351162
>,
11361163
fn_traits: &mut FxIndexMap<ty::PolyTraitRef<'tcx>, OpaqueFnEntry<'tcx>>,
@@ -1139,7 +1166,10 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
11391166

11401167
// If our trait_ref is FnOnce or any of its children, project it onto the parent FnOnce
11411168
// super-trait ref and record it there.
1142-
if let Some(fn_once_trait) = self.tcx().lang_items().fn_once_trait() {
1169+
// We skip negative Fn* bounds since they can't use parenthetical notation anyway.
1170+
if polarity == ty::ImplPolarity::Positive
1171+
&& let Some(fn_once_trait) = self.tcx().lang_items().fn_once_trait()
1172+
{
11431173
// If we have a FnOnce, then insert it into
11441174
if trait_def_id == fn_once_trait {
11451175
let entry = fn_traits.entry(trait_ref).or_default();
@@ -1167,7 +1197,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
11671197
}
11681198

11691199
// Otherwise, just group our traits and projection types.
1170-
traits.entry(trait_ref).or_default().extend(proj_ty);
1200+
traits.entry((trait_ref, polarity)).or_default().extend(proj_ty);
11711201
}
11721202

11731203
fn pretty_print_inherent_projection(

tests/ui/traits/negative-bounds/associated-constraints.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
#![feature(negative_bounds, associated_type_bounds)]
2-
//~^ WARN the feature `negative_bounds` is incomplete and may not be safe to use and/or cause compiler crashes
32

43
trait Trait {
54
type Assoc;
@@ -17,4 +16,7 @@ fn test3<T: !Trait<Assoc: Send>>() {}
1716
fn test4<T>() where T: !Trait<Assoc: Send> {}
1817
//~^ ERROR associated type constraints not allowed on negative bounds
1918

19+
fn test5<T>() where T: !Fn() -> i32 {}
20+
//~^ ERROR parenthetical notation may not be used for negative bounds
21+
2022
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,32 @@
11
error: associated type constraints not allowed on negative bounds
2-
--> $DIR/associated-constraints.rs:8:19
2+
--> $DIR/associated-constraints.rs:7:19
33
|
44
LL | fn test<T: !Trait<Assoc = i32>>() {}
55
| ^^^^^^^^^^^
66

77
error: associated type constraints not allowed on negative bounds
8-
--> $DIR/associated-constraints.rs:11:31
8+
--> $DIR/associated-constraints.rs:10:31
99
|
1010
LL | fn test2<T>() where T: !Trait<Assoc = i32> {}
1111
| ^^^^^^^^^^^
1212

1313
error: associated type constraints not allowed on negative bounds
14-
--> $DIR/associated-constraints.rs:14:20
14+
--> $DIR/associated-constraints.rs:13:20
1515
|
1616
LL | fn test3<T: !Trait<Assoc: Send>>() {}
1717
| ^^^^^^^^^^^
1818

1919
error: associated type constraints not allowed on negative bounds
20-
--> $DIR/associated-constraints.rs:17:31
20+
--> $DIR/associated-constraints.rs:16:31
2121
|
2222
LL | fn test4<T>() where T: !Trait<Assoc: Send> {}
2323
| ^^^^^^^^^^^
2424

25-
warning: the feature `negative_bounds` is incomplete and may not be safe to use and/or cause compiler crashes
26-
--> $DIR/associated-constraints.rs:1:12
25+
error: parenthetical notation may not be used for negative bounds
26+
--> $DIR/associated-constraints.rs:19:25
2727
|
28-
LL | #![feature(negative_bounds, associated_type_bounds)]
29-
| ^^^^^^^^^^^^^^^
30-
|
31-
= note: `#[warn(incomplete_features)]` on by default
28+
LL | fn test5<T>() where T: !Fn() -> i32 {}
29+
| ^^^^^^^^^^^
3230

33-
error: aborting due to 4 previous errors; 1 warning emitted
31+
error: aborting due to 5 previous errors
3432

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
// compile-flags: -Znext-solver
2+
3+
#![feature(negative_bounds, negative_impls)]
4+
5+
trait Trait {}
6+
impl !Trait for () {}
7+
8+
fn produce() -> impl !Trait {}
9+
fn consume(_: impl Trait) {}
10+
11+
fn main() {
12+
consume(produce()); //~ ERROR the trait bound `impl !Trait: Trait` is not satisfied
13+
}
14+
15+
fn weird0() -> impl Sized + !Sized {}
16+
//~^ ERROR mismatched types
17+
//~| ERROR type mismatch resolving `() == impl !Sized + Sized`
18+
fn weird1() -> impl !Sized + Sized {}
19+
//~^ ERROR mismatched types
20+
//~| ERROR type mismatch resolving `() == impl !Sized + Sized`
21+
fn weird2() -> impl !Sized {}
22+
//~^ ERROR mismatched types
23+
//~| ERROR type mismatch resolving `() == impl !Sized`

0 commit comments

Comments
 (0)