Skip to content

Commit 6bb7581

Browse files
Slightly improve mismatched GAT where clause error
1 parent c32dcbb commit 6bb7581

File tree

8 files changed

+62
-90
lines changed

8 files changed

+62
-90
lines changed

compiler/rustc_infer/src/infer/error_reporting/nice_region_error/trait_impl_difference.rs

+18-52
Original file line numberDiff line numberDiff line change
@@ -2,17 +2,17 @@
22
33
use crate::infer::error_reporting::nice_region_error::NiceRegionError;
44
use crate::infer::lexical_region_resolve::RegionResolutionError;
5-
use crate::infer::{SubregionOrigin, Subtype};
6-
use crate::traits::ObligationCauseCode::CompareImplMethodObligation;
5+
use crate::infer::Subtype;
6+
use crate::traits::ObligationCauseCode::{CompareImplMethodObligation, CompareImplTypeObligation};
77
use rustc_errors::{ErrorGuaranteed, MultiSpan};
88
use rustc_hir as hir;
99
use rustc_hir::def::Res;
10-
use rustc_hir::def_id::{DefId, LocalDefId};
10+
use rustc_hir::def_id::DefId;
1111
use rustc_hir::intravisit::Visitor;
1212
use rustc_middle::hir::nested_filter;
1313
use rustc_middle::ty::print::RegionHighlightMode;
1414
use rustc_middle::ty::{self, Ty, TyCtxt, TypeSuperVisitable, TypeVisitor};
15-
use rustc_span::{Span, Symbol};
15+
use rustc_span::Span;
1616

1717
use std::ops::ControlFlow;
1818

@@ -22,38 +22,23 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
2222
let error = self.error.as_ref()?;
2323
debug!("try_report_impl_not_conforming_to_trait {:?}", error);
2424
if let RegionResolutionError::SubSupConflict(
25-
_, var_origin, sub_origin, _sub, sup_origin, _sup, _,
25+
_,
26+
var_origin,
27+
sub_origin,
28+
_sub,
29+
sup_origin,
30+
_sup,
31+
_,
2632
) = error.clone()
27-
&& let (&Subtype(ref sup_trace), &Subtype(ref sub_trace)) = (&sup_origin, &sub_origin)
28-
&& let (
29-
sub_expected_found @ Some((sub_expected, sub_found)),
30-
sup_expected_found @ Some(_),
31-
CompareImplMethodObligation { trait_item_def_id, .. },
32-
) = (sub_trace.values.ty(), sup_trace.values.ty(), sub_trace.cause.code())
33+
&& let (Subtype(sup_trace), Subtype(sub_trace)) = (&sup_origin, &sub_origin)
34+
&& let sub_expected_found @ Some((sub_expected, sub_found)) = sub_trace.values.ty()
35+
&& let sup_expected_found @ Some(_) = sup_trace.values.ty()
36+
&& let CompareImplMethodObligation { trait_item_def_id, .. }
37+
| CompareImplTypeObligation { trait_item_def_id, .. } = sub_trace.cause.code()
3338
&& sup_expected_found == sub_expected_found
3439
{
35-
let guar = self.emit_err(
36-
var_origin.span(),
37-
sub_expected,
38-
sub_found,
39-
*trait_item_def_id,
40-
);
41-
return Some(guar);
42-
}
43-
if let RegionResolutionError::ConcreteFailure(origin, _, _)
44-
| RegionResolutionError::GenericBoundFailure(origin, _, _) = error.clone()
45-
&& let SubregionOrigin::CompareImplTypeObligation {
46-
span,
47-
impl_item_def_id,
48-
trait_item_def_id,
49-
} = origin
50-
{
51-
let guar = self.emit_associated_type_err(
52-
span,
53-
self.infcx.tcx.item_name(impl_item_def_id.to_def_id()),
54-
impl_item_def_id,
55-
trait_item_def_id,
56-
);
40+
let guar =
41+
self.emit_err(var_origin.span(), sub_expected, sub_found, *trait_item_def_id);
5742
return Some(guar);
5843
}
5944
None
@@ -147,25 +132,6 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
147132
}
148133
err.emit()
149134
}
150-
151-
fn emit_associated_type_err(
152-
&self,
153-
span: Span,
154-
item_name: Symbol,
155-
impl_item_def_id: LocalDefId,
156-
trait_item_def_id: DefId,
157-
) -> ErrorGuaranteed {
158-
let impl_sp = self.tcx().def_span(impl_item_def_id);
159-
let trait_sp = self.tcx().def_span(trait_item_def_id);
160-
let mut err = self
161-
.tcx()
162-
.sess
163-
.struct_span_err(span, &format!("`impl` associated type signature for `{}` doesn't match `trait` associated type signature", item_name));
164-
err.span_label(impl_sp, "found");
165-
err.span_label(trait_sp, "expected");
166-
167-
err.emit()
168-
}
169135
}
170136

