Skip to content

Commit 03dfb84

Browse files
committed
More robustly reject relaxing non-default trait bounds
1 parent aee9d3b commit 03dfb84

File tree

12 files changed

+224
-117
lines changed

12 files changed

+224
-117
lines changed

compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs

Lines changed: 48 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,53 @@ 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 tcx = self.tcx();
339+
340+
if let Res::Def(DefKind::Trait, def_id) = trait_ref.path.res
341+
&& (tcx.is_lang_item(def_id, hir::LangItem::Sized) || tcx.is_default_trait(def_id))
342+
{
343+
return;
344+
}
345+
346+
self.dcx().span_err(
347+
span,
348+
if tcx.sess.opts.unstable_opts.experimental_default_bounds
349+
|| tcx.features().more_maybe_bounds()
350+
{
351+
"bound modifier `?` can only be applied to default traits"
352+
} else {
353+
"bound modifier `?` can only be applied to `Sized`"
354+
},
355+
);
356+
}
357+
311358
/// Lower HIR bounds into `bounds` given the self type `param_ty` and the overarching late-bound vars if any.
312359
///
313360
/// ### 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/feature-gates/feature-gate-more-maybe-bounds.rs

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,17 @@
1-
#![feature(auto_traits)]
1+
#![feature(auto_traits, lang_items)]
22

3-
trait Trait1 {}
4-
auto trait Trait2 {}
5-
trait Trait3: ?Trait1 {} //~ ERROR relaxed bounds are not permitted in supertrait bounds
6-
trait Trait4 where Self: ?Trait1 {} //~ ERROR this relaxed bound is not permitted here
3+
#[lang = "default_trait1"] trait Trait1 {}
4+
#[lang = "default_trait2"] auto trait Trait2 {}
5+
6+
trait Trait3: ?Trait1 {}
7+
//~^ ERROR relaxed bounds are not permitted in supertrait bounds
8+
//~| ERROR bound modifier `?` can only be applied to `Sized`
9+
//~| ERROR bound modifier `?` can only be applied to `Sized`
10+
//~| ERROR bound modifier `?` can only be applied to `Sized`
711

812
fn foo(_: Box<dyn Trait1 + ?Trait2>) {}
913
//~^ ERROR relaxed bounds are not permitted in trait object types
14+
//~| ERROR bound modifier `?` can only be applied to `Sized`
1015
fn bar<T: ?Trait1 + ?Trait2>(_: T) {}
1116
//~^ ERROR bound modifier `?` can only be applied to `Sized`
1217
//~| ERROR bound modifier `?` can only be applied to `Sized`
Lines changed: 31 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,54 @@
11
error: relaxed bounds are not permitted in supertrait bounds
2-
--> $DIR/feature-gate-more-maybe-bounds.rs:5:15
2+
--> $DIR/feature-gate-more-maybe-bounds.rs:6:15
33
|
44
LL | trait Trait3: ?Trait1 {}
55
| ^^^^^^^
66

7-
error: this relaxed bound is not permitted here
8-
--> $DIR/feature-gate-more-maybe-bounds.rs:6:26
7+
error: relaxed bounds are not permitted in trait object types
8+
--> $DIR/feature-gate-more-maybe-bounds.rs:12:28
99
|
10-
LL | trait Trait4 where Self: ?Trait1 {}
11-
| ^^^^^^^
10+
LL | fn foo(_: Box<dyn Trait1 + ?Trait2>) {}
11+
| ^^^^^^^
12+
13+
error: bound modifier `?` can only be applied to `Sized`
14+
--> $DIR/feature-gate-more-maybe-bounds.rs:6:15
1215
|
13-
= note: in this context, relaxed bounds are only allowed on type parameters defined on the closest item
16+
LL | trait Trait3: ?Trait1 {}
17+
| ^^^^^^^
1418

15-
error: relaxed bounds are not permitted in trait object types
16-
--> $DIR/feature-gate-more-maybe-bounds.rs:8:28
19+
error: bound modifier `?` can only be applied to `Sized`
20+
--> $DIR/feature-gate-more-maybe-bounds.rs:6:15
21+
|
22+
LL | trait Trait3: ?Trait1 {}
23+
| ^^^^^^^
24+
|
25+
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
26+
27+
error: bound modifier `?` can only be applied to `Sized`
28+
--> $DIR/feature-gate-more-maybe-bounds.rs:6:15
29+
|
30+
LL | trait Trait3: ?Trait1 {}
31+
| ^^^^^^^
32+
|
33+
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
34+
35+
error: bound modifier `?` can only be applied to `Sized`
36+
--> $DIR/feature-gate-more-maybe-bounds.rs:12:28
1737
|
1838
LL | fn foo(_: Box<dyn Trait1 + ?Trait2>) {}
1939
| ^^^^^^^
2040

2141
error: bound modifier `?` can only be applied to `Sized`
22-
--> $DIR/feature-gate-more-maybe-bounds.rs:10:11
42+
--> $DIR/feature-gate-more-maybe-bounds.rs:15:11
2343
|
2444
LL | fn bar<T: ?Trait1 + ?Trait2>(_: T) {}
2545
| ^^^^^^^
2646

2747
error: bound modifier `?` can only be applied to `Sized`
28-
--> $DIR/feature-gate-more-maybe-bounds.rs:10:21
48+
--> $DIR/feature-gate-more-maybe-bounds.rs:15:21
2949
|
3050
LL | fn bar<T: ?Trait1 + ?Trait2>(_: T) {}
3151
| ^^^^^^^
3252

33-
error: aborting due to 5 previous errors
53+
error: aborting due to 8 previous errors
3454

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

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,17 @@ trait MetaSized_: MetaSized { }
1212

1313
trait NegMetaSized: ?MetaSized { }
1414
//~^ ERROR relaxed bounds are not permitted in supertrait bounds
15-
15+
//~| ERROR bound modifier `?` can only be applied to `Sized`
16+
//~| ERROR bound modifier `?` can only be applied to `Sized`
17+
//~| ERROR bound modifier `?` can only be applied to `Sized`
1618

1719
trait PointeeSized_: PointeeSized { }
1820

1921
trait NegPointeeSized: ?PointeeSized { }
2022
//~^ ERROR relaxed bounds are not permitted in supertrait bounds
23+
//~| ERROR bound modifier `?` can only be applied to `Sized`
24+
//~| ERROR bound modifier `?` can only be applied to `Sized`
25+
//~| ERROR bound modifier `?` can only be applied to `Sized`
2126

2227
trait Bare {}
2328

0 commit comments

Comments
 (0)