From ee7e717322f83d4b055e15b9948c07dd59118a5c Mon Sep 17 00:00:00 2001 From: Lukas Markeffsky <@> Date: Wed, 14 Jun 2023 08:03:35 +0000 Subject: [PATCH] tweak suggestion for argument-position `impl ?Sized` --- compiler/rustc_middle/src/ty/diagnostics.rs | 41 +++++++++++++++------ tests/ui/trait-bounds/apit-unsized.rs | 4 ++ tests/ui/trait-bounds/apit-unsized.stderr | 41 +++++++++++++++++++++ 3 files changed, 74 insertions(+), 12 deletions(-) create mode 100644 tests/ui/trait-bounds/apit-unsized.rs create mode 100644 tests/ui/trait-bounds/apit-unsized.stderr diff --git a/compiler/rustc_middle/src/ty/diagnostics.rs b/compiler/rustc_middle/src/ty/diagnostics.rs index 9c948dba1e4..1c80692c306 100644 --- a/compiler/rustc_middle/src/ty/diagnostics.rs +++ b/compiler/rustc_middle/src/ty/diagnostics.rs @@ -14,8 +14,8 @@ use rustc_errors::{Applicability, Diagnostic, DiagnosticArgValue, IntoDiagnostic use rustc_hir as hir; use rustc_hir::def::DefKind; use rustc_hir::def_id::DefId; -use rustc_hir::WherePredicate; -use rustc_span::Span; +use rustc_hir::{PredicateOrigin, WherePredicate}; +use rustc_span::{BytePos, Span}; use rustc_type_ir::sty::TyKind::*; impl<'tcx> IntoDiagnosticArg for Ty<'tcx> { @@ -156,10 +156,11 @@ enum SuggestChangingConstraintsMessage<'a> { RestrictBoundFurther, RestrictType { ty: &'a str }, RestrictTypeFurther { ty: &'a str }, - RemovingQSized, + RemoveMaybeUnsized, + ReplaceMaybeUnsizedWithSized, } -fn suggest_removing_unsized_bound( +fn suggest_changing_unsized_bound( generics: &hir::Generics<'_>, suggestions: &mut Vec<(Span, String, SuggestChangingConstraintsMessage<'_>)>, param: &hir::GenericParam<'_>, @@ -183,12 +184,25 @@ fn suggest_removing_unsized_bound( if poly.trait_ref.trait_def_id() != def_id { continue; } - let sp = generics.span_for_bound_removal(where_pos, pos); - suggestions.push(( - sp, - String::new(), - SuggestChangingConstraintsMessage::RemovingQSized, - )); + if predicate.origin == PredicateOrigin::ImplTrait && predicate.bounds.len() == 1 { + // For `impl ?Sized` with no other bounds, suggest `impl Sized` instead. + let bound_span = bound.span(); + if bound_span.can_be_used_for_suggestions() { + let question_span = bound_span.with_hi(bound_span.lo() + BytePos(1)); + suggestions.push(( + question_span, + String::new(), + SuggestChangingConstraintsMessage::ReplaceMaybeUnsizedWithSized, + )); + } + } else { + let sp = generics.span_for_bound_removal(where_pos, pos); + suggestions.push(( + sp, + String::new(), + SuggestChangingConstraintsMessage::RemoveMaybeUnsized, + )); + } } } } @@ -245,7 +259,7 @@ pub fn suggest_constraining_type_params<'a>( param.span, format!("this type parameter needs to be `{}`", constraint), ); - suggest_removing_unsized_bound(generics, &mut suggestions, param, def_id); + suggest_changing_unsized_bound(generics, &mut suggestions, param, def_id); } } @@ -395,9 +409,12 @@ pub fn suggest_constraining_type_params<'a>( SuggestChangingConstraintsMessage::RestrictTypeFurther { ty } => { Cow::from(format!("consider further restricting type parameter `{}`", ty)) } - SuggestChangingConstraintsMessage::RemovingQSized => { + SuggestChangingConstraintsMessage::RemoveMaybeUnsized => { Cow::from("consider removing the `?Sized` bound to make the type parameter `Sized`") } + SuggestChangingConstraintsMessage::ReplaceMaybeUnsizedWithSized => { + Cow::from("consider replacing `?Sized` with `Sized`") + } }; err.span_suggestion_verbose(span, msg, suggestion, applicability); diff --git a/tests/ui/trait-bounds/apit-unsized.rs b/tests/ui/trait-bounds/apit-unsized.rs new file mode 100644 index 00000000000..469d6a6345e --- /dev/null +++ b/tests/ui/trait-bounds/apit-unsized.rs @@ -0,0 +1,4 @@ +fn foo(_: impl Iterator + ?Sized) {} //~ ERROR [E0277] +fn bar(_: impl ?Sized) {} //~ ERROR [E0277] + +fn main() {} diff --git a/tests/ui/trait-bounds/apit-unsized.stderr b/tests/ui/trait-bounds/apit-unsized.stderr new file mode 100644 index 00000000000..7a4a2274d44 --- /dev/null +++ b/tests/ui/trait-bounds/apit-unsized.stderr @@ -0,0 +1,41 @@ +error[E0277]: the size for values of type `impl Iterator + ?Sized` cannot be known at compilation time + --> $DIR/apit-unsized.rs:1:8 + | +LL | fn foo(_: impl Iterator + ?Sized) {} + | ^ ---------------------------------- this type parameter needs to be `std::marker::Sized` + | | + | doesn't have a size known at compile-time + | + = help: unsized fn params are gated as an unstable feature +help: consider removing the `?Sized` bound to make the type parameter `Sized` + | +LL - fn foo(_: impl Iterator + ?Sized) {} +LL + fn foo(_: impl Iterator) {} + | +help: function arguments must have a statically known size, borrowed types always have a known size + | +LL | fn foo(_: &impl Iterator + ?Sized) {} + | + + +error[E0277]: the size for values of type `impl ?Sized` cannot be known at compilation time + --> $DIR/apit-unsized.rs:2:8 + | +LL | fn bar(_: impl ?Sized) {} + | ^ ----------- this type parameter needs to be `std::marker::Sized` + | | + | doesn't have a size known at compile-time + | + = help: unsized fn params are gated as an unstable feature +help: consider replacing `?Sized` with `Sized` + | +LL - fn bar(_: impl ?Sized) {} +LL + fn bar(_: impl Sized) {} + | +help: function arguments must have a statically known size, borrowed types always have a known size + | +LL | fn bar(_: &impl ?Sized) {} + | + + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`.