171137
struct TypeParamSpanVisitor<'tcx> {

compiler/rustc_typeck/src/check/compare_method.rs

+16-13
Original file line numberDiff line numberDiff line change
@@ -1212,15 +1212,6 @@ fn compare_type_predicate_entailment<'tcx>(
12121212
// `ObligationCause` (and the `FnCtxt`). This is what
12131213
// `regionck_item` expects.
12141214
let impl_ty_hir_id = tcx.hir().local_def_id_to_hir_id(impl_ty.def_id.expect_local());
1215-
let cause = ObligationCause::new(
1216-
impl_ty_span,
1217-
impl_ty_hir_id,
1218-
ObligationCauseCode::CompareImplTypeObligation {
1219-
impl_item_def_id: impl_ty.def_id.expect_local(),
1220-
trait_item_def_id: trait_ty.def_id,
1221-
},
1222-
);
1223-
12241215
debug!("compare_type_predicate_entailment: trait_to_impl_substs={:?}", trait_to_impl_substs);
12251216

12261217
// The predicates declared by the impl definition, the trait and the
@@ -1239,20 +1230,32 @@ fn compare_type_predicate_entailment<'tcx>(
12391230
Reveal::UserFacing,
12401231
hir::Constness::NotConst,
12411232
);
1242-
let param_env = traits::normalize_param_env_or_error(tcx, param_env, normalize_cause.clone());
1233+
let param_env = traits::normalize_param_env_or_error(tcx, param_env, normalize_cause);
12431234
tcx.infer_ctxt().enter(|infcx| {
12441235
let ocx = ObligationCtxt::new(&infcx);
12451236

12461237
debug!("compare_type_predicate_entailment: caller_bounds={:?}", param_env.caller_bounds());
12471238

12481239
let mut selcx = traits::SelectionContext::new(&infcx);
12491240

1250-
for predicate in impl_ty_own_bounds.predicates {
1241+
assert_eq!(impl_ty_own_bounds.predicates.len(), impl_ty_own_bounds.spans.len());
1242+
for (span, predicate) in
1243+
std::iter::zip(impl_ty_own_bounds.spans, impl_ty_own_bounds.predicates)
1244+
{
1245+
let cause = ObligationCause::misc(span, impl_ty_hir_id);
12511246
let traits::Normalized { value: predicate, obligations } =
1252-
traits::normalize(&mut selcx, param_env, normalize_cause.clone(), predicate);
1247+
traits::normalize(&mut selcx, param_env, cause, predicate);
12531248

1249+
let cause = ObligationCause::new(
1250+
span,
1251+
impl_ty_hir_id,
1252+
ObligationCauseCode::CompareImplTypeObligation {
1253+
impl_item_def_id: impl_ty.def_id.expect_local(),
1254+
trait_item_def_id: trait_ty.def_id,
1255+
},
1256+
);
12541257
ocx.register_obligations(obligations);
1255-
ocx.register_obligation(traits::Obligation::new(cause.clone(), param_env, predicate));
1258+
ocx.register_obligation(traits::Obligation::new(cause, param_env, predicate));
12561259
}
12571260

12581261
// Check that all obligations are satisfied by the implementation's

src/test/ui/generic-associated-types/generic-associated-types-where.stderr

+2-2
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,13 @@ LL | type Assoc2<T: std::fmt::Display> = Vec<T>;
1111
| +++++++++++++++++++
1212

1313
error[E0276]: impl has stricter requirements than trait
14-
--> $DIR/generic-associated-types-where.rs:22:5
14+
--> $DIR/generic-associated-types-where.rs:22:38
1515
|
1616
LL | type Assoc3<T>;
1717
| -------------- definition of `Assoc3` from trait
1818
...
1919
LL | type Assoc3<T> = Vec<T> where T: Iterator;
20-
| ^^^^^^^^^^^^^^ impl has extra requirement `T: Iterator`
20+
| ^^^^^^^^ impl has extra requirement `T: Iterator`
2121

2222
error: aborting due to 2 previous errors
2323

src/test/ui/generic-associated-types/impl_bounds.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,9 @@ struct Fooy<T>(T);
1313

1414
impl<T> Foo for Fooy<T> {
1515
type A<'a> = (&'a ()) where Self: 'static;
16-
//~^ ERROR `impl` associated type
16+
//~^ ERROR the parameter type `T` may not live long enoug
1717
type B<'a, 'b> = (&'a(), &'b ()) where 'b: 'a;
18-
//~^ ERROR `impl` associated type
18+
//~^ ERROR impl has stricter requirements than trait
1919
//~| ERROR lifetime bound not satisfied
2020
type C = String where Self: Copy;
2121
//~^ ERROR the trait bound `T: Copy` is not satisfied

src/test/ui/generic-associated-types/impl_bounds.stderr

+16-14
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,22 @@
1-
error: `impl` associated type signature for `A` doesn't match `trait` associated type signature
2-
--> $DIR/impl_bounds.rs:15:5
1+
error[E0310]: the parameter type `T` may not live long enough
2+
--> $DIR/impl_bounds.rs:15:39
33
|
4-
LL | type A<'a> where Self: 'a;
5-
| ---------- expected
6-
...
74
LL | type A<'a> = (&'a ()) where Self: 'static;
8-
| ^^^^^^^^^^ found
5+
| ^^^^^^^ ...so that the definition in impl matches the definition from the trait
6+
|
7+
help: consider adding an explicit lifetime bound...
8+
|
9+
LL | impl<T: 'static> Foo for Fooy<T> {
10+
| +++++++++
911

10-
error: `impl` associated type signature for `B` doesn't match `trait` associated type signature
11-
--> $DIR/impl_bounds.rs:17:5
12+
error[E0276]: impl has stricter requirements than trait
13+
--> $DIR/impl_bounds.rs:17:48
1214
|
1315
LL | type B<'a, 'b> where 'a: 'b;
14-
| -------------- expected
16+
| -------------- definition of `B` from trait
1517
...
1618
LL | type B<'a, 'b> = (&'a(), &'b ()) where 'b: 'a;
17-
| ^^^^^^^^^^^^^^ found
19+
| ^^ impl has extra requirement `'b: 'a`
1820

1921
error[E0478]: lifetime bound not satisfied
2022
--> $DIR/impl_bounds.rs:17:22
@@ -37,10 +39,10 @@ LL | type B<'a, 'b> = (&'a(), &'b ()) where 'b: 'a;
3739
| ^^
3840

3941
error[E0277]: the trait bound `T: Copy` is not satisfied
40-
--> $DIR/impl_bounds.rs:20:5
42+
--> $DIR/impl_bounds.rs:20:33
4143
|
4244
LL | type C = String where Self: Copy;
43-
| ^^^^^^ the trait `Copy` is not implemented for `T`
45+
| ^^^^ the trait `Copy` is not implemented for `T`
4446
|
4547
note: required because of the requirements on the impl of `Copy` for `Fooy<T>`
4648
--> $DIR/impl_bounds.rs:11:10
@@ -88,5 +90,5 @@ LL | impl<T: std::marker::Copy> Foo for Fooy<T> {
8890

8991
error: aborting due to 5 previous errors
9092

91-
Some errors have detailed explanations: E0277, E0478.
92-
For more information about an error, try `rustc --explain E0277`.
93+
Some errors have detailed explanations: E0276, E0277, E0310, E0478.
94+
For more information about an error, try `rustc --explain E0276`.

src/test/ui/generic-associated-types/issue-47206-where-clause.stderr

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
error[E0276]: impl has stricter requirements than trait
2-
--> $DIR/issue-47206-where-clause.rs:12:5
2+
--> $DIR/issue-47206-where-clause.rs:12:38
33
|
44
LL | type Assoc3<T>;
55
| -------------- definition of `Assoc3` from trait
66
...
77
LL | type Assoc3<T> = Vec<T> where T: Iterator;
8-
| ^^^^^^^^^^^^^^ impl has extra requirement `T: Iterator`
8+
| ^^^^^^^^ impl has extra requirement `T: Iterator`
99

1010
error: aborting due to previous error
1111

src/test/ui/generic-associated-types/missing-where-clause-on-trait.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ trait Foo {
77
}
88
impl Foo for () {
99
type Assoc<'a, 'b> = () where 'a: 'b;
10-
//~^ `impl` associated type
10+
//~^ impl has stricter requirements than trait
1111
}
1212

1313
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
1-
error: `impl` associated type signature for `Assoc` doesn't match `trait` associated type signature
2-
--> $DIR/missing-where-clause-on-trait.rs:9:5
1+
error[E0276]: impl has stricter requirements than trait
2+
--> $DIR/missing-where-clause-on-trait.rs:9:39
33
|
44
LL | type Assoc<'a, 'b>;
5-
| ------------------ expected
5+
| ------------------ definition of `Assoc` from trait
66
...
77
LL | type Assoc<'a, 'b> = () where 'a: 'b;
8-
| ^^^^^^^^^^^^^^^^^^ found
8+
| ^^ impl has extra requirement `'a: 'b`
99

1010
error: aborting due to previous error
1111

12+
For more information about this error, try `rustc --explain E0276`.

0 commit comments

Comments
 (0)