Make ProjectionTy::trait_ref truncate substs again

Also make sure that type arguments of associated types are printed in
some error messages.
This commit is contained in:
Matthew Jasper 2021-02-12 22:44:43 +00:00
parent 79f6f11816
commit dfee89f755
12 changed files with 216 additions and 49 deletions

View file

@ -1,5 +1,6 @@
use crate::traits::{ObligationCause, ObligationCauseCode};
use crate::ty::diagnostics::suggest_constraining_type_param;
use crate::ty::print::{FmtPrinter, Printer};
use crate::ty::{self, BoundRegionKind, Region, Ty, TyCtxt};
use rustc_errors::Applicability::{MachineApplicable, MaybeIncorrect};
use rustc_errors::{pluralize, DiagnosticBuilder};
@ -400,14 +401,22 @@ impl<'tcx> TyCtxt<'tcx> {
{
// Synthesize the associated type restriction `Add<Output = Expected>`.
// FIXME: extract this logic for use in other diagnostics.
let trait_ref = proj.trait_ref(self);
let (trait_ref, assoc_substs) = proj.trait_ref_and_own_substs(self);
let path =
self.def_path_str_with_substs(trait_ref.def_id, trait_ref.substs);
let item_name = self.item_name(proj.item_def_id);
let item_args = self.format_generic_args(assoc_substs);
let path = if path.ends_with('>') {
format!("{}, {} = {}>", &path[..path.len() - 1], item_name, p)
format!(
"{}, {}{} = {}>",
&path[..path.len() - 1],
item_name,
item_args,
p
)
} else {
format!("{}<{} = {}>", path, item_name, p)
format!("{}<{}{} = {}>", path, item_name, item_args, p)
};
note = !suggest_constraining_type_param(
self,
@ -556,7 +565,7 @@ impl<T> Trait<T> for X {
ty: Ty<'tcx>,
) -> bool {
let assoc = self.associated_item(proj_ty.item_def_id);
let trait_ref = proj_ty.trait_ref(self);
let (trait_ref, assoc_substs) = proj_ty.trait_ref_and_own_substs(self);
if let Some(item) = self.hir().get_if_local(body_owner_def_id) {
if let Some(hir_generics) = item.generics() {
// Get the `DefId` for the type parameter corresponding to `A` in `<A as T>::Foo`.
@ -590,6 +599,7 @@ impl<T> Trait<T> for X {
&trait_ref,
pred.bounds,
&assoc,
assoc_substs,
ty,
msg,
) {
@ -607,6 +617,7 @@ impl<T> Trait<T> for X {
&trait_ref,
param.bounds,
&assoc,
assoc_substs,
ty,
msg,
);
@ -692,6 +703,7 @@ impl<T> Trait<T> for X {
db,
self.def_span(def_id),
&assoc,
proj_ty.trait_ref_and_own_substs(self).1,
values.found,
&msg,
) {
@ -856,6 +868,7 @@ fn foo(&self) -> Self::T { String::new() }
trait_ref: &ty::TraitRef<'tcx>,
bounds: hir::GenericBounds<'_>,
assoc: &ty::AssocItem,
assoc_substs: &[ty::GenericArg<'tcx>],
ty: Ty<'tcx>,
msg: &str,
) -> bool {
@ -865,7 +878,12 @@ fn foo(&self) -> Self::T { String::new() }
// Relate the type param against `T` in `<A as T>::Foo`.
ptr.trait_ref.trait_def_id() == Some(trait_ref.def_id)
&& self.constrain_associated_type_structured_suggestion(
db, ptr.span, assoc, ty, msg,
db,
ptr.span,
assoc,
assoc_substs,
ty,
msg,
)
}
_ => false,
@ -879,6 +897,7 @@ fn foo(&self) -> Self::T { String::new() }
db: &mut DiagnosticBuilder<'_>,
span: Span,
assoc: &ty::AssocItem,
assoc_substs: &[ty::GenericArg<'tcx>],
ty: Ty<'tcx>,
msg: &str,
) -> bool {
@ -890,11 +909,20 @@ fn foo(&self) -> Self::T { String::new() }
let span = Span::new(pos, pos, span.ctxt());
(span, format!(", {} = {}", assoc.ident, ty))
} else {
(span.shrink_to_hi(), format!("<{} = {}>", assoc.ident, ty))
let item_args = self.format_generic_args(assoc_substs);
(span.shrink_to_hi(), format!("<{}{} = {}>", assoc.ident, item_args, ty))
};
db.span_suggestion_verbose(span, msg, sugg, MaybeIncorrect);
return true;
}
false
}
fn format_generic_args(self, args: &[ty::GenericArg<'tcx>]) -> String {
let mut item_args = String::new();
FmtPrinter::new(self, &mut item_args, hir::def::Namespace::TypeNS)
.path_generic_args(Ok, args)
.expect("could not write to `String`.");
item_args
}
}