Skip to content

Commit 794b644

Browse files
committed
review comments
1 parent 2c998aa commit 794b644

File tree

3 files changed

+86
-92
lines changed

3 files changed

+86
-92
lines changed

src/librustc_trait_selection/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#![feature(crate_visibility_modifier)]
1818
#![feature(or_patterns)]
1919
#![feature(str_strip)]
20+
#![feature(option_zip)]
2021
#![recursion_limit = "512"] // For rustdoc
2122

2223
#[macro_use]

src/librustc_trait_selection/traits/error_reporting/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -388,7 +388,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
388388
// which is somewhat confusing.
389389
self.suggest_restricting_param_bound(
390390
&mut err,
391-
&trait_ref,
391+
trait_ref,
392392
obligation.cause.body_id,
393393
);
394394
} else {

src/librustc_trait_selection/traits/error_reporting/suggestions.rs

Lines changed: 84 additions & 91 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ pub trait InferCtxtExt<'tcx> {
2727
fn suggest_restricting_param_bound(
2828
&self,
2929
err: &mut DiagnosticBuilder<'_>,
30-
trait_ref: &ty::PolyTraitRef<'_>,
30+
trait_ref: ty::PolyTraitRef<'_>,
3131
body_id: hir::HirId,
3232
);
3333

@@ -168,111 +168,104 @@ fn suggest_restriction(
168168
err: &mut DiagnosticBuilder<'_>,
169169
fn_sig: Option<&hir::FnSig<'_>>,
170170
projection: Option<&ty::ProjectionTy<'_>>,
171-
trait_ref: &ty::PolyTraitRef<'_>,
171+
trait_ref: ty::PolyTraitRef<'_>,
172172
) {
173173
let span = generics.where_clause.span_for_predicates_or_empty_place();
174-
if !span.from_expansion() && span.desugaring_kind().is_none() {
175-
// Given `fn foo(t: impl Trait)` where `Trait` requires assoc type `A`...
176-
if let Some((name, fn_sig)) = fn_sig.and_then(|sig| {
177-
projection.and_then(|p| {
178-
// Shenanigans to get the `Trait` from the `impl Trait`.
179-
match p.self_ty().kind {
180-
ty::Param(param) => {
181-
// `fn foo(t: impl Trait)`
182-
// ^^^^^ get this string
183-
param
184-
.name
185-
.as_str()
186-
.strip_prefix("impl")
187-
.map(|s| (s.trim_start().to_string(), sig))
188-
}
189-
_ => None,
190-
}
191-
})
192-
}) {
193-
// We know we have an `impl Trait` that doesn't satisfy a required projection.
194-
195-
// Find all of the ocurrences of `impl Trait` for `Trait` in the function arguments'
196-
// types. There should be at least one, but there might be *more* than one. In that
197-
// case we could just ignore it and try to identify which one needs the restriction,
198-
// but instead we choose to suggest replacing all instances of `impl Trait` with `T`
199-
// where `T: Trait`.
200-
let mut ty_spans = vec![];
201-
let impl_name = format!("impl {}", name);
202-
for input in fn_sig.decl.inputs {
203-
if let hir::TyKind::Path(hir::QPath::Resolved(
204-
None,
205-
hir::Path { segments: [segment], .. },
206-
)) = input.kind
207-
{
208-
if segment.ident.as_str() == impl_name.as_str() {
209-
// `fn foo(t: impl Trait)`
210-
// ^^^^^^^^^^ get this to suggest
211-
// `T` instead
174+
if span.from_expansion() || span.desugaring_kind().is_some() {
175+
return;
176+
}
177+
// Given `fn foo(t: impl Trait)` where `Trait` requires assoc type `A`...
178+
if let Some((name, fn_sig)) =
179+
fn_sig.zip(projection).and_then(|(sig, p)| match p.self_ty().kind {
180+
// Shenanigans to get the `Trait` from the `impl Trait`.
181+
ty::Param(param) => {
182+
// `fn foo(t: impl Trait)`
183+
// ^^^^^ get this string
184+
param.name.as_str().strip_prefix("impl").map(|s| (s.trim_start().to_string(), sig))
185+
}
186+
_ => None,
187+
})
188+
{
189+
// We know we have an `impl Trait` that doesn't satisfy a required projection.
190+
191+
// Find all of the ocurrences of `impl Trait` for `Trait` in the function arguments'
192+
// types. There should be at least one, but there might be *more* than one. In that
193+
// case we could just ignore it and try to identify which one needs the restriction,
194+
// but instead we choose to suggest replacing all instances of `impl Trait` with `T`
195+
// where `T: Trait`.
196+
let mut ty_spans = vec![];
197+
let impl_name = format!("impl {}", name);
198+
for input in fn_sig.decl.inputs {
199+
if let hir::TyKind::Path(hir::QPath::Resolved(
200+
None,
201+
hir::Path { segments: [segment], .. },
202+
)) = input.kind
203+
{
204+
if segment.ident.as_str() == impl_name.as_str() {
205+
// `fn foo(t: impl Trait)`
206+
// ^^^^^^^^^^ get this to suggest
207+
// `T` instead
212208

213-
// There might be more than one `impl Trait`.
214-
ty_spans.push(input.span);
215-
}
209+
// There might be more than one `impl Trait`.
210+
ty_spans.push(input.span);
216211
}
217212
}
213+
}
218214

219-
// The type param `T: Trait` we will suggest to introduce.
220-
let type_param = format!("{}: {}", "T", name);
221-
222-
// FIXME: modify the `trait_ref` instead of string shenanigans.
223-
// Turn `<impl Trait as Foo>::Bar: Qux` into `<T as Foo>::Bar: Qux`.
224-
let pred = trait_ref.without_const().to_predicate().to_string();
225-
let pred = pred.replace(&impl_name, "T");
226-
let mut sugg = vec![
227-
match generics
228-
.params
229-
.iter()
230-
.filter(|p| match p.kind {
231-
hir::GenericParamKind::Type {
232-
synthetic: Some(hir::SyntheticTyParamKind::ImplTrait),
233-
..
234-
} => false,
235-
_ => true,
236-
})
237-
.last()
238-
{
239-
// `fn foo(t: impl Trait)`
240-
// ^ suggest `<T: Trait>` here
241-
None => (generics.span, format!("<{}>", type_param)),
242-
// `fn foo<A>(t: impl Trait)`
243-
// ^^^ suggest `<A, T: Trait>` here
244-
Some(param) => (param.span.shrink_to_hi(), format!(", {}", type_param)),
245-
},
215+
// The type param `T: Trait` we will suggest to introduce.
216+
let type_param = format!("{}: {}", "T", name);
217+
218+
// FIXME: modify the `trait_ref` instead of string shenanigans.
219+
// Turn `<impl Trait as Foo>::Bar: Qux` into `<T as Foo>::Bar: Qux`.
220+
let pred = trait_ref.without_const().to_predicate().to_string();
221+
let pred = pred.replace(&impl_name, "T");
222+
let mut sugg = vec![
223+
match generics
224+
.params
225+
.iter()
226+
.filter(|p| match p.kind {
227+
hir::GenericParamKind::Type {
228+
synthetic: Some(hir::SyntheticTyParamKind::ImplTrait),
229+
..
230+
} => false,
231+
_ => true,
232+
})
233+
.last()
234+
{
246235
// `fn foo(t: impl Trait)`
247-
// ^ suggest `where <T as Trait>::A: Bound`
248-
predicate_constraint(generics, pred),
249-
];
250-
sugg.extend(ty_spans.into_iter().map(|s| (s, "T".to_string())));
251-
252-
// Suggest `fn foo<T: Trait>(t: T) where <T as Trait>::A: Bound`.
253-
err.multipart_suggestion(
254-
"introduce a type parameter with a trait bound instead of using \
236+
// ^ suggest `<T: Trait>` here
237+
None => (generics.span, format!("<{}>", type_param)),
238+
// `fn foo<A>(t: impl Trait)`
239+
// ^^^ suggest `<A, T: Trait>` here
240+
Some(param) => (param.span.shrink_to_hi(), format!(", {}", type_param)),
241+
},
242+
// `fn foo(t: impl Trait)`
243+
// ^ suggest `where <T as Trait>::A: Bound`
244+
predicate_constraint(generics, pred),
245+
];
246+
sugg.extend(ty_spans.into_iter().map(|s| (s, "T".to_string())));
247+
248+
// Suggest `fn foo<T: Trait>(t: T) where <T as Trait>::A: Bound`.
249+
err.multipart_suggestion(
250+
"introduce a type parameter with a trait bound instead of using \
255251
`impl Trait`",
256-
sugg,
257-
Applicability::MaybeIncorrect,
258-
);
259-
} else {
260-
// Trivial case: `T` needs an extra bound: `T: Bound`.
261-
let (sp, s) = predicate_constraint(
262-
generics,
263-
trait_ref.without_const().to_predicate().to_string(),
264-
);
265-
let appl = Applicability::MachineApplicable;
266-
err.span_suggestion(sp, &format!("consider further restricting {}", msg), s, appl);
267-
}
252+
sugg,
253+
Applicability::MaybeIncorrect,
254+
);
255+
} else {
256+
// Trivial case: `T` needs an extra bound: `T: Bound`.
257+
let (sp, s) =
258+
predicate_constraint(generics, trait_ref.without_const().to_predicate().to_string());
259+
let appl = Applicability::MachineApplicable;
260+
err.span_suggestion(sp, &format!("consider further restricting {}", msg), s, appl);
268261
}
269262
}
270263

271264
impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
272265
fn suggest_restricting_param_bound(
273266
&self,
274267
mut err: &mut DiagnosticBuilder<'_>,
275-
trait_ref: &ty::PolyTraitRef<'_>,
268+
trait_ref: ty::PolyTraitRef<'_>,
276269
body_id: hir::HirId,
277270
) {
278271
let self_ty = trait_ref.self_ty();

0 commit comments

Comments
 (0)