Skip to content

Commit 91d1ed2

Browse files
committed
More robustly reject relaxing non-default trait bounds
1 parent ff412f2 commit 91d1ed2

File tree

6 files changed

+113
-73
lines changed

6 files changed

+113
-73
lines changed

compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs

Lines changed: 47 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -204,7 +204,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
204204
// FIXME(more_maybe_bounds): We don't call this for trait object tys, supertrait
205205
// bounds, trait alias bounds, assoc type bounds (ATB)!
206206
let bounds = collect_relaxed_bounds(hir_bounds, self_ty_where_predicates);
207-
self.check_and_report_invalid_relaxed_bounds(bounds);
207+
self.reject_duplicate_relaxed_bounds(bounds);
208208
}
209209

210210
let collected = collect_sizedness_bounds(tcx, hir_bounds, self_ty_where_predicates, span);
@@ -308,6 +308,52 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
308308
!self.tcx().has_attr(CRATE_DEF_ID, sym::rustc_no_implicit_bounds) && !collected.any()
309309
}
310310

311+
fn reject_duplicate_relaxed_bounds(&self, relaxed_bounds: SmallVec<[&PolyTraitRef<'_>; 1]>) {
312+
let tcx = self.tcx();
313+
314+
let mut grouped_bounds = FxIndexMap::<_, Vec<_>>::default();
315+
316+
for bound in &relaxed_bounds {
317+
if let Res::Def(DefKind::Trait, trait_def_id) = bound.trait_ref.path.res {
318+
grouped_bounds.entry(trait_def_id).or_default().push(bound.span);
319+
}
320+
}
321+
322+
for (trait_def_id, spans) in grouped_bounds {
323+
if spans.len() > 1 {
324+
let name = tcx.item_name(trait_def_id);
325+
self.dcx()
326+
.struct_span_err(spans, format!("duplicate relaxed `{name}` bounds"))
327+
.with_code(E0203)
328+
.emit();
329+
}
330+
}
331+
}
332+
333+
pub(crate) fn require_bound_to_relax_default_trait(
334+
&self,
335+
trait_ref: hir::TraitRef<'_>,
336+
span: Span,
337+
) {
338+
let Res::Def(DefKind::Trait, def_id) = trait_ref.path.res else { return };
339+
let tcx = self.tcx();
340+
341+
if tcx.is_lang_item(def_id, hir::LangItem::Sized) || tcx.is_default_trait(def_id) {
342+
return;
343+
}
344+
345+
self.dcx().span_err(
346+
span,
347+
if tcx.sess.opts.unstable_opts.experimental_default_bounds
348+
|| tcx.features().more_maybe_bounds()
349+
{
350+
"bound modifier `?` can only be applied to default traits"
351+
} else {
352+
"bound modifier `?` can only be applied to `Sized`"
353+
},
354+
);
355+
}
356+
311357
/// Lower HIR bounds into `bounds` given the self type `param_ty` and the overarching late-bound vars if any.
312358
///
313359
/// ### Examples

compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs

Lines changed: 1 addition & 47 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, PolyTraitRef};
11+
use rustc_hir::{self as hir, HirId};
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,52 +35,6 @@ use crate::fluent_generated as fluent;
3535
use crate::hir_ty_lowering::{AssocItemQSelf, HirTyLowerer};
3636

