Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
60 changes: 48 additions & 12 deletions compiler/rustc_hir_analysis/src/check/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ use rustc_hir::intravisit::Visitor;
use rustc_index::bit_set::DenseBitSet;
use rustc_infer::infer::{self, TyCtxtInferExt as _};
use rustc_infer::traits::ObligationCause;
use rustc_middle::middle::stability::EvalResult;
use rustc_middle::query::Providers;
use rustc_middle::ty::error::{ExpectedFound, TypeError};
use rustc_middle::ty::print::with_types_for_signature;
Expand All @@ -105,6 +106,7 @@ use self::compare_impl_item::collect_return_position_impl_trait_in_trait_tys;
use self::region::region_scope_tree;
use crate::diagnostics::{
MissingTraitItemLabel, MissingTraitItemSuggestion, MissingTraitItemSuggestionNone,
MissingTraitItemSuggestionUnstable,
};
use crate::{check_c_variadic_abi, diagnostics};

Expand Down Expand Up @@ -229,6 +231,7 @@ fn missing_items_suggestions(
String,
Vec<MissingTraitItemSuggestion>,
Vec<MissingTraitItemSuggestionNone>,
Vec<MissingTraitItemSuggestionUnstable>,
Vec<MissingTraitItemLabel>,
) {
let missing_items =
Expand All @@ -244,8 +247,12 @@ fn missing_items_suggestions(

// Obtain the level of indentation ending in `sugg_sp`.
let padding = tcx.sess.source_map().indentation_before(sugg_sp).unwrap_or_else(String::new);
let (mut missing_trait_item, mut missing_trait_item_none, mut missing_trait_item_label) =
(Vec::new(), Vec::new(), Vec::new());
let (
mut missing_trait_item,
mut missing_trait_item_none,
mut missing_trait_item_unstable,
mut missing_trait_item_label,
) = (Vec::new(), Vec::new(), Vec::new(), Vec::new());

for &trait_item in missing_items {
let snippet = with_types_for_signature!(suggestion_signature(
Expand All @@ -263,27 +270,50 @@ fn missing_items_suggestions(
snippet,
});
} else {
missing_trait_item_none.push(diagnostics::MissingTraitItemSuggestionNone {
span: sugg_sp,
code,
snippet,
})
if let EvalResult::Deny { feature, .. } =
tcx.eval_stability(trait_item.def_id, None, sugg_sp, None)
{
missing_trait_item_unstable.push(diagnostics::MissingTraitItemSuggestionUnstable {
span: sugg_sp,
code,
snippet,
feature,
});
} else {
missing_trait_item_none.push(diagnostics::MissingTraitItemSuggestionNone {
span: sugg_sp,
code,
snippet,
});
}
}
}

(missing_items_msg, missing_trait_item, missing_trait_item_none, missing_trait_item_label)
(
missing_items_msg,
missing_trait_item,
missing_trait_item_none,
missing_trait_item_unstable,
missing_trait_item_label,
)
}

fn missing_items_err(tcx: TyCtxt<'_>, impl_def_id: LocalDefId, missing_items: &[ty::AssocItem]) {
let (missing_items_msg, missing_trait_item, missing_trait_item_none, missing_trait_item_label) =
missing_items_suggestions(tcx, impl_def_id, missing_items);
let (
missing_items_msg,
missing_trait_item,
missing_trait_item_none,
missing_trait_item_unstable,
missing_trait_item_label,
) = missing_items_suggestions(tcx, impl_def_id, missing_items);

tcx.dcx().emit_err(diagnostics::MissingTraitItem {
span: tcx.span_of_impl(impl_def_id.to_def_id()).unwrap(),
missing_items_msg,
missing_trait_item_label,
missing_trait_item,
missing_trait_item_none,
missing_trait_item_unstable,
});
}

Expand All @@ -301,15 +331,21 @@ fn missing_items_must_implement_one_of_err(
.cloned()
.collect::<Vec<_>>();

let (missing_items_msg, missing_trait_item, missing_trait_item_none, missing_trait_item_label) =
missing_items_suggestions(tcx, impl_def_id, &missing_items);
let (
missing_items_msg,
missing_trait_item,
missing_trait_item_none,
missing_trait_item_unstable,
missing_trait_item_label,
) = missing_items_suggestions(tcx, impl_def_id, &missing_items);

tcx.dcx().emit_err(diagnostics::MissingOneOfTraitItem {
span: tcx.def_span(impl_def_id),
note: annotation_span,
missing_items_msg,
missing_trait_item_label,
missing_trait_item,
missing_trait_item_unstable,
missing_trait_item_none,
})
}
Expand Down
19 changes: 19 additions & 0 deletions compiler/rustc_hir_analysis/src/diagnostics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -919,6 +919,8 @@ pub(crate) struct MissingTraitItem {
pub missing_trait_item: Vec<MissingTraitItemSuggestion>,
#[subdiagnostic]
pub missing_trait_item_none: Vec<MissingTraitItemSuggestionNone>,
#[subdiagnostic]
pub missing_trait_item_unstable: Vec<MissingTraitItemSuggestionUnstable>,
pub missing_items_msg: String,
}

Expand All @@ -944,6 +946,21 @@ pub(crate) struct MissingTraitItemSuggestion {
pub snippet: String,
}

#[derive(Subdiagnostic)]
#[suggestion(
"implement the missing item: `{$snippet}` (unstable, requires feature `{$feature}`)",
style = "hidden",
applicability = "has-placeholders",
code = "{code}"
)]
pub(crate) struct MissingTraitItemSuggestionUnstable {
#[primary_span]
pub span: Span,
pub code: String,
pub snippet: String,
pub feature: Symbol,
}

