Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Mention "signature" rather than "fn pointer" when impl/trait methods are incompatible #106131

Merged
merged 1 commit into from
Jan 9, 2023
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
4 changes: 2 additions & 2 deletions compiler/rustc_error_messages/locales/en-US/infer.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -253,8 +253,8 @@ infer_trait_placeholder_mismatch = implementation of `{$trait_def_id}` is not ge
infer_trait_impl_diff = `impl` item signature doesn't match `trait` item signature
.found = found `{$found}`
.expected = expected `{$expected}`
.expected_found = expected `{$expected}`
{" "}found `{$found}`
.expected_found = expected signature `{$expected}`
{" "}found signature `{$found}`

infer_tid_rel_help = verify the lifetime relationships in the `trait` and `impl` between the `self` argument, the other inputs and its output
infer_tid_consider_borrowing = consider borrowing this type parameter in the trait
Expand Down
36 changes: 14 additions & 22 deletions compiler/rustc_hir_analysis/src/check/compare_impl_item.rs
Original file line number Diff line number Diff line change
Expand Up @@ -270,8 +270,8 @@ fn compare_method_predicate_entailment<'tcx>(
let unnormalized_impl_fty = tcx.mk_fn_ptr(ty::Binder::dummy(unnormalized_impl_sig));

let norm_cause = ObligationCause::misc(impl_m_span, impl_m_hir_id);
let impl_fty = ocx.normalize(&norm_cause, param_env, unnormalized_impl_fty);
debug!("compare_impl_method: impl_fty={:?}", impl_fty);
let impl_sig = ocx.normalize(&norm_cause, param_env, unnormalized_impl_sig);
debug!("compare_impl_method: impl_fty={:?}", impl_sig);

let trait_sig = tcx.bound_fn_sig(trait_m.def_id).subst(tcx, trait_to_placeholder_substs);
let trait_sig = tcx.liberate_late_bound_regions(impl_m.def_id, trait_sig);
Expand All @@ -294,18 +294,17 @@ fn compare_method_predicate_entailment<'tcx>(
// type would be more appropriate. In other places we have a `Vec<Span>`
// corresponding to their `Vec<Predicate>`, but we don't have that here.
// Fixing this would improve the output of test `issue-83765.rs`.
let result = ocx.sup(&cause, param_env, trait_fty, impl_fty);
let result = ocx.sup(&cause, param_env, trait_sig, impl_sig);

