Skip to content

Commit

Permalink
And more general error
Browse files Browse the repository at this point in the history
  • Loading branch information
pacak committed May 24, 2024
1 parent d6e4fe5 commit b70fb41
Show file tree
Hide file tree
Showing 7 changed files with 78 additions and 15 deletions.
6 changes: 5 additions & 1 deletion compiler/rustc_resolve/messages.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@ resolve_added_macro_use =
resolve_ancestor_only =
visibilities can only be restricted to ancestor modules
resolve_anonymous_livetime_non_gat_report_error =
in the trait associated type is declared without lifetime parameters, so using a borrowed type for them requires that lifetime to come from the implemented type
.label = this lifetime must come from the implemented type
resolve_arguments_macro_use_not_allowed = arguments to `macro_use` are not allowed here
resolve_associated_const_with_similar_name_exists =
Expand Down Expand Up @@ -235,7 +239,7 @@ resolve_label_with_similar_name_reachable =
a label with a similar name is reachable
resolve_lending_iterator_report_error =
associated type `Iterator::Item` is declared without lifetime parameters, so using a borrowed type for them requires that lifetime to come from the implemented type.
associated type `Iterator::Item` is declared without lifetime parameters, so using a borrowed type for them requires that lifetime to come from the implemented type
.note = you can't create an `Iterator` that borrows each `Item` from itself, but you can instead create a new type that borrows your existing type and implement `Iterator` for that new type.
resolve_lifetime_param_in_enum_discriminant =
Expand Down
8 changes: 8 additions & 0 deletions compiler/rustc_resolve/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -891,6 +891,14 @@ pub(crate) struct LendingIteratorReportError {
pub(crate) ty: Span,
}

#[derive(Diagnostic)]
#[diag(resolve_anonymous_livetime_non_gat_report_error)]
pub(crate) struct AnonymousLivetimeNonGatReportError {
#[primary_span]
#[label]
pub(crate) lifetime: Span,
}

#[derive(Subdiagnostic)]
#[multipart_suggestion(
resolve_elided_anonymous_lifetime_report_error_suggestion,
Expand Down
28 changes: 20 additions & 8 deletions compiler/rustc_resolve/src/late.rs
Original file line number Diff line number Diff line change
Expand Up @@ -629,6 +629,9 @@ struct DiagMetadata<'ast> {
in_assignment: Option<&'ast Expr>,
is_assign_rhs: bool,

/// If we are setting an associated type in trait impl, is it a non-GAT type?
in_non_gat_assoc_type: Option<bool>,

/// Used to detect possible `.` -> `..` typo when calling methods.
in_range: Option<(&'ast Expr, &'ast Expr)>,

Expand Down Expand Up @@ -1704,21 +1707,28 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
}
}