3737
impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
38-
/// Check for duplicate relaxed bounds and relaxed bounds of non-default traits.
39-
pub(crate) fn check_and_report_invalid_relaxed_bounds(
40-
&self,
41-
relaxed_bounds: SmallVec<[&PolyTraitRef<'_>; 1]>,
42-
) {
43-
let tcx = self.tcx();
44-
45-
let mut grouped_bounds = FxIndexMap::<_, Vec<_>>::default();
46-
47-
for bound in &relaxed_bounds {
48-
if let Res::Def(DefKind::Trait, trait_def_id) = bound.trait_ref.path.res {
49-
grouped_bounds.entry(trait_def_id).or_default().push(bound.span);
50-
}
51-
}
52-
53-
for (trait_def_id, spans) in grouped_bounds {
54-
if spans.len() > 1 {
55-
let name = tcx.item_name(trait_def_id);
56-
self.dcx()
57-
.struct_span_err(spans, format!("duplicate relaxed `{name}` bounds"))
58-
.with_code(E0203)
59-
.emit();
60-
}
61-
}
62-
63-
let sized_def_id = tcx.require_lang_item(hir::LangItem::Sized, DUMMY_SP);
64-
65-
for bound in relaxed_bounds {
66-
if let Res::Def(DefKind::Trait, def_id) = bound.trait_ref.path.res
67-
&& (def_id == sized_def_id || tcx.is_default_trait(def_id))
68-
{
69-
continue;
70-
}
71-
self.dcx().span_err(
72-
bound.span,
73-
if tcx.sess.opts.unstable_opts.experimental_default_bounds
74-
|| tcx.features().more_maybe_bounds()
75-
{
76-
"bound modifier `?` can only be applied to default traits like `Sized`"
77-
} else {
78-
"bound modifier `?` can only be applied to `Sized`"
79-
},
80-
);
81-
}
82-
}
83-
8438
/// On missing type parameters, emit an E0393 error and provide a structured suggestion using
8539
/// the type parameter's name as a placeholder.
8640
pub(crate) fn report_missing_type_params(

compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -767,7 +767,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
767767

768768
// We use the *resolved* bound vars later instead of the HIR ones since the former
769769
// also include the bound vars of the overarching predicate if applicable.
770-
let hir::PolyTraitRef { bound_generic_params: _, modifiers, ref trait_ref, span } =
770+
let hir::PolyTraitRef { bound_generic_params: _, modifiers, trait_ref, span } =
771771
*poly_trait_ref;
772772
let hir::TraitBoundModifiers { constness, polarity } = modifiers;
773773

@@ -791,6 +791,8 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
791791
rustc_ast::BoundPolarity::Positive => (ty::PredicatePolarity::Positive, bounds),
792792
rustc_ast::BoundPolarity::Negative(_) => (ty::PredicatePolarity::Negative, bounds),
793793
rustc_ast::BoundPolarity::Maybe(_) => {
794+
self.require_bound_to_relax_default_trait(trait_ref, span);
795+
794796
(ty::PredicatePolarity::Positive, &mut Vec::new())
795797
}
796798
};

compiler/rustc_middle/src/ty/context.rs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1782,9 +1782,7 @@ impl<'tcx> TyCtxt<'tcx> {
17821782
}
17831783

17841784
pub fn is_default_trait(self, def_id: DefId) -> bool {
1785-
self.default_traits()
1786-
.iter()
1787-
.any(|&default_trait| self.lang_items().get(default_trait) == Some(def_id))
1785+
self.default_traits().iter().any(|&default_trait| self.is_lang_item(def_id, default_trait))
17881786
}
17891787

17901788
/// Returns a range of the start/end indices specified with the

tests/ui/trait-bounds/more_maybe_bounds.rs

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,40 +1,40 @@
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 places like supertrait bounds, trait object types or associated type bounds (ATB)
4-
// where we currently don't perform this check.
51
#![feature(auto_traits, more_maybe_bounds, negative_impls)]
62

73
trait Trait1 {}
84
auto trait Trait2 {}
95

10-
// FIXME: `?Trait1` should be rejected, `Trait1` isn't marked `#[lang = "default_traitN"]`.
116
trait Trait3: ?Trait1 {}
7+
//~^ ERROR bound modifier `?` can only be applied to default traits
8+
//~| ERROR bound modifier `?` can only be applied to default traits
9+
//~| ERROR bound modifier `?` can only be applied to default traits
1210
trait Trait4 where Self: Trait1 {}
1311

14-
// FIXME: `?Trait2` should be rejected, `Trait2` isn't marked `#[lang = "default_traitN"]`.
12+
1513
fn foo(_: Box<(dyn Trait3 + ?Trait2)>) {}
14+
//~^ ERROR bound modifier `?` can only be applied to default traits
1615

1716
fn bar<T: ?Sized + ?Trait2 + ?Trait1 + ?Trait4>(_: &T) {}
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-
//~| ERROR bound modifier `?` can only be applied to default traits like `Sized`
17+
//~^ ERROR bound modifier `?` can only be applied to default traits
18+
//~| ERROR bound modifier `?` can only be applied to default traits
19+
//~| ERROR bound modifier `?` can only be applied to default traits
2120

22-
// FIXME: `?Trait1` should be rejected, `Trait1` isn't marked `#[lang = "default_traitN"]`.
2321
fn baz<T>() where T: Iterator<Item: ?Trait1> {}
2422
//~^ ERROR this relaxed bound is not permitted here
23+
//~| ERROR bound modifier `?` can only be applied to default traits
2524

2625
struct S1<T>(T);
2726

2827
impl<T> S1<T> {
2928
fn f() where T: ?Trait1 {}
3029
//~^ ERROR this relaxed bound is not permitted here
30+
//~| ERROR bound modifier `?` can only be applied to default traits
3131
}
3232

3333
trait Trait5<'a> {}
3434

3535
struct S2<T>(T) where for<'a> T: ?Trait5<'a>;
3636
//~^ ERROR this relaxed bound is not permitted here
37-
//~| ERROR bound modifier `?` can only be applied to default traits like `Sized`
37+
//~| ERROR bound modifier `?` can only be applied to default traits
3838

3939
struct S;
4040
impl !Trait2 for S {}
Lines changed: 50 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
error: this relaxed bound is not permitted here
2-
--> $DIR/more_maybe_bounds.rs:23:37
2+
--> $DIR/more_maybe_bounds.rs:21:37
33
|
44
LL | fn baz<T>() where T: Iterator<Item: ?Trait1> {}
55
| ^^^^^^^
66
|
77
= note: in this context, relaxed bounds are only allowed on type parameters defined on the closest item
88

99
error: this relaxed bound is not permitted here
10-
--> $DIR/more_maybe_bounds.rs:29:21
10+
--> $DIR/more_maybe_bounds.rs:28:21
1111
|
1212
LL | fn f() where T: ?Trait1 {}
1313
| ^^^^^^^
@@ -22,29 +22,69 @@ LL | struct S2<T>(T) where for<'a> T: ?Trait5<'a>;
2222
|
2323
= note: in this context, relaxed bounds are only allowed on type parameters defined on the closest item
2424

25-
error: bound modifier `?` can only be applied to default traits like `Sized`
26-
--> $DIR/more_maybe_bounds.rs:17:20
25+
error: bound modifier `?` can only be applied to default traits
26+
--> $DIR/more_maybe_bounds.rs:6:15
27+
|
28+
LL | trait Trait3: ?Trait1 {}
29+
| ^^^^^^^
30+
31+
error: bound modifier `?` can only be applied to default traits
32+
--> $DIR/more_maybe_bounds.rs:6:15
33+
|
34+
LL | trait Trait3: ?Trait1 {}
35+
| ^^^^^^^
36+
|
37+
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
38+
39+
error: bound modifier `?` can only be applied to default traits
40+
--> $DIR/more_maybe_bounds.rs:6:15
41+
|
42+
LL | trait Trait3: ?Trait1 {}
43+
| ^^^^^^^
44+
|
45+
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
46+
47+
error: bound modifier `?` can only be applied to default traits
48+
--> $DIR/more_maybe_bounds.rs:13:29
49+
|
50+
LL | fn foo(_: Box<(dyn Trait3 + ?Trait2)>) {}
51+
| ^^^^^^^
52+
53+
error: bound modifier `?` can only be applied to default traits
54+
--> $DIR/more_maybe_bounds.rs:16:20
2755
|
2856
LL | fn bar<T: ?Sized + ?Trait2 + ?Trait1 + ?Trait4>(_: &T) {}
2957
| ^^^^^^^
3058

31-
error: bound modifier `?` can only be applied to default traits like `Sized`
32-
--> $DIR/more_maybe_bounds.rs:17:30
59+
error: bound modifier `?` can only be applied to default traits
60+
--> $DIR/more_maybe_bounds.rs:16:30
3361
|
3462
LL | fn bar<T: ?Sized + ?Trait2 + ?Trait1 + ?Trait4>(_: &T) {}
3563
| ^^^^^^^
3664

37-
error: bound modifier `?` can only be applied to default traits like `Sized`
38-
--> $DIR/more_maybe_bounds.rs:17:40
65+
error: bound modifier `?` can only be applied to default traits
66+
--> $DIR/more_maybe_bounds.rs:16:40
3967
|
4068
LL | fn bar<T: ?Sized + ?Trait2 + ?Trait1 + ?Trait4>(_: &T) {}
4169
| ^^^^^^^
4270

43-
error: bound modifier `?` can only be applied to default traits like `Sized`
71+
error: bound modifier `?` can only be applied to default traits
72+
--> $DIR/more_maybe_bounds.rs:21:37
73+
|
74+
LL | fn baz<T>() where T: Iterator<Item: ?Trait1> {}
75+
| ^^^^^^^
76+
77+
error: bound modifier `?` can only be applied to default traits
4478
--> $DIR/more_maybe_bounds.rs:35:34
4579
|
4680
LL | struct S2<T>(T) where for<'a> T: ?Trait5<'a>;
4781
| ^^^^^^^^^^^
4882

49-
error: aborting due to 7 previous errors
83+
error: bound modifier `?` can only be applied to default traits
84+
--> $DIR/more_maybe_bounds.rs:28:21
85+
|
86+
LL | fn f() where T: ?Trait1 {}
87+
| ^^^^^^^
88+
89+
error: aborting due to 13 previous errors
5090

0 commit comments

Comments
 (0)