Skip to content

Commit 02ccf86

Browse files
committed
review comments
1 parent 02711fd commit 02ccf86

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
@@ -387,7 +387,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
387387
// which is somewhat confusing.
388388
self.suggest_restricting_param_bound(
389389
&mut err,
390-
&trait_ref,
390+
trait_ref,
391391
obligation.cause.body_id,
392392
);
393393
} else {

src/librustc_trait_selection/traits/error_reporting/suggestions.rs

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

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

212-
// There might be more than one `impl Trait`.
213-
ty_spans.push(input.span);
214-
}
208+
// There might be more than one `impl Trait`.
209+
ty_spans.push(input.span);
215210
}
216211
}
212+
}
217213

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

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

0 commit comments

Comments
 (0)