@@ -296,6 +296,7 @@ enum RelaxedBoundPolicy<'a> {
296296enum RelaxedBoundForbiddenReason {
297297 TraitObjectTy ,
298298 SuperTrait ,
299+ TraitAlias ,
299300 AssocTyBounds ,
300301 LateBoundVarsInScope ,
301302}
@@ -2085,12 +2086,14 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
20852086 span : Span ,
20862087 rbp : RelaxedBoundPolicy < ' _ > ,
20872088 ) {
2088- // Even though feature `more_maybe_bounds` bypasses the given policy and (currently) enables
2089- // relaxed bounds in every conceivable position[^1], we don't want to advertise it to the user
2090- // (via a feature gate) since it's super internal. Besides this, it'd be quite distracting .
2089+ // Even though feature `more_maybe_bounds` enables the user to relax all default bounds
2090+ // other than `Sized` in a lot more positions (thereby bypassing the given policy, we don't
2091+ // want to advertise it to the user (via a feature gate error ) since it's super internal.
20912092 //
2092- // [^1]: Strictly speaking, this is incorrect (at the very least for `Sized`) because it's
2093- // no longer fully consistent with default trait elaboration in HIR ty lowering.
2093+ // FIXME(more_maybe_bounds): Moreover, if we actually were to add new proper default traits
2094+ // (like the hypothetical `Move`) we want to properly validate the location according to
2095+ // default trait elaboration in HIR ty lowering (which depends on the specific trait in
2096+ // question: E.g., `?Sized` & `?Move` most likely won't be allowed in all the same places).
20942097
20952098 match rbp {
20962099 RelaxedBoundPolicy :: Allowed => return ,
@@ -2103,33 +2106,41 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
21032106 }
21042107 }
21052108 RelaxedBoundPolicy :: Forbidden ( reason) => {
2109+ let gate = |context, subject| {
2110+ let extended = self . tcx . features ( ) . more_maybe_bounds ( ) ;
2111+ let is_sized = trait_ref
2112+ . trait_def_id ( )
2113+ . is_some_and ( |def_id| self . tcx . is_lang_item ( def_id, hir:: LangItem :: Sized ) ) ;
2114+
2115+ if extended && !is_sized {
2116+ return ;
2117+ }
2118+
2119+ let prefix = if extended { "`Sized` " } else { "" } ;
2120+ let mut diag = self . dcx ( ) . struct_span_err (
2121+ span,
2122+ format ! ( "relaxed {prefix}bounds are not permitted in {context}" ) ,
2123+ ) ;
2124+ if is_sized {
2125+ diag. note ( format ! (
2126+ "{subject} are not implicitly bounded by `Sized`, \
2127+ so there is nothing to relax"
2128+ ) ) ;
2129+ }
2130+ diag. emit ( ) ;
2131+ } ;
2132+
21062133 match reason {
21072134 RelaxedBoundForbiddenReason :: TraitObjectTy => {
2108- if self . tcx . features ( ) . more_maybe_bounds ( ) {
2109- return ;
2110- }
2111-
2112- self . dcx ( ) . span_err (
2113- span,
2114- "relaxed bounds are not permitted in trait object types" ,
2115- ) ;
2135+ gate ( "trait object types" , "trait object types" ) ;
21162136 return ;
21172137 }
21182138 RelaxedBoundForbiddenReason :: SuperTrait => {
2119- if self . tcx . features ( ) . more_maybe_bounds ( ) {
2120- return ;
2121- }
2122-
2123- let mut diag = self . dcx ( ) . struct_span_err (
2124- span,
2125- "relaxed bounds are not permitted in supertrait bounds" ,
2126- ) ;
2127- if let Some ( def_id) = trait_ref. trait_def_id ( )
2128- && self . tcx . is_lang_item ( def_id, hir:: LangItem :: Sized )
2129- {
2130- diag. note ( "traits are `?Sized` by default" ) ;
2131- }
2132- diag. emit ( ) ;
2139+ gate ( "supertrait bounds" , "traits" ) ;
2140+ return ;
2141+ }
2142+ RelaxedBoundForbiddenReason :: TraitAlias => {
2143+ gate ( "trait alias bounds" , "trait aliases" ) ;
21332144 return ;
21342145 }
21352146 RelaxedBoundForbiddenReason :: AssocTyBounds
@@ -2142,7 +2153,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
21422153 . struct_span_err ( span, "this relaxed bound is not permitted here" )
21432154 . with_note (
21442155 "in this context, relaxed bounds are only allowed on \
2145- type parameters defined by the closest item",
2156+ type parameters defined on the closest item",
21462157 )
21472158 . emit ( ) ;
21482159 }
0 commit comments