// Is it caused by user trying to implement a lending iterator?
// are we trying to use an anonymous lifetime
// on a non GAT associated trait type?
if !self.in_func_body
&& let Some((module, _)) = &self.current_trait_ref
&& let Some(ty) = &self.diag_metadata.current_self_type
&& Some(true) == self.diag_metadata.in_non_gat_assoc_type
&& let crate::ModuleKind::Def(DefKind::Trait, trait_id, _) = module.kind
&& def_id_matches_path(
{
if def_id_matches_path(
self.r.tcx,
trait_id,
&["core", "iter", "traits", "iterator", "Iterator"],
)
{
self.r.dcx().emit_err(errors::LendingIteratorReportError {
lifetime: lifetime.ident.span,
ty: ty.span(),
});
) {
self.r.dcx().emit_err(errors::LendingIteratorReportError {
lifetime: lifetime.ident.span,
ty: ty.span(),
});
} else {
self.r.dcx().emit_err(errors::AnonymousLivetimeNonGatReportError {
lifetime: lifetime.ident.span,
});
}
} else {
self.r.dcx().emit_err(errors::ElidedAnonymousLivetimeReportError {
span: lifetime.ident.span,
Expand Down Expand Up @@ -3076,6 +3086,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
);
}
AssocItemKind::Type(box TyAlias { generics, .. }) => {
self.diag_metadata.in_non_gat_assoc_type = Some(generics.params.is_empty());
debug!("resolve_implementation AssocItemKind::Type");
// We also need a new scope for the impl item type parameters.
self.with_generic_param_rib(
Expand Down Expand Up @@ -3104,6 +3115,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
});
},
);
self.diag_metadata.in_non_gat_assoc_type = None;
}
AssocItemKind::Delegation(box delegation) => {
debug!("resolve_implementation AssocItemKind::Delegation");
Expand Down
2 changes: 1 addition & 1 deletion tests/ui/impl-header-lifetime-elision/assoc-type.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ trait MyTrait {

impl MyTrait for &i32 {
type Output = &i32;
//~^ ERROR `&` without an explicit lifetime name cannot be used here
//~^ ERROR 11:19: 11:20: in the trait associated type is declared without lifetime parameters, so using a borrowed type for them requires that lifetime to come from the implemented type
}

impl MyTrait for &u32 {
Expand Down
4 changes: 2 additions & 2 deletions tests/ui/impl-header-lifetime-elision/assoc-type.stderr
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
error[E0637]: `&` without an explicit lifetime name cannot be used here
error: in the trait associated type is declared without lifetime parameters, so using a borrowed type for them requires that lifetime to come from the implemented type
--> $DIR/assoc-type.rs:11:19
|
LL | type Output = &i32;
| ^ explicit lifetime name needed here
| ^ this lifetime must come from the implemented type

error[E0637]: `'_` cannot be used here
--> $DIR/assoc-type.rs:16:20
Expand Down
25 changes: 24 additions & 1 deletion tests/ui/lifetimes/no_lending_iterators.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,34 @@ struct Data(String);

impl Iterator for Data {
type Item = &str;
//~^ ERROR 4:17: 4:18: associated type `Iterator::Item` is declared without lifetime parameters, so using a borrowed type for them requires that lifetime to come from the implemented type.
//~^ ERROR 4:17: 4:18: associated type `Iterator::Item` is declared without lifetime parameters, so using a borrowed type for them requires that lifetime to come from the implemented type

fn next(&mut self) -> Option<Self::Item> {
Some(&self.0)
}
}

trait Bar {
type Item;
fn poke(&mut self, item: Self::Item);
}

impl Bar for usize {
type Item = &usize;
//~^ ERROR 18:17: 18:18: in the trait associated type is declared without lifetime parameters, so using a borrowed type for them requires that lifetime to come from the implemented type

fn poke(&mut self, item: Self::Item) {
self += *item;
}
}

impl Bar for isize {
type Item<'a> = &'a isize;
//~^ ERROR 27:14: 27:18: lifetime parameters or bounds on type `Item` do not match the trait declaration [E0195]

fn poke(&mut self, item: Self::Item) {
self += *item;
}
}

fn main() {}
20 changes: 18 additions & 2 deletions tests/ui/lifetimes/no_lending_iterators.stderr
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
error: associated type `Iterator::Item` is declared without lifetime parameters, so using a borrowed type for them requires that lifetime to come from the implemented type.
error: associated type `Iterator::Item` is declared without lifetime parameters, so using a borrowed type for them requires that lifetime to come from the implemented type
--> $DIR/no_lending_iterators.rs:4:17
|
LL | type Item = &str;
Expand All @@ -10,5 +10,21 @@ note: you can't create an `Iterator` that borrows each `Item` from itself, but y
LL | impl Iterator for Data {
| ^^^^

error: aborting due to 1 previous error
error: in the trait associated type is declared without lifetime parameters, so using a borrowed type for them requires that lifetime to come from the implemented type
--> $DIR/no_lending_iterators.rs:18:17
|
LL | type Item = &usize;
| ^ this lifetime must come from the implemented type

error[E0195]: lifetime parameters or bounds on type `Item` do not match the trait declaration
--> $DIR/no_lending_iterators.rs:27:14
|
LL | type Item;
| - lifetimes in impl do not match this type in trait
...
LL | type Item<'a> = &'a isize;
| ^^^^ lifetimes do not match type in trait

error: aborting due to 3 previous errors

For more information about this error, try `rustc --explain E0195`.

0 comments on commit b70fb41

Please sign in to comment.