Don't report on_unimplemented for negative traits
This commit is contained in:
parent
f6648f252a
commit
5a8405a5fa
@ -952,7 +952,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
unimplemented_traits.entry(p.trait_ref.def_id).or_insert((
|
unimplemented_traits.entry(p.trait_ref.def_id).or_insert((
|
||||||
predicate.kind().rebind(p.trait_ref),
|
predicate.kind().rebind(p),
|
||||||
Obligation {
|
Obligation {
|
||||||
cause: cause.clone(),
|
cause: cause.clone(),
|
||||||
param_env: self.param_env,
|
param_env: self.param_env,
|
||||||
|
@ -202,7 +202,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
|||||||
notes,
|
notes,
|
||||||
parent_label,
|
parent_label,
|
||||||
append_const_msg,
|
append_const_msg,
|
||||||
} = self.on_unimplemented_note(main_trait_ref, o, &mut long_ty_file);
|
} = self.on_unimplemented_note(main_trait_predicate, o, &mut long_ty_file);
|
||||||
|
|
||||||
let have_alt_message = message.is_some() || label.is_some();
|
let have_alt_message = message.is_some() || label.is_some();
|
||||||
let is_try_conversion = self.is_try_conversion(span, main_trait_ref.def_id());
|
let is_try_conversion = self.is_try_conversion(span, main_trait_ref.def_id());
|
||||||
|
@ -9,7 +9,7 @@ use rustc_hir::def_id::{DefId, LocalDefId};
|
|||||||
use rustc_macros::LintDiagnostic;
|
use rustc_macros::LintDiagnostic;
|
||||||
use rustc_middle::bug;
|
use rustc_middle::bug;
|
||||||
use rustc_middle::ty::print::PrintTraitRefExt as _;
|
use rustc_middle::ty::print::PrintTraitRefExt as _;
|
||||||
use rustc_middle::ty::{self, GenericArgsRef, GenericParamDefKind, TyCtxt};
|
use rustc_middle::ty::{self, GenericArgsRef, GenericParamDefKind, ToPolyTraitRef, TyCtxt};
|
||||||
use rustc_parse_format::{ParseMode, Parser, Piece, Position};
|
use rustc_parse_format::{ParseMode, Parser, Piece, Position};
|
||||||
use rustc_session::lint::builtin::UNKNOWN_OR_MALFORMED_DIAGNOSTIC_ATTRIBUTES;
|
use rustc_session::lint::builtin::UNKNOWN_OR_MALFORMED_DIAGNOSTIC_ATTRIBUTES;
|
||||||
use rustc_span::Span;
|
use rustc_span::Span;
|
||||||
@ -108,14 +108,18 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
|
|||||||
|
|
||||||
pub fn on_unimplemented_note(
|
pub fn on_unimplemented_note(
|
||||||
&self,
|
&self,
|
||||||
trait_ref: ty::PolyTraitRef<'tcx>,
|
trait_pred: ty::PolyTraitPredicate<'tcx>,
|
||||||
obligation: &PredicateObligation<'tcx>,
|
obligation: &PredicateObligation<'tcx>,
|
||||||
long_ty_file: &mut Option<PathBuf>,
|
long_ty_file: &mut Option<PathBuf>,
|
||||||
) -> OnUnimplementedNote {
|
) -> OnUnimplementedNote {
|
||||||
|
if trait_pred.polarity() != ty::PredicatePolarity::Positive {
|
||||||
|
return OnUnimplementedNote::default();
|
||||||
|
}
|
||||||
|
|
||||||
let (def_id, args) = self
|
let (def_id, args) = self
|
||||||
.impl_similar_to(trait_ref, obligation)
|
.impl_similar_to(trait_pred.to_poly_trait_ref(), obligation)
|
||||||
.unwrap_or_else(|| (trait_ref.def_id(), trait_ref.skip_binder().args));
|
.unwrap_or_else(|| (trait_pred.def_id(), trait_pred.skip_binder().trait_ref.args));
|
||||||
let trait_ref = trait_ref.skip_binder();
|
let trait_pred = trait_pred.skip_binder();
|
||||||
|
|
||||||
let mut flags = vec![];
|
let mut flags = vec![];
|
||||||
// FIXME(-Zlower-impl-trait-in-trait-to-assoc-ty): HIR is not present for RPITITs,
|
// FIXME(-Zlower-impl-trait-in-trait-to-assoc-ty): HIR is not present for RPITITs,
|
||||||
@ -144,13 +148,13 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
|
|||||||
flags.push((sym::cause, Some("MainFunctionType".to_string())));
|
flags.push((sym::cause, Some("MainFunctionType".to_string())));
|
||||||
}
|
}
|
||||||
|
|
||||||
flags.push((sym::Trait, Some(trait_ref.print_trait_sugared().to_string())));
|
flags.push((sym::Trait, Some(trait_pred.trait_ref.print_trait_sugared().to_string())));
|
||||||
|
|
||||||
// Add all types without trimmed paths or visible paths, ensuring they end up with
|
// Add all types without trimmed paths or visible paths, ensuring they end up with
|
||||||
// their "canonical" def path.
|
// their "canonical" def path.
|
||||||
ty::print::with_no_trimmed_paths!(ty::print::with_no_visible_paths!({
|
ty::print::with_no_trimmed_paths!(ty::print::with_no_visible_paths!({
|
||||||
let generics = self.tcx.generics_of(def_id);
|
let generics = self.tcx.generics_of(def_id);
|
||||||
let self_ty = trait_ref.self_ty();
|
let self_ty = trait_pred.self_ty();
|
||||||
// This is also included through the generics list as `Self`,
|
// This is also included through the generics list as `Self`,
|
||||||
// but the parser won't allow you to use it
|
// but the parser won't allow you to use it
|
||||||
flags.push((sym::_Self, Some(self_ty.to_string())));
|
flags.push((sym::_Self, Some(self_ty.to_string())));
|
||||||
@ -266,7 +270,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
|
|||||||
}));
|
}));
|
||||||
|
|
||||||
if let Ok(Some(command)) = OnUnimplementedDirective::of_item(self.tcx, def_id) {
|
if let Ok(Some(command)) = OnUnimplementedDirective::of_item(self.tcx, def_id) {
|
||||||
command.evaluate(self.tcx, trait_ref, &flags, long_ty_file)
|
command.evaluate(self.tcx, trait_pred.trait_ref, &flags, long_ty_file)
|
||||||
} else {
|
} else {
|
||||||
OnUnimplementedNote::default()
|
OnUnimplementedNote::default()
|
||||||
}
|
}
|
||||||
|
12
tests/ui/traits/negative-bounds/on-unimplemented.rs
Normal file
12
tests/ui/traits/negative-bounds/on-unimplemented.rs
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
#![feature(negative_bounds)]
|
||||||
|
|
||||||
|
#[diagnostic::on_unimplemented(message = "this ain't fooing")]
|
||||||
|
trait Foo {}
|
||||||
|
struct NotFoo;
|
||||||
|
|
||||||
|
fn hello() -> impl !Foo {
|
||||||
|
//~^ ERROR the trait bound `NotFoo: !Foo` is not satisfied
|
||||||
|
NotFoo
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {}
|
18
tests/ui/traits/negative-bounds/on-unimplemented.stderr
Normal file
18
tests/ui/traits/negative-bounds/on-unimplemented.stderr
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
error[E0277]: the trait bound `NotFoo: !Foo` is not satisfied
|
||||||
|
--> $DIR/on-unimplemented.rs:7:15
|
||||||
|
|
|
||||||
|
LL | fn hello() -> impl !Foo {
|
||||||
|
| ^^^^^^^^^ the trait bound `NotFoo: !Foo` is not satisfied
|
||||||
|
LL |
|
||||||
|
LL | NotFoo
|
||||||
|
| ------ return type was inferred to be `NotFoo` here
|
||||||
|
|
|
||||||
|
help: this trait has no implementations, consider adding one
|
||||||
|
--> $DIR/on-unimplemented.rs:4:1
|
||||||
|
|
|
||||||
|
LL | trait Foo {}
|
||||||
|
| ^^^^^^^^^
|
||||||
|
|
||||||
|
error: aborting due to 1 previous error
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0277`.
|
Loading…
x
Reference in New Issue
Block a user