Skip to content

Commit 07f0823

Browse files
committed
Reword diagnostic about relaxing non-Sized bound
* The phrasing "only does something for" made sense back when this diagnostic was a (hard) warning. Now however, it's simply a hard error and thus completely rules out "doing something". * The primary message was way too long * The new wording more closely mirrors the wording we use for applying other bound modifiers (like `const` and `async`) to incompatible traits. * "all other traits are not bound by default" is no longer accurate under Sized Hierarchy. E.g., traits and assoc tys are (currently) bounded by `MetaSized` by default but can't be relaxed using `?MetaSized` (instead, you relax it by adding `PointeeSized`). * I've decided against adding any diagnositic notes or suggestions for now like "trait `Trait` can't be relaxed as it's not bound by default" which would be incorrect for `MetaSized` and assoc tys as mentioned above) or "consider changing `?MetaSized` to `PointeeSized`" as the Sized Hierarchy impl is still WIP)
1 parent d8ab552 commit 07f0823

24 files changed

+131
-117
lines changed

compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -85,17 +85,17 @@ fn search_bounds_for<'tcx>(
8585
}
8686
}
8787

88-
fn collect_unbounds<'tcx>(
88+
fn collect_relaxed_bounds<'tcx>(
8989
hir_bounds: &'tcx [hir::GenericBound<'tcx>],
9090
self_ty_where_predicates: Option<(LocalDefId, &'tcx [hir::WherePredicate<'tcx>])>,
9191
) -> SmallVec<[&'tcx PolyTraitRef<'tcx>; 1]> {
92-
let mut unbounds: SmallVec<[_; 1]> = SmallVec::new();
92+
let mut relaxed_bounds: SmallVec<[_; 1]> = SmallVec::new();
9393
search_bounds_for(hir_bounds, self_ty_where_predicates, |ptr| {
9494
if matches!(ptr.modifiers.polarity, hir::BoundPolarity::Maybe(_)) {
95-
unbounds.push(ptr);
95+
relaxed_bounds.push(ptr);
9696
}
9797
});
98-
unbounds
98+
relaxed_bounds
9999
}
100100

101101
fn collect_bounds<'a, 'tcx>(
@@ -209,9 +209,22 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
209209
return;
210210
}
211211
} else {
212-
// Report invalid unbounds on sizedness-bounded generic parameters.
213-
let unbounds = collect_unbounds(hir_bounds, self_ty_where_predicates);
214-
self.check_and_report_invalid_unbounds_on_param(unbounds);
212+
// Report invalid relaxed bounds.
213+
// FIXME: Since we only call this validation function here in this function, we only
214+
// fully validate relaxed bounds in contexts where we perform
215+
// "sized elaboration". In most cases that doesn't matter because we *usually*
216+
// reject relaxed bounds outright during AST lowering.
217+
// However, this can easily get out of sync! Ideally, we would perform this step
218+
// where we are guaranteed to catch *all* bounds like in
219+
// `Self::lower_poly_trait_ref`. List of concrete issues:
220+
// FIXME(more_maybe_bounds): We don't call this for e.g., trait object tys or
221+
// supertrait bounds!
222+
// FIXME(trait_alias, #143122): We don't call it for the RHS. Arguably however,
223+
// AST lowering should reject them outright.
224+
// FIXME(associated_type_bounds): We don't call this for them. However, AST
225+
// lowering should reject them outright (#135229).
226+
let bounds = collect_relaxed_bounds(hir_bounds, self_ty_where_predicates);
227+
self.check_and_report_invalid_relaxed_bounds(bounds);
215228
}
216229

217230
let collected = collect_sizedness_bounds(tcx, hir_bounds, self_ty_where_predicates, span);

compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs

Lines changed: 22 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ use rustc_errors::{
88
};
99
use rustc_hir::def::{CtorOf, DefKind, Res};
1010
use rustc_hir::def_id::DefId;
11-
use rustc_hir::{self as hir, HirId, LangItem, PolyTraitRef};
11+
use rustc_hir::{self as hir, HirId, PolyTraitRef};
1212
use rustc_middle::bug;
1313
use rustc_middle::ty::fast_reject::{TreatParams, simplify_type};
1414
use rustc_middle::ty::print::{PrintPolyTraitRefExt as _, PrintTraitRefExt as _};
@@ -35,26 +35,24 @@ use crate::fluent_generated as fluent;
3535
use crate::hir_ty_lowering::{AssocItemQSelf, HirTyLowerer};
3636

