Skip to content

Commit 3c8b108

Browse files
committed
Inside eager ty aliases on unresolved assoc tys suggest fully qualifying instead of restricting their self ty
1 parent 898448c commit 3c8b108

File tree

8 files changed

+138
-24
lines changed

8 files changed

+138
-24
lines changed

compiler/rustc_hir_analysis/messages.ftl

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,13 @@ hir_analysis_assoc_item_not_found_found_in_other_trait_label = there is {$identi
2020
} associated {$assoc_kind} `{$suggested_name}` in the trait `{$trait_name}`
2121
hir_analysis_assoc_item_not_found_label = associated {$assoc_kind} `{$assoc_name}` not found
2222
hir_analysis_assoc_item_not_found_other_sugg = `{$qself}` has the following associated {$assoc_kind}
23+
hir_analysis_assoc_item_not_found_similar_in_other_trait_qpath_sugg =
24+
consider fully qualifying{$identically_named ->
25+
[true] {""}
26+
*[false] {" "}and renaming
27+
} the associated {$assoc_kind}
2328
hir_analysis_assoc_item_not_found_similar_in_other_trait_sugg = change the associated {$assoc_kind} name to use `{$suggested_name}` from `{$trait_name}`
24-
hir_analysis_assoc_item_not_found_similar_in_other_trait_with_bound_sugg = and also change the associated {$assoc_kind} name
29+
hir_analysis_assoc_item_not_found_similar_in_other_trait_with_bound_sugg = ...and changing the associated {$assoc_kind} name
2530
hir_analysis_assoc_item_not_found_similar_sugg = there is an associated {$assoc_kind} with a similar name
2631
2732
hir_analysis_assoc_kind_mismatch = expected {$expected}, found {$got}

compiler/rustc_hir_analysis/src/errors.rs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,22 @@ pub enum AssocItemNotFoundSugg<'a> {
126126
assoc_kind: &'static str,
127127
suggested_name: Symbol,
128128
},
129+
#[multipart_suggestion(
130+
hir_analysis_assoc_item_not_found_similar_in_other_trait_qpath_sugg,
131+
style = "verbose",
132+
applicability = "maybe-incorrect"
133+
)]
134+
SimilarInOtherTraitQPath {
135+
#[suggestion_part(code = "<")]
136+
lo: Span,
137+
#[suggestion_part(code = " as {trait_}>")]
138+
mi: Span,
139+
#[suggestion_part(code = "{suggested_name}")]
140+
hi: Option<Span>,
141+
trait_: &'a str,
142+
suggested_name: Symbol,
143+
identically_named: bool,
144+
},
129145
#[suggestion(
130146
hir_analysis_assoc_item_not_found_other_sugg,
131147
code = "{suggested_name}",

compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs

Lines changed: 36 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -219,7 +219,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
219219
suggested_name,
220220
identically_named: suggested_name == assoc_name.name,
221221
});
222-
if let AssocItemQSelf::TyParam(ty_param_def_id) = qself
222+
if let AssocItemQSelf::TyParam(ty_param_def_id, ty_param_span) = qself
223223
// Not using `self.item_def_id()` here as that would yield the opaque type itself if we're
224224
// inside an opaque type while we're interested in the overarching type alias (TAIT).
225225
// FIXME: However, for trait aliases, this incorrectly returns the enclosing module...
@@ -251,27 +251,44 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
251251
return self.dcx().emit_err(err);
252252
}
253253

