summaryrefslogtreecommitdiffstats
path: root/compiler/rustc_middle/src/ty/diagnostics.rs
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/rustc_middle/src/ty/diagnostics.rs')
-rw-r--r--compiler/rustc_middle/src/ty/diagnostics.rs65
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.