if let Err(terr) = result {
debug!(?terr, "sub_types failed: impl ty {:?}, trait ty {:?}", impl_fty, trait_fty);
debug!(?impl_sig, ?trait_sig, ?terr, "sub_types failed");

let emitted = report_trait_method_mismatch(
&infcx,
cause,
terr,
(trait_m, trait_fty),
(impl_m, impl_fty),
trait_sig,
(trait_m, trait_sig),
(impl_m, impl_sig),
impl_trait_ref,
);
return Err(emitted);
Expand Down Expand Up @@ -484,7 +483,8 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>(
let impl_trait_ref = tcx.impl_trait_ref(impl_m.impl_container(tcx).unwrap()).unwrap();
let param_env = tcx.param_env(def_id);

// First, check a few of the same thing as `compare_impl_method`, just so we don't ICE during substitutions later.
// First, check a few of the same things as `compare_impl_method`,
// just so we don't ICE during substitution later.
compare_number_of_generics(tcx, impl_m, trait_m, tcx.hir().span_if_local(impl_m.def_id), true)?;
compare_generic_param_kinds(tcx, impl_m, trait_m, true)?;
check_region_bounds_on_impl_item(tcx, impl_m, trait_m, true)?;
Expand Down Expand Up @@ -577,14 +577,11 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>(

debug!(?trait_sig, ?impl_sig, "equating function signatures");

let trait_fty = tcx.mk_fn_ptr(ty::Binder::dummy(trait_sig));
let impl_fty = tcx.mk_fn_ptr(ty::Binder::dummy(impl_sig));

// Unify the whole function signature. We need to do this to fully infer
// the lifetimes of the return type, but do this after unifying just the
// return types, since we want to avoid duplicating errors from
// `compare_method_predicate_entailment`.
match ocx.eq(&cause, param_env, trait_fty, impl_fty) {
match ocx.eq(&cause, param_env, trait_sig, impl_sig) {
Ok(()) => {}
Err(terr) => {
// This function gets called during `compare_method_predicate_entailment` when normalizing a
Expand All @@ -595,9 +592,8 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>(
infcx,
cause,
terr,
(trait_m, trait_fty),
(impl_m, impl_fty),
trait_sig,
(trait_m, trait_sig),
(impl_m, impl_sig),
impl_trait_ref,
);
return Err(emitted);
Expand Down Expand Up @@ -771,9 +767,8 @@ fn report_trait_method_mismatch<'tcx>(
infcx: &InferCtxt<'tcx>,
mut cause: ObligationCause<'tcx>,
terr: TypeError<'tcx>,
(trait_m, trait_fty): (&ty::AssocItem, Ty<'tcx>),
(impl_m, impl_fty): (&ty::AssocItem, Ty<'tcx>),
trait_sig: ty::FnSig<'tcx>,
(trait_m, trait_sig): (&ty::AssocItem, ty::FnSig<'tcx>),
(impl_m, impl_sig): (&ty::AssocItem, ty::FnSig<'tcx>),
impl_trait_ref: ty::TraitRef<'tcx>,
) -> ErrorGuaranteed {
let tcx = infcx.tcx;
Expand Down Expand Up @@ -858,10 +853,7 @@ fn report_trait_method_mismatch<'tcx>(
&mut diag,
&cause,
trait_err_span.map(|sp| (sp, "type in trait".to_owned())),
Some(infer::ValuePairs::Terms(ExpectedFound {
expected: trait_fty.into(),
found: impl_fty.into(),
})),
Some(infer::ValuePairs::Sigs(ExpectedFound { expected: trait_sig, found: impl_sig })),
terr,
false,
false,
Expand Down
12 changes: 12 additions & 0 deletions compiler/rustc_infer/src/infer/at.rs
Original file line number Diff line number Diff line change
Expand Up @@ -427,3 +427,15 @@ impl<'tcx> ToTrace<'tcx> for ty::AliasTy<'tcx> {
}
}
}

impl<'tcx> ToTrace<'tcx> for ty::FnSig<'tcx> {
fn to_trace(
_: TyCtxt<'tcx>,
cause: &ObligationCause<'tcx>,
a_is_expected: bool,
a: Self,
b: Self,
) -> TypeTrace<'tcx> {
TypeTrace { cause: cause.clone(), values: Sigs(ExpectedFound::new(a_is_expected, a, b)) }
}
}
20 changes: 18 additions & 2 deletions compiler/rustc_infer/src/infer/error_reporting/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1429,8 +1429,8 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
impl<'tcx> OpaqueTypesVisitor<'tcx> {
fn visit_expected_found(
tcx: TyCtxt<'tcx>,
expected: Ty<'tcx>,
found: Ty<'tcx>,
expected: impl TypeVisitable<'tcx>,
found: impl TypeVisitable<'tcx>,
ignore_span: Span,
) -> Self {
let mut types_visitor = OpaqueTypesVisitor {
Expand Down Expand Up @@ -1570,6 +1570,11 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
_ => (false, Mismatch::Fixed("type")),
}
}
ValuePairs::Sigs(infer::ExpectedFound { expected, found }) => {
OpaqueTypesVisitor::visit_expected_found(self.tcx, expected, found, span)
.report(diag);
(false, Mismatch::Fixed("signature"))
}
ValuePairs::TraitRefs(_) | ValuePairs::PolyTraitRefs(_) => {
(false, Mismatch::Fixed("trait"))
}
Expand Down Expand Up @@ -2041,6 +2046,17 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
ret => ret,
}
}
infer::Sigs(exp_found) => {
let exp_found = self.resolve_vars_if_possible(exp_found);
if exp_found.references_error() {
return None;
}
let (exp, fnd) = self.cmp_fn_sig(
&ty::Binder::dummy(exp_found.expected),
&ty::Binder::dummy(exp_found.found),
);
Some((exp, fnd, None, None))
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,15 @@
use crate::errors::{ConsiderBorrowingParamHelp, RelationshipHelp, TraitImplDiff};
use crate::infer::error_reporting::nice_region_error::NiceRegionError;
use crate::infer::lexical_region_resolve::RegionResolutionError;
use crate::infer::Subtype;
use crate::infer::{Subtype, ValuePairs};
use crate::traits::ObligationCauseCode::CompareImplItemObligation;
use rustc_errors::ErrorGuaranteed;
use rustc_hir as hir;
use rustc_hir::def::Res;
use rustc_hir::def_id::DefId;
use rustc_hir::intravisit::Visitor;
use rustc_middle::hir::nested_filter;
use rustc_middle::ty::error::ExpectedFound;
use rustc_middle::ty::print::RegionHighlightMode;
use rustc_middle::ty::{self, Ty, TyCtxt, TypeSuperVisitable, TypeVisitor};
use rustc_span::Span;
Expand All @@ -23,22 +24,27 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
let error = self.error.as_ref()?;
debug!("try_report_impl_not_conforming_to_trait {:?}", error);
if let RegionResolutionError::SubSupConflict(
_,
var_origin,
sub_origin,
_sub,
sup_origin,
_sup,
_,
) = error.clone()
_,
var_origin,
sub_origin,
_sub,
sup_origin,
_sup,
_,
) = error.clone()
&& let (Subtype(sup_trace), Subtype(sub_trace)) = (&sup_origin, &sub_origin)
&& let sub_expected_found @ Some((sub_expected, sub_found)) = sub_trace.values.ty()
&& let sup_expected_found @ Some(_) = sup_trace.values.ty()
&& let CompareImplItemObligation { trait_item_def_id, .. } = sub_trace.cause.code()
&& sup_expected_found == sub_expected_found
&& sub_trace.values == sup_trace.values
&& let ValuePairs::Sigs(ExpectedFound { expected, found }) = sub_trace.values
{
let guar =
self.emit_err(var_origin.span(), sub_expected, sub_found, *trait_item_def_id);
// FIXME(compiler-errors): Don't like that this needs `Ty`s, but
// all of the region highlighting machinery only deals with those.
let guar = self.emit_err(
var_origin.span(),
self.cx.tcx.mk_fn_ptr(ty::Binder::dummy(expected)),
self.cx.tcx.mk_fn_ptr(ty::Binder::dummy(found)),
*trait_item_def_id,
);
return Some(guar);
}
None
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_infer/src/infer/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -361,6 +361,7 @@ pub enum ValuePairs<'tcx> {
Terms(ExpectedFound<ty::Term<'tcx>>),
TraitRefs(ExpectedFound<ty::TraitRef<'tcx>>),
PolyTraitRefs(ExpectedFound<ty::PolyTraitRef<'tcx>>),
Sigs(ExpectedFound<ty::FnSig<'tcx>>),
}

impl<'tcx> ValuePairs<'tcx> {
Expand Down
8 changes: 4 additions & 4 deletions src/test/ui/associated-types/defaults-specialization.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@ note: type in trait
|
LL | fn make() -> Self::Ty {
| ^^^^^^^^
= note: expected fn pointer `fn() -> <A<T> as Tr>::Ty`
found fn pointer `fn() -> u8`
= note: expected signature `fn() -> <A<T> as Tr>::Ty`
found signature `fn() -> u8`

error[E0053]: method `make` has an incompatible type for trait
--> $DIR/defaults-specialization.rs:35:18
Expand All @@ -42,8 +42,8 @@ note: type in trait
|
LL | fn make() -> Self::Ty {
| ^^^^^^^^
= note: expected fn pointer `fn() -> <B<T> as Tr>::Ty`
found fn pointer `fn() -> bool`
= note: expected signature `fn() -> <B<T> as Tr>::Ty`
found signature `fn() -> bool`

error[E0308]: mismatched types
--> $DIR/defaults-specialization.rs:10:9
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ note: type in trait
|
LL | fn foo(&self) -> Pin<Box<dyn Future<Output = i32> + '_>>;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= note: expected fn pointer `fn(&i32) -> Pin<Box<dyn Future<Output = i32>>>`
found fn pointer `fn(&i32) -> impl Future<Output = i32>`
= note: expected signature `fn(&i32) -> Pin<Box<dyn Future<Output = i32>>>`
found signature `fn(&i32) -> impl Future<Output = i32>`

error: aborting due to previous error

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@ error[E0308]: method not compatible with trait
LL | fn wrong_bound1<'b,'c,'d:'a+'c>(self, b: Inv<'b>, c: Inv<'c>, d: Inv<'d>) {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ lifetime mismatch
|
= note: expected fn pointer `fn(&'a isize, Inv<'c>, Inv<'c>, Inv<'_>)`
found fn pointer `fn(&'a isize, Inv<'_>, Inv<'c>, Inv<'_>)`
= note: expected signature `fn(&'a isize, Inv<'c>, Inv<'c>, Inv<'_>)`
found signature `fn(&'a isize, Inv<'_>, Inv<'c>, Inv<'_>)`
note: the lifetime `'c` as defined here...
--> $DIR/regions-bound-missing-bound-in-impl.rs:27:24
|
Expand All @@ -41,8 +41,8 @@ error[E0308]: method not compatible with trait
LL | fn wrong_bound1<'b,'c,'d:'a+'c>(self, b: Inv<'b>, c: Inv<'c>, d: Inv<'d>) {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ lifetime mismatch
|
= note: expected fn pointer `fn(&'a isize, Inv<'c>, Inv<'c>, Inv<'_>)`
found fn pointer `fn(&'a isize, Inv<'_>, Inv<'c>, Inv<'_>)`
= note: expected signature `fn(&'a isize, Inv<'c>, Inv<'c>, Inv<'_>)`
found signature `fn(&'a isize, Inv<'_>, Inv<'c>, Inv<'_>)`
note: the lifetime `'c` as defined here...
--> $DIR/regions-bound-missing-bound-in-impl.rs:27:24
|
Expand Down
12 changes: 6 additions & 6 deletions src/test/ui/compare-method/bad-self-type.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ LL | fn poll(self, _: &mut Context<'_>) -> Poll<()> {
| expected struct `Pin`, found struct `MyFuture`
| help: change the self-receiver type to match the trait: `self: Pin<&mut MyFuture>`
|
= note: expected fn pointer `fn(Pin<&mut MyFuture>, &mut Context<'_>) -> Poll<_>`
found fn pointer `fn(MyFuture, &mut Context<'_>) -> Poll<_>`
= note: expected signature `fn(Pin<&mut MyFuture>, &mut Context<'_>) -> Poll<_>`
found signature `fn(MyFuture, &mut Context<'_>) -> Poll<_>`

error[E0053]: method `foo` has an incompatible type for trait
--> $DIR/bad-self-type.rs:22:18
Expand All @@ -24,8 +24,8 @@ note: type in trait
|
LL | fn foo(self);
| ^^^^
= note: expected fn pointer `fn(MyFuture)`
found fn pointer `fn(Box<MyFuture>)`
= note: expected signature `fn(MyFuture)`
found signature `fn(Box<MyFuture>)`

error[E0053]: method `bar` has an incompatible type for trait
--> $DIR/bad-self-type.rs:24:18
Expand All @@ -38,8 +38,8 @@ note: type in trait
|
LL | fn bar(self) -> Option<()>;
| ^^^^^^^^^^
= note: expected fn pointer `fn(MyFuture) -> Option<()>`
found fn pointer `fn(MyFuture)`
= note: expected signature `fn(MyFuture) -> Option<()>`
found signature `fn(MyFuture)`
help: change the output type to match the trait
|
LL | fn bar(self) -> Option<()> {}
Expand Down
8 changes: 4 additions & 4 deletions src/test/ui/compare-method/issue-90444.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ LL | fn from(_: fn((), (), &mut ())) -> Self {
| types differ in mutability
| help: change the parameter type to match the trait: `for<'a> fn((), (), &'a ())`
|
= note: expected fn pointer `fn(for<'a> fn((), (), &'a ())) -> A`
found fn pointer `fn(for<'a> fn((), (), &'a mut ())) -> A`
= note: expected signature `fn(for<'a> fn((), (), &'a ())) -> A`
found signature `fn(for<'a> fn((), (), &'a mut ())) -> A`

error[E0053]: method `from` has an incompatible type for trait
--> $DIR/issue-90444.rs:11:16
Expand All @@ -19,8 +19,8 @@ LL | fn from(_: fn((), (), u64)) -> Self {
| expected `u32`, found `u64`
| help: change the parameter type to match the trait: `fn((), (), u32)`
|
= note: expected fn pointer `fn(fn((), (), u32)) -> B`
found fn pointer `fn(fn((), (), u64)) -> B`
= note: expected signature `fn(fn((), (), u32)) -> B`
found signature `fn(fn((), (), u64)) -> B`

error: aborting due to 2 previous errors

Expand Down
4 changes: 2 additions & 2 deletions src/test/ui/compare-method/reordered-type-param.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ note: type in trait
|
LL | fn b<C:Clone,D>(&self, x: C) -> C;
| ^
= note: expected fn pointer `fn(&E, F) -> F`
found fn pointer `fn(&E, G) -> G`
= note: expected signature `fn(&E, F) -> F`
found signature `fn(&E, G) -> G`
= note: a type parameter was expected, but a different one was found; you might be missing a type parameter or trait bound
= note: for more information, visit https://doc.rust-lang.org/book/ch10-02-traits.html#traits-as-parameters

Expand Down
4 changes: 2 additions & 2 deletions src/test/ui/impl-trait/impl-generic-mismatch-ab.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ note: type in trait
|
LL | fn foo<A: Debug>(&self, a: &A, b: &impl Debug);
| ^^
= note: expected fn pointer `fn(&(), &B, &impl Debug)`
found fn pointer `fn(&(), &impl Debug, &B)`
= note: expected signature `fn(&(), &B, &impl Debug)`
found signature `fn(&(), &impl Debug, &B)`
= note: a type parameter was expected, but a different one was found; you might be missing a type parameter or trait bound
= note: for more information, visit https://doc.rust-lang.org/book/ch10-02-traits.html#traits-as-parameters

Expand Down
12 changes: 6 additions & 6 deletions src/test/ui/impl-trait/in-trait/method-signature-matches.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ note: type in trait
|
LL | fn owo(x: ()) -> impl Sized;
| ^^
= note: expected fn pointer `fn(())`
found fn pointer `fn(u8)`
= note: expected signature `fn(())`
found signature `fn(u8)`

error[E0053]: method `owo` has an incompatible type for trait
--> $DIR/method-signature-matches.rs:20:21
Expand All @@ -39,8 +39,8 @@ note: type in trait
|
LL | async fn owo(x: ()) {}
| ^^
= note: expected fn pointer `fn(()) -> _`
found fn pointer `fn(u8) -> _`
= note: expected signature `fn(()) -> _`
found signature `fn(u8) -> _`

error[E0050]: method `calm_down_please` has 3 parameters but the declaration in trait `TooMuch::calm_down_please` has 0
--> $DIR/method-signature-matches.rs:29:28
Expand Down Expand Up @@ -75,8 +75,8 @@ note: type in trait
|
LL | fn early<'early, T>(x: &'early T) -> impl Sized;
| ^^^^^^^^^
= note: expected fn pointer `fn(&'early T)`
found fn pointer `fn(&())`
= note: expected signature `fn(&'early T)`
found signature `fn(&())`

error: aborting due to 5 previous errors

Expand Down
Loading