254-
let mut err = self.dcx().create_err(err);
255-
if suggest_constraining_type_param(
256-
tcx,
257-
generics,
258-
&mut err,
259-
&qself_str,
260-
&trait_name,
261-
None,
262-
None,
263-
) && suggested_name != assoc_name.name
254+
let identically_named = suggested_name == assoc_name.name;
255+
256+
if let DefKind::TyAlias = tcx.def_kind(item_def_id)
257+
&& !tcx.type_alias_is_lazy(item_def_id)
264258
{
265-
// We suggested constraining a type parameter, but the associated item on it
266-
// was also not an exact match, so we also suggest changing it.
267-
err.span_suggestion_verbose(
268-
assoc_name.span,
269-
fluent::hir_analysis_assoc_item_not_found_similar_in_other_trait_with_bound_sugg,
259+
err.sugg = Some(errors::AssocItemNotFoundSugg::SimilarInOtherTraitQPath {
260+
lo: ty_param_span.shrink_to_lo(),
261+
mi: ty_param_span.shrink_to_hi(),
262+
hi: (!identically_named).then_some(assoc_name.span),
263+
// FIXME(fmease): Use a full trait ref here (with placeholders).
264+
trait_: &trait_name,
265+
identically_named,
270266
suggested_name,
271-
Applicability::MaybeIncorrect,
272-
);
267+
});
268+
} else {
269+
let mut err = self.dcx().create_err(err);
270+
if suggest_constraining_type_param(
271+
tcx,
272+
generics,
273+
&mut err,
274+
&qself_str,
275+
// FIXME(fmease): Use a full trait ref here (with placeholders).
276+
&trait_name,
277+
None,
278+
None,
279+
) && !identically_named
280+
{
281+
// We suggested constraining a type parameter, but the associated item on it
282+
// was also not an exact match, so we also suggest changing it.
283+
err.span_suggestion_verbose(
284+
assoc_name.span,
285+
fluent::hir_analysis_assoc_item_not_found_similar_in_other_trait_with_bound_sugg,
286+
suggested_name,
287+
Applicability::MaybeIncorrect,
288+
);
289+
}
290+
return err.emit();
273291
}
274-
return err.emit();
275292
}
276293
return self.dcx().emit_err(err);
277294
}

compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -197,15 +197,15 @@ pub trait HirTyLowerer<'tcx> {
197197
/// For diagnostic purposes only.
198198
enum AssocItemQSelf {
199199
Trait(DefId),
200-
TyParam(LocalDefId),
200+
TyParam(LocalDefId, Span),
201201
SelfTyAlias,
202202
}
203203

204204
impl AssocItemQSelf {
205205
fn to_string(&self, tcx: TyCtxt<'_>) -> String {
206206
match *self {
207207
Self::Trait(def_id) => tcx.def_path_str(def_id),
208-
Self::TyParam(def_id) => tcx.hir().ty_param_name(def_id).to_string(),
208+
Self::TyParam(def_id, _) => tcx.hir().ty_param_name(def_id).to_string(),
209209
Self::SelfTyAlias => kw::SelfUpper.to_string(),
210210
}
211211
}
@@ -820,6 +820,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
820820
fn probe_single_ty_param_bound_for_assoc_ty(
821821
&self,
822822
ty_param_def_id: LocalDefId,
823+
ty_param_span: Span,
823824
assoc_name: Ident,
824825
span: Span,
825826
) -> Result<ty::PolyTraitRef<'tcx>, ErrorGuaranteed> {
@@ -836,7 +837,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
836837
.filter_map(|(p, _)| Some(p.as_trait_clause()?.map_bound(|t| t.trait_ref)));
837838
traits::transitive_bounds_that_define_assoc_item(tcx, trait_refs, assoc_name)
838839
},
839-
AssocItemQSelf::TyParam(ty_param_def_id),
840+
AssocItemQSelf::TyParam(ty_param_def_id, ty_param_span),
840841
ty::AssocKind::Type,
841842
assoc_name,
842843
span,
@@ -1080,6 +1081,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
10801081
Res::SelfTyParam { trait_: param_did } | Res::Def(DefKind::TyParam, param_did),
10811082
) => self.probe_single_ty_param_bound_for_assoc_ty(
10821083
param_did.expect_local(),
1084+
qself.span,
10831085
assoc_ident,
10841086
span,
10851087
)?,