3737
impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
38-
/// Check for multiple relaxed default bounds and relaxed bounds of non-sizedness traits.
39-
pub(crate) fn check_and_report_invalid_unbounds_on_param(
38+
/// Check for duplicate relaxed bounds and relaxed bounds of non-default traits.
39+
pub(crate) fn check_and_report_invalid_relaxed_bounds(
4040
&self,
41-
unbounds: SmallVec<[&PolyTraitRef<'_>; 1]>,
41+
relaxed_bounds: SmallVec<[&PolyTraitRef<'_>; 1]>,
4242
) {
4343
let tcx = self.tcx();
4444

45-
let sized_did = tcx.require_lang_item(LangItem::Sized, DUMMY_SP);
46-
4745
let mut unique_bounds = FxIndexSet::default();
4846
let mut seen_repeat = false;
49-
for unbound in &unbounds {
50-
if let Res::Def(DefKind::Trait, unbound_def_id) = unbound.trait_ref.path.res {
51-
seen_repeat |= !unique_bounds.insert(unbound_def_id);
47+
for bound in &relaxed_bounds {
48+
if let Res::Def(DefKind::Trait, trait_def_id) = bound.trait_ref.path.res {
49+
seen_repeat |= !unique_bounds.insert(trait_def_id);
5250
}
5351
}
5452

55-
if unbounds.len() > 1 {
53+
if relaxed_bounds.len() > 1 {
5654
let err = errors::MultipleRelaxedDefaultBounds {
57-
spans: unbounds.iter().map(|ptr| ptr.span).collect(),
55+
spans: relaxed_bounds.iter().map(|ptr| ptr.span).collect(),
5856
};
5957

6058
if seen_repeat {
@@ -64,24 +62,23 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
6462
};
6563
}
6664

67-
for unbound in unbounds {
68-
if let Res::Def(DefKind::Trait, did) = unbound.trait_ref.path.res
69-
&& ((did == sized_did) || tcx.is_default_trait(did))
65+
let sized_def_id = tcx.require_lang_item(hir::LangItem::Sized, DUMMY_SP);
66+
67+
for bound in relaxed_bounds {
68+
if let Res::Def(DefKind::Trait, def_id) = bound.trait_ref.path.res
69+
&& (def_id == sized_def_id || tcx.is_default_trait(def_id))
7070
{
7171
continue;
7272
}
73-
74-
let unbound_traits = match tcx.sess.opts.unstable_opts.experimental_default_bounds {
75-
true => "`?Sized` and `experimental_default_bounds`",
76-
false => "`?Sized`",
77-
};
7873
self.dcx().span_err(
79-
unbound.span,
80-
format!(
81-
"relaxing a default bound only does something for {}; all other traits are \
82-
not bound by default",
83-
unbound_traits
84-
),
74+
bound.span,
75+
if tcx.sess.opts.unstable_opts.experimental_default_bounds
76+
|| tcx.features().more_maybe_bounds()
77+
{
78+
"bound modifier `?` can only be applied to default traits like `Sized`"
79+
} else {
80+
"bound modifier `?` can only be applied to `Sized`"
81+
},
8582
);
8683
}
8784
}

tests/ui/feature-gates/feature-gate-more-maybe-bounds.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,14 @@ fn foo(_: Box<dyn Trait1 + ?Trait2>) {}
99
//~^ ERROR relaxed bounds are not permitted in trait object types
1010
fn bar<T: ?Trait1 + ?Trait2>(_: T) {}
1111
//~^ ERROR type parameter has more than one relaxed default bound, only one is supported
12-
//~| ERROR relaxing a default bound only does something for `?Sized`; all other traits are not bound by default
13-
//~| ERROR relaxing a default bound only does something for `?Sized`; all other traits are not bound by default
12+
//~| ERROR bound modifier `?` can only be applied to `Sized`
13+
//~| ERROR bound modifier `?` can only be applied to `Sized`
1414

1515
trait Trait {}
1616
// Do not suggest `#![feature(more_maybe_bounds)]` for repetitions
1717
fn baz<T: ?Trait + ?Trait>(_ : T) {}
1818
//~^ ERROR type parameter has more than one relaxed default bound, only one is supported
19-
//~| ERROR relaxing a default bound only does something for `?Sized`; all other traits are not bound by default
20-
//~| ERROR relaxing a default bound only does something for `?Sized`; all other traits are not bound by default
19+
//~| ERROR bound modifier `?` can only be applied to `Sized`
20+
//~| ERROR bound modifier `?` can only be applied to `Sized`
2121

2222
fn main() {}

tests/ui/feature-gates/feature-gate-more-maybe-bounds.stderr

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -35,13 +35,13 @@ LL | fn bar<T: ?Trait1 + ?Trait2>(_: T) {}
3535
= help: add `#![feature(more_maybe_bounds)]` to the crate attributes to enable
3636
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
3737

38-
error: relaxing a default bound only does something for `?Sized`; all other traits are not bound by default
38+
error: bound modifier `?` can only be applied to `Sized`
3939
--> $DIR/feature-gate-more-maybe-bounds.rs:10:11
4040
|
4141
LL | fn bar<T: ?Trait1 + ?Trait2>(_: T) {}
4242
| ^^^^^^^
4343

44-
error: relaxing a default bound only does something for `?Sized`; all other traits are not bound by default
44+
error: bound modifier `?` can only be applied to `Sized`
4545
--> $DIR/feature-gate-more-maybe-bounds.rs:10:21
4646
|
4747
LL | fn bar<T: ?Trait1 + ?Trait2>(_: T) {}
@@ -53,13 +53,13 @@ error[E0203]: type parameter has more than one relaxed default bound, only one i
5353
LL | fn baz<T: ?Trait + ?Trait>(_ : T) {}
5454
| ^^^^^^ ^^^^^^
5555

56-
error: relaxing a default bound only does something for `?Sized`; all other traits are not bound by default
56+
error: bound modifier `?` can only be applied to `Sized`
5757
--> $DIR/feature-gate-more-maybe-bounds.rs:17:11
5858
|
5959
LL | fn baz<T: ?Trait + ?Trait>(_ : T) {}
6060
| ^^^^^^
6161

62-
error: relaxing a default bound only does something for `?Sized`; all other traits are not bound by default
62+
error: bound modifier `?` can only be applied to `Sized`
6363
--> $DIR/feature-gate-more-maybe-bounds.rs:17:20
6464
|
6565
LL | fn baz<T: ?Trait + ?Trait>(_ : T) {}

tests/ui/impl-trait/opt-out-bound-not-satisfied.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@
33
44
use std::future::Future;
55
fn foo() -> impl ?Future<Output = impl Send> {
6-
//~^ ERROR: relaxing a default bound only does something for `?Sized`
7-
//~| ERROR: relaxing a default bound only does something for `?Sized`
6+
//~^ ERROR: bound modifier `?` can only be applied to `Sized`
7+
//~| ERROR: bound modifier `?` can only be applied to `Sized`
88
()
99
}
1010

tests/ui/impl-trait/opt-out-bound-not-satisfied.stderr

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
1-
error: relaxing a default bound only does something for `?Sized`; all other traits are not bound by default
1+
error: bound modifier `?` can only be applied to `Sized`
22
--> $DIR/opt-out-bound-not-satisfied.rs:5:18
33
|
44
LL | fn foo() -> impl ?Future<Output = impl Send> {
55
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
66

7-
error: relaxing a default bound only does something for `?Sized`; all other traits are not bound by default
7+
error: bound modifier `?` can only be applied to `Sized`
88
--> $DIR/opt-out-bound-not-satisfied.rs:5:18
99
|
1010
LL | fn foo() -> impl ?Future<Output = impl Send> {

tests/ui/issues/issue-37534.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
struct Foo<T: ?Hash> {}
22
//~^ ERROR expected trait, found derive macro `Hash`
3-
//~| ERROR relaxing a default bound only does something for `?Sized`
3+
//~| ERROR bound modifier `?` can only be applied to `Sized`
44

55
fn main() {}

tests/ui/issues/issue-37534.stderr

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ help: consider importing this trait instead
99
LL + use std::hash::Hash;
1010
|
1111

12-
error: relaxing a default bound only does something for `?Sized`; all other traits are not bound by default
12+
error: bound modifier `?` can only be applied to `Sized`
1313
--> $DIR/issue-37534.rs:1:15
1414
|
1515
LL | struct Foo<T: ?Hash> {}

tests/ui/issues/issue-87199.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,12 @@
66

77
// Check that these function definitions only emit warnings, not errors
88
fn arg<T: ?Send>(_: T) {}
9-
//~^ ERROR: relaxing a default bound only does something for `?Sized`
9+
//~^ ERROR: bound modifier `?` can only be applied to `Sized`
1010
fn ref_arg<T: ?Send>(_: &T) {}
11-
//~^ ERROR: relaxing a default bound only does something for `?Sized`
11+
//~^ ERROR: bound modifier `?` can only be applied to `Sized`
1212
fn ret() -> impl Iterator<Item = ()> + ?Send { std::iter::empty() }
13-
//~^ ERROR: relaxing a default bound only does something for `?Sized`
14-
//~| ERROR: relaxing a default bound only does something for `?Sized`
13+
//~^ ERROR: bound modifier `?` can only be applied to `Sized`
14+
//~| ERROR: bound modifier `?` can only be applied to `Sized`
1515

1616
// Check that there's no `?Sized` relaxation!
1717
fn main() {

tests/ui/issues/issue-87199.stderr

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,22 @@
1-
error: relaxing a default bound only does something for `?Sized`; all other traits are not bound by default
1+
error: bound modifier `?` can only be applied to `Sized`
22
--> $DIR/issue-87199.rs:8:11
33
|
44
LL | fn arg<T: ?Send>(_: T) {}
55
| ^^^^^
66

7-
error: relaxing a default bound only does something for `?Sized`; all other traits are not bound by default
7+
error: bound modifier `?` can only be applied to `Sized`
88
--> $DIR/issue-87199.rs:10:15
99
|
1010
LL | fn ref_arg<T: ?Send>(_: &T) {}
1111
| ^^^^^
1212

13-
error: relaxing a default bound only does something for `?Sized`; all other traits are not bound by default
13+
error: bound modifier `?` can only be applied to `Sized`
1414
--> $DIR/issue-87199.rs:12:40
1515
|
1616
LL | fn ret() -> impl Iterator<Item = ()> + ?Send { std::iter::empty() }
1717
| ^^^^^
1818

19-
error: relaxing a default bound only does something for `?Sized`; all other traits are not bound by default
19+
error: bound modifier `?` can only be applied to `Sized`
2020
--> $DIR/issue-87199.rs:12:40
2121
|
2222
LL | fn ret() -> impl Iterator<Item = ()> + ?Send { std::iter::empty() }

tests/ui/sized-hierarchy/default-bound.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,13 @@ fn neg_sized<T: ?Sized>() {}
1414
fn metasized<T: MetaSized>() {}
1515

1616
fn neg_metasized<T: ?MetaSized>() {}
17-
//~^ ERROR relaxing a default bound only does something for `?Sized`; all other traits are not bound by default
17+
//~^ ERROR bound modifier `?` can only be applied to `Sized`
1818

1919

2020
fn pointeesized<T: PointeeSized>() { }
2121

2222
fn neg_pointeesized<T: ?PointeeSized>() { }
23-
//~^ ERROR relaxing a default bound only does something for `?Sized`; all other traits are not bound by default
23+
//~^ ERROR bound modifier `?` can only be applied to `Sized`
2424

2525

2626
fn main() {

tests/ui/sized-hierarchy/default-bound.stderr

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
1-
error: relaxing a default bound only does something for `?Sized`; all other traits are not bound by default
1+
error: bound modifier `?` can only be applied to `Sized`
22
--> $DIR/default-bound.rs:16:21
33
|
44
LL | fn neg_metasized<T: ?MetaSized>() {}
55
| ^^^^^^^^^^
66

7-
error: relaxing a default bound only does something for `?Sized`; all other traits are not bound by default
7+
error: bound modifier `?` can only be applied to `Sized`
88
--> $DIR/default-bound.rs:22:24
99
|
1010
LL | fn neg_pointeesized<T: ?PointeeSized>() { }

tests/ui/trait-bounds/maybe-bound-has-path-args.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,6 @@ trait Trait {}
22

33
fn test<T: ?self::<i32>::Trait>() {}
44
//~^ ERROR type arguments are not allowed on module `maybe_bound_has_path_args`
5-
//~| ERROR relaxing a default bound only does something for `?Sized`
5+
//~| ERROR bound modifier `?` can only be applied to `Sized`
66

77
fn main() {}

tests/ui/trait-bounds/maybe-bound-has-path-args.stderr

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
error: relaxing a default bound only does something for `?Sized`; all other traits are not bound by default
1+
error: bound modifier `?` can only be applied to `Sized`
22
--> $DIR/maybe-bound-has-path-args.rs:3:12
33
|
44
LL | fn test<T: ?self::<i32>::Trait>() {}

tests/ui/trait-bounds/maybe-bound-with-assoc.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,11 @@ trait HasAssoc {
22
type Assoc;
33
}
44
fn hasassoc<T: ?HasAssoc<Assoc = ()>>() {}
5-
//~^ ERROR relaxing a default bound
5+
//~^ ERROR bound modifier `?` can only be applied to `Sized`
66

77
trait NoAssoc {}
88
fn noassoc<T: ?NoAssoc<Missing = ()>>() {}
9-
//~^ ERROR relaxing a default bound
9+
//~^ ERROR bound modifier `?` can only be applied to `Sized`
1010
//~| ERROR associated type `Missing` not found for `NoAssoc`
1111

1212
fn main() {}

tests/ui/trait-bounds/maybe-bound-with-assoc.stderr

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
1-
error: relaxing a default bound only does something for `?Sized`; all other traits are not bound by default
1+
error: bound modifier `?` can only be applied to `Sized`
22
--> $DIR/maybe-bound-with-assoc.rs:4:16
33
|
44
LL | fn hasassoc<T: ?HasAssoc<Assoc = ()>>() {}
55
| ^^^^^^^^^^^^^^^^^^^^^
66

7-
error: relaxing a default bound only does something for `?Sized`; all other traits are not bound by default
7+
error: bound modifier `?` can only be applied to `Sized`
88
--> $DIR/maybe-bound-with-assoc.rs:8:15
99
|
1010
LL | fn noassoc<T: ?NoAssoc<Missing = ()>>() {}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
// FIXME(more_maybe_bounds): Even under `more_maybe_bounds` / `-Zexperimental-default-bounds`,
2+
// trying to relax non-default bounds should still be an error in all contexts! As you can see
3+
// there are placed like supertrait bounds and trait object types where we currently don't perform
4+
// this check.
5+
#![feature(auto_traits, more_maybe_bounds, negative_impls)]
6+
7+
trait Trait1 {}
8+
auto trait Trait2 {}
9+
10+
// FIXME: `?Trait1` should be rejected, `Trait1` isn't marked `#[lang = "default_traitN"]`.
11+
trait Trait3: ?Trait1 {}
12+
trait Trait4 where Self: Trait1 {}
13+
14+
// FIXME: `?Trait2` should be rejected, `Trait2` isn't marked `#[lang = "default_traitN"]`.
15+
fn foo(_: Box<(dyn Trait3 + ?Trait2)>) {}
16+
fn bar<T: ?Sized + ?Trait2 + ?Trait1 + ?Trait4>(_: &T) {}
17+
//~^ ERROR bound modifier `?` can only be applied to default traits like `Sized`
18+
//~| ERROR bound modifier `?` can only be applied to default traits like `Sized`
19+
//~| ERROR bound modifier `?` can only be applied to default traits like `Sized`
20+
21+
struct S;
22+
impl !Trait2 for S {}
23+
impl Trait1 for S {}
24+
impl Trait3 for S {}
25+
26+
fn main() {
27+
foo(Box::new(S));
28+
bar(&S);
29+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
error: bound modifier `?` can only be applied to default traits like `Sized`
2+
--> $DIR/more_maybe_bounds.rs:16:20
3+
|
4+
LL | fn bar<T: ?Sized + ?Trait2 + ?Trait1 + ?Trait4>(_: &T) {}
5+
| ^^^^^^^
6+
7+
error: bound modifier `?` can only be applied to default traits like `Sized`
8+
--> $DIR/more_maybe_bounds.rs:16:30
9+
|
10+
LL | fn bar<T: ?Sized + ?Trait2 + ?Trait1 + ?Trait4>(_: &T) {}
11+
| ^^^^^^^
12+
13+
error: bound modifier `?` can only be applied to default traits like `Sized`
14+
--> $DIR/more_maybe_bounds.rs:16:40
15+
|
16+
LL | fn bar<T: ?Sized + ?Trait2 + ?Trait1 + ?Trait4>(_: &T) {}
17+
| ^^^^^^^
18+
19+
error: aborting due to 3 previous errors
20+

0 commit comments

Comments
 (0)