diff options
Diffstat (limited to 'compiler/rustc_middle/src/ty/diagnostics.rs')
-rw-r--r-- | compiler/rustc_middle/src/ty/diagnostics.rs | 65 |
1 files changed, 38 insertions, 27 deletions
diff --git a/compiler/rustc_middle/src/ty/diagnostics.rs b/compiler/rustc_middle/src/ty/diagnostics.rs index 6a29063b8..a0b17c374 100644 --- a/compiler/rustc_middle/src/ty/diagnostics.rs +++ b/compiler/rustc_middle/src/ty/diagnostics.rs @@ -1,5 +1,6 @@ //! Diagnostics related methods for `Ty`. +use std::borrow::Cow; use std::ops::ControlFlow; use crate::ty::{ @@ -13,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> { @@ -155,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<'_>, @@ -182,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, + )); + } } } } @@ -236,15 +251,12 @@ pub fn suggest_constraining_type_params<'a>( { let mut sized_constraints = - constraints.drain_filter(|(_, def_id)| *def_id == tcx.lang_items().sized_trait()); - if let Some((constraint, def_id)) = sized_constraints.next() { + constraints.extract_if(|(_, def_id)| *def_id == tcx.lang_items().sized_trait()); + if let Some((_, def_id)) = sized_constraints.next() { applicability = Applicability::MaybeIncorrect; - err.span_label( - param.span, - format!("this type parameter needs to be `{}`", constraint), - ); - suggest_removing_unsized_bound(generics, &mut suggestions, param, def_id); + err.span_label(param.span, "this type parameter needs to be `Sized`"); + suggest_changing_unsized_bound(generics, &mut suggestions, param, def_id); } } @@ -384,22 +396,21 @@ pub fn suggest_constraining_type_params<'a>( if suggestions.len() == 1 { let (span, suggestion, msg) = suggestions.pop().unwrap(); - - let s; let msg = match msg { SuggestChangingConstraintsMessage::RestrictBoundFurther => { - "consider further restricting this bound" + Cow::from("consider further restricting this bound") } SuggestChangingConstraintsMessage::RestrictType { ty } => { - s = format!("consider restricting type parameter `{}`", ty); - &s + Cow::from(format!("consider restricting type parameter `{}`", ty)) } SuggestChangingConstraintsMessage::RestrictTypeFurther { ty } => { - s = format!("consider further restricting type parameter `{}`", ty); - &s + Cow::from(format!("consider further restricting type parameter `{}`", ty)) + } + SuggestChangingConstraintsMessage::RemoveMaybeUnsized => { + Cow::from("consider removing the `?Sized` bound to make the type parameter `Sized`") } - SuggestChangingConstraintsMessage::RemovingQSized => { - "consider removing the `?Sized` bound to make the type parameter `Sized`" + SuggestChangingConstraintsMessage::ReplaceMaybeUnsizedWithSized => { + Cow::from("consider replacing `?Sized` with `Sized`") } }; @@ -548,7 +559,7 @@ impl<'tcx> FallibleTypeFolder<TyCtxt<'tcx>> for MakeSuggestableFolder<'tcx> { Infer(InferTy::TyVar(_)) if self.infer_suggestable => t, FnDef(def_id, substs) => { - self.tcx.mk_fn_ptr(self.tcx.fn_sig(def_id).subst(self.tcx, substs)) + Ty::new_fn_ptr(self.tcx, self.tcx.fn_sig(def_id).subst(self.tcx, substs)) } // FIXME(compiler-errors): We could replace these with infer, I guess. |