tests/ui/resolve/issue-55673.stderr

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ help: consider further restricting type parameter `T`
1919
|
2020
LL | T::Baa: std::fmt::Debug, T: Foo
2121
| ~~~~~~~~
22-
help: and also change the associated type name
22+
help: ...and changing the associated type name
2323
|
2424
LL | T::Bar: std::fmt::Debug,
2525
| ~~~
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
error[E0220]: associated type `Assoc` not found for `T`
2+
--> $DIR/unresolved-assoc-ty-suggest-trait.rs:11:22
3+
|
4+
LL | type AssocOf<T> = T::Assoc;
5+
| ^^^^^ there is an associated type `Assoc` in the trait `Trait`
6+
|
7+
help: consider fully qualifying the associated type
8+
|
9+
LL | type AssocOf<T> = <T as Trait>::Assoc;
10+
| + +++++++++
11+
12+
error[E0220]: associated type `Assok` not found for `T`
13+
--> $DIR/unresolved-assoc-ty-suggest-trait.rs:15:22
14+
|
15+
LL | type AssokOf<T> = T::Assok;
16+
| ^^^^^ there is a similarly named associated type `Assoc` in the trait `Trait`
17+
|
18+
help: consider fully qualifying and renaming the associated type
19+
|
20+
LL | type AssokOf<T> = <T as Trait>::Assoc;
21+
| + +++++++++ ~~~~~
22+
23+
error: aborting due to 2 previous errors
24+
25+
For more information about this error, try `rustc --explain E0220`.
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
error[E0220]: associated type `Assoc` not found for `T`
2+
--> $DIR/unresolved-assoc-ty-suggest-trait.rs:11:22
3+
|
4+
LL | type AssocOf<T> = T::Assoc;
5+
| ^^^^^ there is an associated type `Assoc` in the trait `Trait`
6+
|
7+
help: consider restricting type parameter `T`
8+
|
9+
LL | type AssocOf<T: Trait> = T::Assoc;
10+
| +++++++
11+
12+
error[E0220]: associated type `Assok` not found for `T`
13+
--> $DIR/unresolved-assoc-ty-suggest-trait.rs:15:22
14+
|
15+
LL | type AssokOf<T> = T::Assok;
16+
| ^^^^^ there is a similarly named associated type `Assoc` in the trait `Trait`
17+
|
18+
help: consider restricting type parameter `T`
19+
|
20+
LL | type AssokOf<T: Trait> = T::Assok;
21+
| +++++++
22+
help: ...and changing the associated type name
23+
|
24+
LL | type AssokOf<T> = T::Assoc;
25+
| ~~~~~
26+
27+
error: aborting due to 2 previous errors
28+
29+
For more information about this error, try `rustc --explain E0220`.
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
// Ensure that we don't suggest *type alias bounds* for **eager** type aliases.
2+
// issue: rust-lang/rust#125789
3+
4+
//@ revisions: eager lazy
5+
#![cfg_attr(lazy, feature(lazy_type_alias), allow(incomplete_features))]
6+
7+
// FIXME(fmease): Suggest a full trait ref (with placeholders) instead of just a trait name.
8+
9+
trait Trait<T> { type Assoc; }
10+
11+
type AssocOf<T> = T::Assoc; //~ ERROR associated type `Assoc` not found for `T`
12+
//[eager]~^ HELP consider fully qualifying the associated type
13+
//[lazy]~| HELP consider restricting type parameter `T`
14+
15+
type AssokOf<T> = T::Assok; //~ ERROR associated type `Assok` not found for `T`
16+
//[eager]~^ HELP consider fully qualifying and renaming the associated type
17+
//[lazy]~| HELP consider restricting type parameter `T`
18+
//[lazy]~| HELP and changing the associated type name
19+
20+
fn main() {}

0 commit comments

Comments
 (0)