diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index 0fddb0ee4cc8c..3acf69ec2b7d0 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -1443,16 +1443,19 @@ impl<'hir> LoweringContext<'_, 'hir> { ImplTraitContext::disallowed(), ), bounded_ty: this.lower_ty(bounded_ty, ImplTraitContext::disallowed()), - bounds: this.arena.alloc_from_iter(bounds.iter().filter_map(|bound| { - match *bound { - // Ignore `?Trait` bounds. - // They were copied into type parameters already. - GenericBound::Trait(_, TraitBoundModifier::Maybe) => None, - _ => Some( - this.lower_param_bound(bound, ImplTraitContext::disallowed()), - ), - } - })), + bounds: this.arena.alloc_from_iter(bounds.iter().map( + |bound| match bound { + // We used to ignore `?Trait` bounds, as they were copied into type + // parameters already, but we need to keep them around only for + // diagnostics when we suggest removal of `?Sized` bounds. See + // `suggest_constraining_type_param`. This will need to change if + // we ever allow something *other* than `?Sized`. + GenericBound::Trait(p, TraitBoundModifier::Maybe) => { + hir::GenericBound::Unsized(p.span) + } + _ => this.lower_param_bound(bound, ImplTraitContext::disallowed()), + }, + )), span, }) }) diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 3bd42ba6090dd..581f177ad14f6 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -2160,12 +2160,12 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { tpb: &GenericBound, itctx: ImplTraitContext<'_, 'hir>, ) -> hir::GenericBound<'hir> { - match *tpb { - GenericBound::Trait(ref ty, modifier) => hir::GenericBound::Trait( - self.lower_poly_trait_ref(ty, itctx), - self.lower_trait_bound_modifier(modifier), + match tpb { + GenericBound::Trait(p, modifier) => hir::GenericBound::Trait( + self.lower_poly_trait_ref(p, itctx), + self.lower_trait_bound_modifier(*modifier), ), - GenericBound::Outlives(ref lifetime) => { + GenericBound::Outlives(lifetime) => { hir::GenericBound::Outlives(self.lower_lifetime(lifetime)) } } diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index db7fe6cb12ff1..aac5d296f17b5 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -442,6 +442,7 @@ pub enum GenericBound<'hir> { Trait(PolyTraitRef<'hir>, TraitBoundModifier), // FIXME(davidtwco): Introduce `PolyTraitRef::LangItem` LangItemTrait(LangItem, Span, HirId, &'hir GenericArgs<'hir>), + Unsized(Span), Outlives(Lifetime), } @@ -458,6 +459,7 @@ impl GenericBound<'_> { GenericBound::Trait(t, ..) => t.span, GenericBound::LangItemTrait(_, span, ..) => *span, GenericBound::Outlives(l) => l.span, + GenericBound::Unsized(span) => *span, } } } diff --git a/compiler/rustc_hir/src/intravisit.rs b/compiler/rustc_hir/src/intravisit.rs index 17835493cda62..ae186d66004d7 100644 --- a/compiler/rustc_hir/src/intravisit.rs +++ b/compiler/rustc_hir/src/intravisit.rs @@ -889,6 +889,7 @@ pub fn walk_param_bound<'v, V: Visitor<'v>>(visitor: &mut V, bound: &'v GenericB visitor.visit_generic_args(span, args); } GenericBound::Outlives(ref lifetime) => visitor.visit_lifetime(lifetime), + GenericBound::Unsized(_) => {} } } diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs index 90ceb1d5c91ec..2b372392575e9 100644 --- a/compiler/rustc_hir_pretty/src/lib.rs +++ b/compiler/rustc_hir_pretty/src/lib.rs @@ -2230,6 +2230,9 @@ impl<'a> State<'a> { GenericBound::Outlives(lt) => { self.print_lifetime(lt); } + GenericBound::Unsized(_) => { + self.s.word("?Sized"); + } } } } diff --git a/compiler/rustc_middle/src/ty/diagnostics.rs b/compiler/rustc_middle/src/ty/diagnostics.rs index bfb4c0cb538de..4cfb104bee3a4 100644 --- a/compiler/rustc_middle/src/ty/diagnostics.rs +++ b/compiler/rustc_middle/src/ty/diagnostics.rs @@ -2,6 +2,7 @@ use crate::ty::TyKind::*; use crate::ty::{InferTy, TyCtxt, TyS}; +use rustc_data_structures::fx::FxHashSet; use rustc_errors::{Applicability, DiagnosticBuilder}; use rustc_hir as hir; use rustc_hir::def_id::DefId; @@ -105,6 +106,116 @@ pub fn suggest_arbitrary_trait_bound( true } +fn suggest_removing_unsized_bound( + generics: &hir::Generics<'_>, + err: &mut DiagnosticBuilder<'_>, + param_name: &str, + param: &hir::GenericParam<'_>, + def_id: Option, +) { + // See if there's a `?Sized` bound that can be removed to suggest that. + // First look at the `where` clause because we can have `where T: ?Sized`, but that + // `?Sized` bound is *also* included in the `GenericParam` as a bound, which breaks + // the spans. Hence the somewhat involved logic that follows. + let mut where_unsized_bounds = FxHashSet::default(); + for (where_pos, predicate) in generics.where_clause.predicates.iter().enumerate() { + match predicate { + WherePredicate::BoundPredicate(WhereBoundPredicate { + bounded_ty: + hir::Ty { + kind: + hir::TyKind::Path(hir::QPath::Resolved( + None, + hir::Path { + segments: [segment], + res: hir::def::Res::Def(hir::def::DefKind::TyParam, _), + .. + }, + )), + .. + }, + bounds, + span, + .. + }) if segment.ident.as_str() == param_name => { + for (pos, bound) in bounds.iter().enumerate() { + match bound { + hir::GenericBound::Unsized(_) => {} + hir::GenericBound::Trait(poly, hir::TraitBoundModifier::Maybe) + if poly.trait_ref.trait_def_id() == def_id => {} + _ => continue, + } + let sp = match ( + bounds.len(), + pos, + generics.where_clause.predicates.len(), + where_pos, + ) { + // where T: ?Sized + // ^^^^^^^^^^^^^^^ + (1, _, 1, _) => generics.where_clause.span, + // where Foo: Bar, T: ?Sized, + // ^^^^^^^^^^^ + (1, _, len, pos) if pos == len - 1 => generics.where_clause.predicates + [pos - 1] + .span() + .shrink_to_hi() + .to(*span), + // where T: ?Sized, Foo: Bar, + // ^^^^^^^^^^^ + (1, _, _, pos) => { + span.until(generics.where_clause.predicates[pos + 1].span()) + } + // where T: ?Sized + Bar, Foo: Bar, + // ^^^^^^^^^ + (_, 0, _, _) => bound.span().to(bounds[1].span().shrink_to_lo()), + // where T: Bar + ?Sized, Foo: Bar, + // ^^^^^^^^^ + (_, pos, _, _) => bounds[pos - 1].span().shrink_to_hi().to(bound.span()), + }; + where_unsized_bounds.insert(bound.span()); + err.span_suggestion_verbose( + sp, + "consider removing the `?Sized` bound to make the \ + type parameter `Sized`", + String::new(), + Applicability::MaybeIncorrect, + ); + } + } + _ => {} + } + } + for (pos, bound) in param.bounds.iter().enumerate() { + match bound { + hir::GenericBound::Trait(poly, hir::TraitBoundModifier::Maybe) + if poly.trait_ref.trait_def_id() == def_id + && !where_unsized_bounds.contains(&bound.span()) => + { + let sp = match (param.bounds.len(), pos) { + // T: ?Sized, + // ^^^^^^^^ + (1, _) => param.span.shrink_to_hi().to(bound.span()), + // T: ?Sized + Bar, + // ^^^^^^^^^ + (_, 0) => bound.span().to(param.bounds[1].span().shrink_to_lo()), + // T: Bar + ?Sized, + // ^^^^^^^^^ + (_, pos) => param.bounds[pos - 1].span().shrink_to_hi().to(bound.span()), + }; + err.span_suggestion_verbose( + sp, + "consider removing the `?Sized` bound to make the type parameter \ + `Sized`", + String::new(), + Applicability::MaybeIncorrect, + ); + } + _ => {} + } + } +} + /// Suggest restricting a type param with a new bound. pub fn suggest_constraining_type_param( tcx: TyCtxt<'_>, @@ -130,6 +241,7 @@ pub fn suggest_constraining_type_param( if def_id == tcx.lang_items().sized_trait() { // Type parameters are already `Sized` by default. err.span_label(param.span, &format!("this type parameter needs to be `{}`", constraint)); + suggest_removing_unsized_bound(generics, err, param_name, param, def_id); return true; } let mut suggest_restrict = |span| { diff --git a/compiler/rustc_save_analysis/src/dump_visitor.rs b/compiler/rustc_save_analysis/src/dump_visitor.rs index 4f8dc7d16d4b9..34302c3fb429f 100644 --- a/compiler/rustc_save_analysis/src/dump_visitor.rs +++ b/compiler/rustc_save_analysis/src/dump_visitor.rs @@ -689,6 +689,7 @@ impl<'tcx> DumpVisitor<'tcx> { (Some(self.tcx.require_lang_item(lang_item, Some(span))), span) } hir::GenericBound::Outlives(..) => continue, + hir::GenericBound::Unsized(_) => continue, }; if let Some(id) = def_id { diff --git a/compiler/rustc_typeck/src/astconv/mod.rs b/compiler/rustc_typeck/src/astconv/mod.rs index 9871b14754e62..92583f2b0ea9b 100644 --- a/compiler/rustc_typeck/src/astconv/mod.rs +++ b/compiler/rustc_typeck/src/astconv/mod.rs @@ -943,7 +943,8 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { false, ); } - hir::GenericBound::Trait(_, hir::TraitBoundModifier::Maybe) => {} + hir::GenericBound::Trait(_, hir::TraitBoundModifier::Maybe) + | hir::GenericBound::Unsized(_) => {} hir::GenericBound::LangItemTrait(lang_item, span, hir_id, args) => self .instantiate_lang_item_trait_ref( lang_item, span, hir_id, args, param_ty, bounds, diff --git a/compiler/rustc_typeck/src/collect.rs b/compiler/rustc_typeck/src/collect.rs index 997fdcefe037a..ce74d6fec9eae 100644 --- a/compiler/rustc_typeck/src/collect.rs +++ b/compiler/rustc_typeck/src/collect.rs @@ -2230,7 +2230,9 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericP let constness = match modifier { hir::TraitBoundModifier::MaybeConst => hir::Constness::NotConst, hir::TraitBoundModifier::None => constness, - hir::TraitBoundModifier::Maybe => bug!("this wasn't handled"), + // We ignore `where T: ?Sized`, it is already part of + // type parameter `T`. + hir::TraitBoundModifier::Maybe => continue, }; let mut bounds = Bounds::default(); @@ -2260,6 +2262,8 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericP predicates.extend(bounds.predicates(tcx, ty)); } + hir::GenericBound::Unsized(_) => {} + hir::GenericBound::Outlives(lifetime) => { let region = >::ast_region_to_region(&icx, lifetime, None); @@ -2521,6 +2525,7 @@ fn predicates_from_bound<'tcx>( ); bounds.predicates(astconv.tcx(), param_ty) } + hir::GenericBound::Unsized(_) => vec![], hir::GenericBound::Outlives(ref lifetime) => { let region = astconv.ast_region_to_region(lifetime, None); let pred = ty::PredicateKind::TypeOutlives(ty::OutlivesPredicate(param_ty, region)) diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index fd79292477cab..75ea30bb565f1 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -128,6 +128,7 @@ impl Clean for hir::GenericBound<'_> { fn clean(&self, cx: &mut DocContext<'_>) -> GenericBound { match *self { hir::GenericBound::Outlives(lt) => GenericBound::Outlives(lt.clean(cx)), + hir::GenericBound::Unsized(_) => GenericBound::maybe_sized(cx), hir::GenericBound::LangItemTrait(lang_item, span, _, generic_args) => { let def_id = cx.tcx.require_lang_item(lang_item, Some(span)); @@ -562,13 +563,19 @@ impl Clean for hir::Generics<'_> { WherePredicate::BoundPredicate { ty: Generic(ref name), ref mut bounds, .. } => { - if bounds.is_empty() { + if let [] | [GenericBound::TraitBound(_, hir::TraitBoundModifier::Maybe)] = + &bounds[..] + { for param in &mut generics.params { match param.kind { GenericParamDefKind::Lifetime => {} GenericParamDefKind::Type { bounds: ref mut ty_bounds, .. } => { if ¶m.name == name { mem::swap(bounds, ty_bounds); + // We now keep track of `?Sized` obligations in the HIR. + // If we don't clear `ty_bounds` we end up with + // `fn foo(_: X) where X: ?Sized`. + ty_bounds.clear(); break; } } diff --git a/src/test/ui/const-generics/const-argument-if-length.full.stderr b/src/test/ui/const-generics/const-argument-if-length.full.stderr index c6088e665a232..a9f1d0eb65718 100644 --- a/src/test/ui/const-generics/const-argument-if-length.full.stderr +++ b/src/test/ui/const-generics/const-argument-if-length.full.stderr @@ -10,6 +10,11 @@ LL | if std::mem::size_of::() == 0 { | LL | pub const fn size_of() -> usize { | - required by this bound in `std::mem::size_of` + | +help: consider removing the `?Sized` bound to make the type parameter `Sized` + | +LL | pub const fn is_zst() -> usize { + | -- error[E0277]: the size for values of type `T` cannot be known at compilation time --> $DIR/const-argument-if-length.rs:16:12 @@ -21,6 +26,10 @@ LL | value: T, | = note: only the last field of a struct may have a dynamically sized type = help: change the field's type to have a statically known size +help: consider removing the `?Sized` bound to make the type parameter `Sized` + | +LL | pub struct AtLeastByte { + | -- help: borrowed types always have a statically known size | LL | value: &T, diff --git a/src/test/ui/const-generics/const-argument-if-length.min.stderr b/src/test/ui/const-generics/const-argument-if-length.min.stderr index bc06e8d7fb123..173a14716635d 100644 --- a/src/test/ui/const-generics/const-argument-if-length.min.stderr +++ b/src/test/ui/const-generics/const-argument-if-length.min.stderr @@ -17,6 +17,10 @@ LL | value: T, | = note: only the last field of a struct may have a dynamically sized type = help: change the field's type to have a statically known size +help: consider removing the `?Sized` bound to make the type parameter `Sized` + | +LL | pub struct AtLeastByte { + | -- help: borrowed types always have a statically known size | LL | value: &T, diff --git a/src/test/ui/dst/dst-object-from-unsized-type.stderr b/src/test/ui/dst/dst-object-from-unsized-type.stderr index 2d12265df98ed..6c57dd9316fbd 100644 --- a/src/test/ui/dst/dst-object-from-unsized-type.stderr +++ b/src/test/ui/dst/dst-object-from-unsized-type.stderr @@ -7,6 +7,10 @@ LL | let u: &dyn Foo = t; | ^ doesn't have a size known at compile-time | = note: required for the cast to the object type `dyn Foo` +help: consider removing the `?Sized` bound to make the type parameter `Sized` + | +LL | fn test1(t: &T) { + | -- error[E0277]: the size for values of type `T` cannot be known at compilation time --> $DIR/dst-object-from-unsized-type.rs:13:23 @@ -17,6 +21,10 @@ LL | let v: &dyn Foo = t as &dyn Foo; | ^ doesn't have a size known at compile-time | = note: required for the cast to the object type `dyn Foo` +help: consider removing the `?Sized` bound to make the type parameter `Sized` + | +LL | fn test2(t: &T) { + | -- error[E0277]: the size for values of type `str` cannot be known at compilation time --> $DIR/dst-object-from-unsized-type.rs:18:28 diff --git a/src/test/ui/packed/issue-27060-2.stderr b/src/test/ui/packed/issue-27060-2.stderr index 5dbcc96e87488..64e061a89b410 100644 --- a/src/test/ui/packed/issue-27060-2.stderr +++ b/src/test/ui/packed/issue-27060-2.stderr @@ -8,6 +8,10 @@ LL | data: T, | = note: the last field of a packed struct may only have a dynamically sized type if it does not need drop to be run = help: change the field's type to have a statically known size +help: consider removing the `?Sized` bound to make the type parameter `Sized` + | +LL | pub struct Bad { + | -- help: borrowed types always have a statically known size | LL | data: &T, diff --git a/src/test/ui/suggestions/adt-param-with-implicit-sized-bound.stderr b/src/test/ui/suggestions/adt-param-with-implicit-sized-bound.stderr index 18ba7254446b4..ac3902dc6de9a 100644 --- a/src/test/ui/suggestions/adt-param-with-implicit-sized-bound.stderr +++ b/src/test/ui/suggestions/adt-param-with-implicit-sized-bound.stderr @@ -91,6 +91,10 @@ LL | struct X(T); | ^ - ...if indirection were used here: `Box` | | | this could be changed to `T: ?Sized`... +help: consider removing the `?Sized` bound to make the type parameter `Sized` + | +LL | struct Struct5{ + | -- error: aborting due to 5 previous errors diff --git a/src/test/ui/trait-bounds/unsized-bound.rs b/src/test/ui/trait-bounds/unsized-bound.rs new file mode 100644 index 0000000000000..035b8ef1bdebc --- /dev/null +++ b/src/test/ui/trait-bounds/unsized-bound.rs @@ -0,0 +1,32 @@ +trait Trait {} +impl Trait<(A, B)> for (A, B) where A: ?Sized, B: ?Sized, {} +//~^ ERROR E0277 +//~| ERROR E0277 +impl Trait<(A, B, C)> for (A, B, C) where A: ?Sized, {} +//~^ ERROR E0277 +//~| ERROR E0277 +//~| ERROR E0277 +trait Trait2 {} +impl Trait2<(A, B)> for (A, B) {} +//~^ ERROR E0277 +//~| ERROR E0277 +trait Trait3 {} +impl Trait3 for A where A: ?Sized {} +//~^ ERROR E0277 +trait Trait4 {} +impl Trait4 for A {} +//~^ ERROR E0277 +trait Trait5 {} +impl Trait5 for X where X: ?Sized {} +//~^ ERROR E0277 +trait Trait6 {} +impl Trait6 for X {} +//~^ ERROR E0277 +trait Trait7 {} +impl Trait7 for X where Y: ?Sized {} +//~^ ERROR E0277 +trait Trait8 {} +impl Trait8 for X {} +//~^ ERROR E0277 + +fn main() {} diff --git a/src/test/ui/trait-bounds/unsized-bound.stderr b/src/test/ui/trait-bounds/unsized-bound.stderr new file mode 100644 index 0000000000000..30163ab797813 --- /dev/null +++ b/src/test/ui/trait-bounds/unsized-bound.stderr @@ -0,0 +1,234 @@ +error[E0277]: the size for values of type `B` cannot be known at compilation time + --> $DIR/unsized-bound.rs:2:12 + | +LL | trait Trait {} + | - required by this bound in `Trait` +LL | impl Trait<(A, B)> for (A, B) where A: ?Sized, B: ?Sized, {} + | - ^^^^^^^^^^^^^ doesn't have a size known at compile-time + | | + | this type parameter needs to be `std::marker::Sized` + | + = note: required because it appears within the type `(A, B)` +help: consider removing the `?Sized` bound to make the type parameter `Sized` + | +LL | impl Trait<(A, B)> for (A, B) where A: ?Sized, {} + | -- +help: consider relaxing the implicit `Sized` restriction + | +LL | trait Trait {} + | ^^^^^^^^ + +error[E0277]: the size for values of type `A` cannot be known at compilation time + --> $DIR/unsized-bound.rs:2:30 + | +LL | impl Trait<(A, B)> for (A, B) where A: ?Sized, B: ?Sized, {} + | - ^^^^^^ doesn't have a size known at compile-time + | | + | this type parameter needs to be `std::marker::Sized` + | + = note: only the last element of a tuple may have a dynamically sized type +help: consider removing the `?Sized` bound to make the type parameter `Sized` + | +LL | impl Trait<(A, B)> for (A, B) where B: ?Sized, {} + | -- + +error[E0277]: the size for values of type `C` cannot be known at compilation time + --> $DIR/unsized-bound.rs:5:31 + | +LL | trait Trait {} + | - required by this bound in `Trait` +... +LL | impl Trait<(A, B, C)> for (A, B, C) where A: ?Sized, {} + | - ^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | | + | this type parameter needs to be `std::marker::Sized` + | + = note: required because it appears within the type `(A, B, C)` +help: consider removing the `?Sized` bound to make the type parameter `Sized` + | +LL | impl Trait<(A, B, C)> for (A, B, C) where A: ?Sized, {} + | -- +help: consider relaxing the implicit `Sized` restriction + | +LL | trait Trait {} + | ^^^^^^^^ + +error[E0277]: the size for values of type `A` cannot be known at compilation time + --> $DIR/unsized-bound.rs:5:52 + | +LL | impl Trait<(A, B, C)> for (A, B, C) where A: ?Sized, {} + | - ^^^^^^^^^ doesn't have a size known at compile-time + | | + | this type parameter needs to be `std::marker::Sized` + | + = note: only the last element of a tuple may have a dynamically sized type +help: consider removing the `?Sized` bound to make the type parameter `Sized` + | +LL | impl Trait<(A, B, C)> for (A, B, C) {} + | -- + +error[E0277]: the size for values of type `B` cannot be known at compilation time + --> $DIR/unsized-bound.rs:5:52 + | +LL | impl Trait<(A, B, C)> for (A, B, C) where A: ?Sized, {} + | - ^^^^^^^^^ doesn't have a size known at compile-time + | | + | this type parameter needs to be `std::marker::Sized` + | + = note: only the last element of a tuple may have a dynamically sized type +help: consider removing the `?Sized` bound to make the type parameter `Sized` + | +LL | impl Trait<(A, B, C)> for (A, B, C) where A: ?Sized, {} + | -- + +error[E0277]: the size for values of type `B` cannot be known at compilation time + --> $DIR/unsized-bound.rs:10:28 + | +LL | trait Trait2 {} + | - required by this bound in `Trait2` +LL | impl Trait2<(A, B)> for (A, B) {} + | - ^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | | + | this type parameter needs to be `std::marker::Sized` + | + = note: required because it appears within the type `(A, B)` +help: consider removing the `?Sized` bound to make the type parameter `Sized` + | +LL | impl Trait2<(A, B)> for (A, B) {} + | -- +help: consider relaxing the implicit `Sized` restriction + | +LL | trait Trait2 {} + | ^^^^^^^^ + +error[E0277]: the size for values of type `A` cannot be known at compilation time + --> $DIR/unsized-bound.rs:10:47 + | +LL | impl Trait2<(A, B)> for (A, B) {} + | - ^^^^^^ doesn't have a size known at compile-time + | | + | this type parameter needs to be `std::marker::Sized` + | + = note: only the last element of a tuple may have a dynamically sized type +help: consider removing the `?Sized` bound to make the type parameter `Sized` + | +LL | impl Trait2<(A, B)> for (A, B) {} + | -- + +error[E0277]: the size for values of type `A` cannot be known at compilation time + --> $DIR/unsized-bound.rs:14:9 + | +LL | trait Trait3 {} + | - required by this bound in `Trait3` +LL | impl Trait3 for A where A: ?Sized {} + | - ^^^^^^^^^ doesn't have a size known at compile-time + | | + | this type parameter needs to be `std::marker::Sized` + | +help: consider removing the `?Sized` bound to make the type parameter `Sized` + | +LL | impl Trait3 for A {} + | -- +help: consider relaxing the implicit `Sized` restriction + | +LL | trait Trait3 {} + | ^^^^^^^^ + +error[E0277]: the size for values of type `A` cannot be known at compilation time + --> $DIR/unsized-bound.rs:17:17 + | +LL | trait Trait4 {} + | - required by this bound in `Trait4` +LL | impl Trait4 for A {} + | - ^^^^^^^^^ doesn't have a size known at compile-time + | | + | this type parameter needs to be `std::marker::Sized` + | +help: consider removing the `?Sized` bound to make the type parameter `Sized` + | +LL | impl Trait4 for A {} + | -- +help: consider relaxing the implicit `Sized` restriction + | +LL | trait Trait4 {} + | ^^^^^^^^ + +error[E0277]: the size for values of type `X` cannot be known at compilation time + --> $DIR/unsized-bound.rs:20:12 + | +LL | trait Trait5 {} + | - required by this bound in `Trait5` +LL | impl Trait5 for X where X: ?Sized {} + | - ^^^^^^^^^^^^ doesn't have a size known at compile-time + | | + | this type parameter needs to be `std::marker::Sized` + | +help: consider removing the `?Sized` bound to make the type parameter `Sized` + | +LL | impl Trait5 for X {} + | -- +help: consider relaxing the implicit `Sized` restriction + | +LL | trait Trait5 {} + | ^^^^^^^^ + +error[E0277]: the size for values of type `X` cannot be known at compilation time + --> $DIR/unsized-bound.rs:23:20 + | +LL | trait Trait6 {} + | - required by this bound in `Trait6` +LL | impl Trait6 for X {} + | - ^^^^^^^^^^^^ doesn't have a size known at compile-time + | | + | this type parameter needs to be `std::marker::Sized` + | +help: consider removing the `?Sized` bound to make the type parameter `Sized` + | +LL | impl Trait6 for X {} + | -- +help: consider relaxing the implicit `Sized` restriction + | +LL | trait Trait6 {} + | ^^^^^^^^ + +error[E0277]: the size for values of type `Y` cannot be known at compilation time + --> $DIR/unsized-bound.rs:26:12 + | +LL | trait Trait7 {} + | - required by this bound in `Trait7` +LL | impl Trait7 for X where Y: ?Sized {} + | - ^^^^^^^^^^^^ doesn't have a size known at compile-time + | | + | this type parameter needs to be `std::marker::Sized` + | +help: consider removing the `?Sized` bound to make the type parameter `Sized` + | +LL | impl Trait7 for X {} + | -- +help: consider relaxing the implicit `Sized` restriction + | +LL | trait Trait7 {} + | ^^^^^^^^ + +error[E0277]: the size for values of type `Y` cannot be known at compilation time + --> $DIR/unsized-bound.rs:29:20 + | +LL | trait Trait8 {} + | - required by this bound in `Trait8` +LL | impl Trait8 for X {} + | - ^^^^^^^^^^^^ doesn't have a size known at compile-time + | | + | this type parameter needs to be `std::marker::Sized` + | +help: consider removing the `?Sized` bound to make the type parameter `Sized` + | +LL | impl Trait8 for X {} + | -- +help: consider relaxing the implicit `Sized` restriction + | +LL | trait Trait8 {} + | ^^^^^^^^ + +error: aborting due to 13 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/traits/suggest-where-clause.stderr b/src/test/ui/traits/suggest-where-clause.stderr index f15e7e35839d5..47f287807d4b9 100644 --- a/src/test/ui/traits/suggest-where-clause.stderr +++ b/src/test/ui/traits/suggest-where-clause.stderr @@ -11,6 +11,11 @@ LL | mem::size_of::(); | LL | pub const fn size_of() -> usize { | - required by this bound in `std::mem::size_of` + | +help: consider removing the `?Sized` bound to make the type parameter `Sized` + | +LL | fn check() { + | -- error[E0277]: the size for values of type `U` cannot be known at compilation time --> $DIR/suggest-where-clause.rs:10:5 @@ -31,6 +36,10 @@ note: required because it appears within the type `Misc` | LL | struct Misc(T); | ^^^^ +help: consider removing the `?Sized` bound to make the type parameter `Sized` + | +LL | fn check() { + | -- error[E0277]: the trait bound `u64: From` is not satisfied --> $DIR/suggest-where-clause.rs:15:5 diff --git a/src/test/ui/union/union-sized-field.stderr b/src/test/ui/union/union-sized-field.stderr index b916bbe8ad10a..ef86c624e9b19 100644 --- a/src/test/ui/union/union-sized-field.stderr +++ b/src/test/ui/union/union-sized-field.stderr @@ -8,6 +8,10 @@ LL | value: T, | = note: no field of a union may have a dynamically sized type = help: change the field's type to have a statically known size +help: consider removing the `?Sized` bound to make the type parameter `Sized` + | +LL | union Foo { + | -- help: borrowed types always have a statically known size | LL | value: &T, @@ -27,6 +31,10 @@ LL | value: T, | = note: only the last field of a struct may have a dynamically sized type = help: change the field's type to have a statically known size +help: consider removing the `?Sized` bound to make the type parameter `Sized` + | +LL | struct Foo2 { + | -- help: borrowed types always have a statically known size | LL | value: &T, @@ -46,6 +54,10 @@ LL | Value(T), | = note: no field of an enum variant may have a dynamically sized type = help: change the field's type to have a statically known size +help: consider removing the `?Sized` bound to make the type parameter `Sized` + | +LL | enum Foo3 { + | -- help: borrowed types always have a statically known size | LL | Value(&T), diff --git a/src/test/ui/unsized/unsized-bare-typaram.stderr b/src/test/ui/unsized/unsized-bare-typaram.stderr index 19978ae24cacb..35bba1c103a05 100644 --- a/src/test/ui/unsized/unsized-bare-typaram.stderr +++ b/src/test/ui/unsized/unsized-bare-typaram.stderr @@ -7,6 +7,11 @@ LL | fn foo() { bar::() } | - ^ doesn't have a size known at compile-time | | | this type parameter needs to be `std::marker::Sized` + | +help: consider removing the `?Sized` bound to make the type parameter `Sized` + | +LL | fn foo() { bar::() } + | -- error: aborting due to previous error diff --git a/src/test/ui/unsized/unsized-enum.stderr b/src/test/ui/unsized/unsized-enum.stderr index 601db7d1cd983..f66ce2af30416 100644 --- a/src/test/ui/unsized/unsized-enum.stderr +++ b/src/test/ui/unsized/unsized-enum.stderr @@ -16,6 +16,10 @@ LL | enum Foo { FooSome(U), FooNone } | ^ - ...if indirection were used here: `Box` | | | this could be changed to `U: ?Sized`... +help: consider removing the `?Sized` bound to make the type parameter `Sized` + | +LL | fn foo2() { not_sized::>() } + | -- error: aborting due to previous error diff --git a/src/test/ui/unsized/unsized-enum2.stderr b/src/test/ui/unsized/unsized-enum2.stderr index 1b6c85858159d..b9a03d904af4d 100644 --- a/src/test/ui/unsized/unsized-enum2.stderr +++ b/src/test/ui/unsized/unsized-enum2.stderr @@ -9,6 +9,10 @@ LL | VA(W), | = note: no field of an enum variant may have a dynamically sized type = help: change the field's type to have a statically known size +help: consider removing the `?Sized` bound to make the type parameter `Sized` + | +LL | enum E { + | -- help: borrowed types always have a statically known size | LL | VA(&W), @@ -29,6 +33,10 @@ LL | VB{x: X}, | = note: no field of an enum variant may have a dynamically sized type = help: change the field's type to have a statically known size +help: consider removing the `?Sized` bound to make the type parameter `Sized` + | +LL | enum E { + | -- help: borrowed types always have a statically known size | LL | VB{x: &X}, @@ -49,6 +57,10 @@ LL | VC(isize, Y), | = note: no field of an enum variant may have a dynamically sized type = help: change the field's type to have a statically known size +help: consider removing the `?Sized` bound to make the type parameter `Sized` + | +LL | enum E { + | -- help: borrowed types always have a statically known size | LL | VC(isize, &Y), @@ -69,6 +81,10 @@ LL | VD{u: isize, x: Z}, | = note: no field of an enum variant may have a dynamically sized type = help: change the field's type to have a statically known size +help: consider removing the `?Sized` bound to make the type parameter `Sized` + | +LL | enum E { + | -- help: borrowed types always have a statically known size | LL | VD{u: isize, x: &Z}, diff --git a/src/test/ui/unsized/unsized-fn-arg.fixed b/src/test/ui/unsized/unsized-fn-arg.fixed index 2c686c6c2b271..fd9b159a48138 100644 --- a/src/test/ui/unsized/unsized-fn-arg.fixed +++ b/src/test/ui/unsized/unsized-fn-arg.fixed @@ -2,5 +2,5 @@ #![crate_type="lib"] #![allow(unused)] -fn f(t: &T) {} +fn f(t: &T) {} //~^ ERROR the size for values of type `T` cannot be known at compilation time diff --git a/src/test/ui/unsized/unsized-fn-arg.stderr b/src/test/ui/unsized/unsized-fn-arg.stderr index 6b802ddf542d5..acb8a598d2c8a 100644 --- a/src/test/ui/unsized/unsized-fn-arg.stderr +++ b/src/test/ui/unsized/unsized-fn-arg.stderr @@ -7,6 +7,10 @@ LL | fn f(t: T) {} | this type parameter needs to be `std::marker::Sized` | = help: unsized fn params are gated as an unstable feature +help: consider removing the `?Sized` bound to make the type parameter `Sized` + | +LL | fn f(t: T) {} + | -- help: function arguments must have a statically known size, borrowed types always have a known size | LL | fn f(t: &T) {} diff --git a/src/test/ui/unsized/unsized-inherent-impl-self-type.stderr b/src/test/ui/unsized/unsized-inherent-impl-self-type.stderr index 9d072eda4e81c..99f75d8c5b303 100644 --- a/src/test/ui/unsized/unsized-inherent-impl-self-type.stderr +++ b/src/test/ui/unsized/unsized-inherent-impl-self-type.stderr @@ -16,6 +16,10 @@ LL | struct S5(Y); | ^ - ...if indirection were used here: `Box` | | | this could be changed to `Y: ?Sized`... +help: consider removing the `?Sized` bound to make the type parameter `Sized` + | +LL | impl S5 { + | -- error: aborting due to previous error diff --git a/src/test/ui/unsized/unsized-struct.stderr b/src/test/ui/unsized/unsized-struct.stderr index e38375bff46cf..71693b8130dee 100644 --- a/src/test/ui/unsized/unsized-struct.stderr +++ b/src/test/ui/unsized/unsized-struct.stderr @@ -16,6 +16,10 @@ LL | struct Foo { data: T } | ^ - ...if indirection were used here: `Box` | | | this could be changed to `T: ?Sized`... +help: consider removing the `?Sized` bound to make the type parameter `Sized` + | +LL | fn foo2() { not_sized::>() } + | -- error[E0277]: the size for values of type `T` cannot be known at compilation time --> $DIR/unsized-struct.rs:13:24 @@ -33,6 +37,10 @@ note: required because it appears within the type `Bar` | LL | struct Bar { data: T } | ^^^ +help: consider removing the `?Sized` bound to make the type parameter `Sized` + | +LL | fn bar2() { is_sized::>() } + | -- error: aborting due to 2 previous errors diff --git a/src/test/ui/unsized/unsized-trait-impl-self-type.stderr b/src/test/ui/unsized/unsized-trait-impl-self-type.stderr index aef0d0cbb8395..201dbf85d2042 100644 --- a/src/test/ui/unsized/unsized-trait-impl-self-type.stderr +++ b/src/test/ui/unsized/unsized-trait-impl-self-type.stderr @@ -16,6 +16,10 @@ LL | struct S5(Y); | ^ - ...if indirection were used here: `Box` | | | this could be changed to `Y: ?Sized`... +help: consider removing the `?Sized` bound to make the type parameter `Sized` + | +LL | impl T3 for S5 { + | -- error: aborting due to previous error diff --git a/src/test/ui/unsized/unsized-trait-impl-trait-arg.stderr b/src/test/ui/unsized/unsized-trait-impl-trait-arg.stderr index f48d4ef9f1461..f8f8aa8e3e9ba 100644 --- a/src/test/ui/unsized/unsized-trait-impl-trait-arg.stderr +++ b/src/test/ui/unsized/unsized-trait-impl-trait-arg.stderr @@ -9,6 +9,10 @@ LL | impl T2 for S4 { | | | this type parameter needs to be `std::marker::Sized` | +help: consider removing the `?Sized` bound to make the type parameter `Sized` + | +LL | impl T2 for S4 { + | -- help: consider relaxing the implicit `Sized` restriction | LL | trait T2 { diff --git a/src/test/ui/unsized/unsized3.stderr b/src/test/ui/unsized/unsized3.stderr index bd36008aca044..10ddfe34eace6 100644 --- a/src/test/ui/unsized/unsized3.stderr +++ b/src/test/ui/unsized/unsized3.stderr @@ -9,6 +9,10 @@ LL | f2::(x); LL | fn f2(x: &X) { | - required by this bound in `f2` | +help: consider removing the `?Sized` bound to make the type parameter `Sized` + | +LL | fn f1(x: &X) { + | -- help: consider relaxing the implicit `Sized` restriction | LL | fn f2(x: &X) { @@ -25,6 +29,10 @@ LL | f4::(x); LL | fn f4(x: &X) { | - required by this bound in `f4` | +help: consider removing the `?Sized` bound to make the type parameter `Sized` + | +LL | fn f3(x: &X) { + | -- help: consider relaxing the implicit `Sized` restriction | LL | fn f4(x: &X) { @@ -46,6 +54,10 @@ note: required because it appears within the type `S` | LL | struct S { | ^ +help: consider removing the `?Sized` bound to make the type parameter `Sized` + | +LL | fn f8(x1: &S, x2: &S) { + | -- help: consider relaxing the implicit `Sized` restriction | LL | fn f5(x: &Y) {} @@ -65,6 +77,10 @@ note: required because it appears within the type `S` LL | struct S { | ^ = note: only the last element of a tuple may have a dynamically sized type +help: consider removing the `?Sized` bound to make the type parameter `Sized` + | +LL | fn f9(x1: Box>) { + | -- error[E0277]: the size for values of type `X` cannot be known at compilation time --> $DIR/unsized3.rs:45:9 @@ -81,6 +97,10 @@ LL | struct S { | ^ = note: required because it appears within the type `({integer}, S)` = note: tuples must have a statically known size to be initialized +help: consider removing the `?Sized` bound to make the type parameter `Sized` + | +LL | fn f10(x1: Box>) { + | -- error[E0277]: the size for values of type `X` cannot be known at compilation time --> $DIR/unsized3.rs:45:8 @@ -99,6 +119,10 @@ note: required because it appears within the type `S` LL | struct S { | ^ = note: required because it appears within the type `({integer}, S)` +help: consider removing the `?Sized` bound to make the type parameter `Sized` + | +LL | fn f10(x1: Box>) { + | -- help: consider relaxing the implicit `Sized` restriction | LL | fn f5(x: &Y) {} diff --git a/src/test/ui/unsized/unsized5.stderr b/src/test/ui/unsized/unsized5.stderr index 0bfd4565529aa..6e5b355642932 100644 --- a/src/test/ui/unsized/unsized5.stderr +++ b/src/test/ui/unsized/unsized5.stderr @@ -8,6 +8,10 @@ LL | f1: X, | = note: only the last field of a struct may have a dynamically sized type = help: change the field's type to have a statically known size +help: consider removing the `?Sized` bound to make the type parameter `Sized` + | +LL | struct S1 { + | -- help: borrowed types always have a statically known size | LL | f1: &X, @@ -28,6 +32,10 @@ LL | g: X, | = note: only the last field of a struct may have a dynamically sized type = help: change the field's type to have a statically known size +help: consider removing the `?Sized` bound to make the type parameter `Sized` + | +LL | struct S2 { + | -- help: borrowed types always have a statically known size | LL | g: &X, @@ -83,6 +91,10 @@ LL | V1(X, isize), | = note: no field of an enum variant may have a dynamically sized type = help: change the field's type to have a statically known size +help: consider removing the `?Sized` bound to make the type parameter `Sized` + | +LL | enum E { + | -- help: borrowed types always have a statically known size | LL | V1(&X, isize), @@ -102,6 +114,10 @@ LL | V2{f1: X, f: isize}, | = note: no field of an enum variant may have a dynamically sized type = help: change the field's type to have a statically known size +help: consider removing the `?Sized` bound to make the type parameter `Sized` + | +LL | enum F { + | -- help: borrowed types always have a statically known size | LL | V2{f1: &X, f: isize}, diff --git a/src/test/ui/unsized/unsized6.stderr b/src/test/ui/unsized/unsized6.stderr index 8e5734dffb145..5eff89d971fbb 100644 --- a/src/test/ui/unsized/unsized6.stderr +++ b/src/test/ui/unsized/unsized6.stderr @@ -9,6 +9,10 @@ LL | let y: Y; | = note: all local variables must have a statically known size = help: unsized locals are gated as an unstable feature +help: consider removing the `?Sized` bound to make the type parameter `Sized` + | +LL | fn f1(x: &X) { + | -- error[E0277]: the size for values of type `X` cannot be known at compilation time --> $DIR/unsized6.rs:7:12 @@ -20,6 +24,10 @@ LL | let _: (isize, (X, isize)); | ^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time | = note: only the last element of a tuple may have a dynamically sized type +help: consider removing the `?Sized` bound to make the type parameter `Sized` + | +LL | fn f1(x: &X) { + | -- error[E0277]: the size for values of type `Z` cannot be known at compilation time --> $DIR/unsized6.rs:11:12 @@ -31,6 +39,10 @@ LL | let y: (isize, (Z, usize)); | ^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time | = note: only the last element of a tuple may have a dynamically sized type +help: consider removing the `?Sized` bound to make the type parameter `Sized` + | +LL | fn f1(x: &X) { + | -- error[E0277]: the size for values of type `X` cannot be known at compilation time --> $DIR/unsized6.rs:15:9 @@ -42,6 +54,10 @@ LL | let y: X; | = note: all local variables must have a statically known size = help: unsized locals are gated as an unstable feature +help: consider removing the `?Sized` bound to make the type parameter `Sized` + | +LL | fn f2(x: &X) { + | -- error[E0277]: the size for values of type `Y` cannot be known at compilation time --> $DIR/unsized6.rs:17:12 @@ -53,6 +69,10 @@ LL | let y: (isize, (Y, isize)); | ^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time | = note: only the last element of a tuple may have a dynamically sized type +help: consider removing the `?Sized` bound to make the type parameter `Sized` + | +LL | fn f2(x: &X) { + | -- error[E0277]: the size for values of type `X` cannot be known at compilation time --> $DIR/unsized6.rs:22:9 @@ -64,6 +84,10 @@ LL | let y: X = *x1; | = note: all local variables must have a statically known size = help: unsized locals are gated as an unstable feature +help: consider removing the `?Sized` bound to make the type parameter `Sized` + | +LL | fn f3(x1: Box, x2: Box, x3: Box) { + | -- error[E0277]: the size for values of type `X` cannot be known at compilation time --> $DIR/unsized6.rs:24:9 @@ -76,6 +100,10 @@ LL | let y = *x2; | = note: all local variables must have a statically known size = help: unsized locals are gated as an unstable feature +help: consider removing the `?Sized` bound to make the type parameter `Sized` + | +LL | fn f3(x1: Box, x2: Box, x3: Box) { + | -- error[E0277]: the size for values of type `X` cannot be known at compilation time --> $DIR/unsized6.rs:26:10 @@ -88,6 +116,10 @@ LL | let (y, z) = (*x3, 4); | = note: all local variables must have a statically known size = help: unsized locals are gated as an unstable feature +help: consider removing the `?Sized` bound to make the type parameter `Sized` + | +LL | fn f3(x1: Box, x2: Box, x3: Box) { + | -- error[E0277]: the size for values of type `X` cannot be known at compilation time --> $DIR/unsized6.rs:30:9 @@ -99,6 +131,10 @@ LL | let y: X = *x1; | = note: all local variables must have a statically known size = help: unsized locals are gated as an unstable feature +help: consider removing the `?Sized` bound to make the type parameter `Sized` + | +LL | fn f4(x1: Box, x2: Box, x3: Box) { + | -- error[E0277]: the size for values of type `X` cannot be known at compilation time --> $DIR/unsized6.rs:32:9 @@ -111,6 +147,10 @@ LL | let y = *x2; | = note: all local variables must have a statically known size = help: unsized locals are gated as an unstable feature +help: consider removing the `?Sized` bound to make the type parameter `Sized` + | +LL | fn f4(x1: Box, x2: Box, x3: Box) { + | -- error[E0277]: the size for values of type `X` cannot be known at compilation time --> $DIR/unsized6.rs:34:10 @@ -123,6 +163,10 @@ LL | let (y, z) = (*x3, 4); | = note: all local variables must have a statically known size = help: unsized locals are gated as an unstable feature +help: consider removing the `?Sized` bound to make the type parameter `Sized` + | +LL | fn f4(x1: Box, x2: Box, x3: Box) { + | -- error[E0277]: the size for values of type `X` cannot be known at compilation time --> $DIR/unsized6.rs:38:18 @@ -133,6 +177,10 @@ LL | fn g1(x: X) {} | this type parameter needs to be `std::marker::Sized` | = help: unsized fn params are gated as an unstable feature +help: consider removing the `?Sized` bound to make the type parameter `Sized` + | +LL | fn g1(x: X) {} + | -- help: function arguments must have a statically known size, borrowed types always have a known size | LL | fn g1(x: &X) {} @@ -147,6 +195,10 @@ LL | fn g2(x: X) {} | this type parameter needs to be `std::marker::Sized` | = help: unsized fn params are gated as an unstable feature +help: consider removing the `?Sized` bound to make the type parameter `Sized` + | +LL | fn g2(x: X) {} + | -- help: function arguments must have a statically known size, borrowed types always have a known size | LL | fn g2(x: &X) {} diff --git a/src/test/ui/unsized/unsized7.stderr b/src/test/ui/unsized/unsized7.stderr index 7dbddd4ed2443..e0d95e212964d 100644 --- a/src/test/ui/unsized/unsized7.stderr +++ b/src/test/ui/unsized/unsized7.stderr @@ -9,6 +9,10 @@ LL | impl T1 for S3 { | | | this type parameter needs to be `std::marker::Sized` | +help: consider removing the `?Sized` bound to make the type parameter `Sized` + | +LL | impl T1 for S3 { + | -- help: consider relaxing the implicit `Sized` restriction | LL | trait T1 {