#[derive(Subdiagnostic)]
#[suggestion(
"implement the missing item: `{$snippet}`",
Expand Down Expand Up @@ -972,6 +989,8 @@ pub(crate) struct MissingOneOfTraitItem {
pub missing_trait_item: Vec<MissingTraitItemSuggestion>,
#[subdiagnostic]
pub missing_trait_item_none: Vec<MissingTraitItemSuggestionNone>,
#[subdiagnostic]
pub missing_trait_item_unstable: Vec<MissingTraitItemSuggestionUnstable>,
pub missing_items_msg: String,
}

Expand Down
2 changes: 1 addition & 1 deletion tests/ui/async-await/async-fn/impl-header.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ error[E0046]: not all trait items implemented, missing: `call`
LL | impl async Fn<()> for F {}
| ^^^^^^^^^^^^^^^^^^^^^^^ missing `call` in implementation
|
= help: implement the missing item: `fn call(&self, _: ()) -> <Self as FnOnce<()>>::Output { todo!() }`
= help: implement the missing item: `fn call(&self, _: ()) -> <Self as FnOnce<()>>::Output { todo!() }` (unstable, requires feature `fn_traits`)

error[E0277]: expected an `FnMut()` closure, found `F`
--> $DIR/impl-header.rs:5:23
Expand Down
2 changes: 1 addition & 1 deletion tests/ui/lifetimes/issue-95023.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ error[E0046]: not all trait items implemented, missing: `call`
LL | impl Fn(&isize) for Error {
| ^^^^^^^^^^^^^^^^^^^^^^^^^ missing `call` in implementation
|
= help: implement the missing item: `fn call(&self, _: (&isize,)) -> <Self as FnOnce<(&isize,)>>::Output { todo!() }`
= help: implement the missing item: `fn call(&self, _: (&isize,)) -> <Self as FnOnce<(&isize,)>>::Output { todo!() }` (unstable, requires feature `fn_traits`)

error[E0277]: expected an `FnMut(&isize)` closure, found `Error`
--> $DIR/issue-95023.rs:3:21
Expand Down
31 changes: 31 additions & 0 deletions tests/ui/traits/default-method/auxiliary/mioou.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
#![feature(rustc_attrs)]
#![feature(staged_api)]
#![stable(feature="s", since="1.0.0")]

#[rustc_must_implement_one_of(a1, b1)]
#[stable(feature="s", since="1.0.0")]
pub trait Trait1 {
#[stable(feature="s", since="1.0.0")]
fn a1(&self) -> u64 {
self.a1() + 1
}

#[stable(feature="s", since="1.0.0")]
fn b1(&self) -> u64 {
self.b1() + 1
}
}

#[rustc_must_implement_one_of(a2, b2)]
#[stable(feature="s", since="1.0.0")]
pub trait Trait2 {
#[stable(feature="s", since="1.0.0")]
fn a2(&self) -> u64 {
self.b2() + 1
}

#[unstable(feature="trait2_b2", issue="none")]
fn b2(&self) -> u64 {
self.a2() + 1
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
//@ edition:2024
//@ aux-crate:mioou=mioou.rs

use mioou::*;

struct A;

impl Trait1 for A {
//~^ ERROR not all trait items implemented, missing one of: `a1`, `b1`
}

impl Trait2 for A {
//~^ ERROR not all trait items implemented, missing one of: `a2`, `b2`
}

fn main() {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
error[E0046]: not all trait items implemented, missing one of: `a1`, `b1`
--> $DIR/rustc_must_implement_one_of-unstable.rs:8:1
|
LL | impl Trait1 for A {
| ^^^^^^^^^^^^^^^^^ missing one of `a1`, `b1` in implementation
|
= help: implement the missing item: `fn a1(&self) -> u64 { todo!() }`
= help: implement the missing item: `fn b1(&self) -> u64 { todo!() }`

error[E0046]: not all trait items implemented, missing one of: `a2`, `b2`
--> $DIR/rustc_must_implement_one_of-unstable.rs:12:1
|
LL | impl Trait2 for A {
| ^^^^^^^^^^^^^^^^^ missing one of `a2`, `b2` in implementation
|
= help: implement the missing item: `fn a2(&self) -> u64 { todo!() }`
= help: implement the missing item: `fn b2(&self) -> u64 { todo!() }` (unstable, requires feature `trait2_b2`)

error: aborting due to 2 previous errors

For more information about this error, try `rustc --explain E0046`.
2 changes: 1 addition & 1 deletion tests/ui/traits/issue-87558.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ error[E0046]: not all trait items implemented, missing: `call`
LL | impl Fn(&isize) for Error {
| ^^^^^^^^^^^^^^^^^^^^^^^^^ missing `call` in implementation
|
= help: implement the missing item: `fn call(&self, _: (&isize,)) -> <Self as FnOnce<(&isize,)>>::Output { todo!() }`
= help: implement the missing item: `fn call(&self, _: (&isize,)) -> <Self as FnOnce<(&isize,)>>::Output { todo!() }` (unstable, requires feature `fn_traits`)

error[E0277]: expected an `FnMut(&isize)` closure, found `Error`
--> $DIR/issue-87558.rs:3:21
Expand Down
Loading