Skip to content

Commit 6d4f27e

Browse files
authored
Rollup merge of #88336 - jackh726:gats-where-constraints, r=estebank
Detect stricter constraints on gats where clauses in impls vs trait I might try to see if I can do a bit more to improve these diagnostics, but any initial feedback is appreciated. I can also do any additional work in a followup PR. r? `@estebank`
2 parents 0212c70 + 890de33 commit 6d4f27e

File tree

8 files changed

+130
-47
lines changed

8 files changed

+130
-47
lines changed

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

+58-30
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
33
use crate::infer::error_reporting::nice_region_error::NiceRegionError;
44
use crate::infer::lexical_region_resolve::RegionResolutionError;
5-
use crate::infer::{Subtype, ValuePairs};
5+
use crate::infer::{SubregionOrigin, Subtype, ValuePairs};
66
use crate::traits::ObligationCauseCode::CompareImplMethodObligation;
77
use rustc_errors::ErrorReported;
88
use rustc_hir as hir;
@@ -11,44 +11,53 @@ use rustc_hir::def_id::DefId;
1111
use rustc_hir::intravisit::Visitor;
1212
use rustc_middle::ty::error::ExpectedFound;
1313
use rustc_middle::ty::{self, Ty, TyCtxt};
14-
use rustc_span::{MultiSpan, Span};
14+
use rustc_span::{MultiSpan, Span, Symbol};
1515

1616
impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
1717
/// Print the error message for lifetime errors when the `impl` doesn't conform to the `trait`.
1818
pub(super) fn try_report_impl_not_conforming_to_trait(&self) -> Option<ErrorReported> {
19-
if let Some(ref error) = self.error {
20-
debug!("try_report_impl_not_conforming_to_trait {:?}", error);
21-
if let RegionResolutionError::SubSupConflict(
22-
_,
23-
var_origin,
24-
sub_origin,
25-
_sub,
26-
sup_origin,
27-
_sup,
28-
) = error.clone()
29-
{
30-
if let (&Subtype(ref sup_trace), &Subtype(ref sub_trace)) =
31-
(&sup_origin, &sub_origin)
19+
let error = self.error.as_ref()?;
20+
debug!("try_report_impl_not_conforming_to_trait {:?}", error);
21+
if let RegionResolutionError::SubSupConflict(
22+
_,
23+
var_origin,
24+
sub_origin,
25+
_sub,
26+
sup_origin,
27+
_sup,
28+
) = error.clone()
29+
{
30+
if let (&Subtype(ref sup_trace), &Subtype(ref sub_trace)) = (&sup_origin, &sub_origin) {
31+
if let (
32+
ValuePairs::Types(sub_expected_found),
33+
ValuePairs::Types(sup_expected_found),
34+
CompareImplMethodObligation { trait_item_def_id, .. },
35+
) = (&sub_trace.values, &sup_trace.values, &sub_trace.cause.code)
3236
{
33-
if let (
34-
ValuePairs::Types(sub_expected_found),
35-
ValuePairs::Types(sup_expected_found),
36-
CompareImplMethodObligation { trait_item_def_id, .. },
37-
) = (&sub_trace.values, &sup_trace.values, &sub_trace.cause.code)
38-
{
39-
if sup_expected_found == sub_expected_found {
40-
self.emit_err(
41-
var_origin.span(),
42-
sub_expected_found.expected,
43-
sub_expected_found.found,
44-
*trait_item_def_id,
45-
);
46-
return Some(ErrorReported);
47-
}
37+
if sup_expected_found == sub_expected_found {
38+
self.emit_err(
39+
var_origin.span(),
40+
sub_expected_found.expected,
41+
sub_expected_found.found,
42+
*trait_item_def_id,
43+
);
44+
return Some(ErrorReported);
4845
}
4946
}
5047
}
5148
}
49+
if let RegionResolutionError::ConcreteFailure(origin, _, _) = error.clone() {
50+
if let SubregionOrigin::CompareImplTypeObligation {
51+
span,
52+
item_name,
53+
impl_item_def_id,
54+
trait_item_def_id,
55+
} = origin
56+
{
57+
self.emit_associated_type_err(span, item_name, impl_item_def_id, trait_item_def_id);
58+
return Some(ErrorReported);
59+
}
60+
}
5261
None
5362
}
5463

@@ -107,6 +116,25 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
107116
}
108117
err.emit();
109118
}
119+
120+
fn emit_associated_type_err(
121+
&self,
122+
span: Span,
123+
item_name: Symbol,
124+
impl_item_def_id: DefId,
125+
trait_item_def_id: DefId,
126+
) {
127+
let impl_sp = self.tcx().def_span(impl_item_def_id);
128+
let trait_sp = self.tcx().def_span(trait_item_def_id);
129+
let mut err = self
130+
.tcx()
131+
.sess
132+
.struct_span_err(span, &format!("`impl` associated type signature for `{}` doesn't match `trait` associated type signature", item_name));
133+
err.span_label(impl_sp, &format!("found"));
134+
err.span_label(trait_sp, &format!("expected"));
135+
136+
err.emit();
137+
}
110138
}
111139

112140
struct TypeParamSpanVisitor<'tcx> {

compiler/rustc_infer/src/infer/error_reporting/note.rs

+18
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,12 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
9999
"...so that the definition in impl matches the definition from the trait",
100100
);
101101
}
102+
infer::CompareImplTypeObligation { span, .. } => {
103+
label_or_note(
104+
span,
105+
"...so that the definition in impl matches the definition from the trait",
106+
);
107+
}
102108
}
103109
}
104110

@@ -356,6 +362,18 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
356362
trait_item_def_id,
357363
&format!("`{}: {}`", sup, sub),
358364
),
365+
infer::CompareImplTypeObligation {
366+
span,
367+
item_name,
368+
impl_item_def_id,
369+
trait_item_def_id,
370+
} => self.report_extra_impl_obligation(
371+
span,
372+
item_name,
373+
impl_item_def_id,
374+
trait_item_def_id,
375+
&format!("`{}: {}`", sup, sub),
376+
),
359377
}
360378
}
361379

compiler/rustc_infer/src/infer/mod.rs

+21
Original file line numberDiff line numberDiff line change
@@ -427,6 +427,15 @@ pub enum SubregionOrigin<'tcx> {
427427
impl_item_def_id: DefId,
428428
trait_item_def_id: DefId,
429429
},
430+
431+
/// Comparing the signature and requirements of an impl associated type
432+
/// against the containing trait
433+
CompareImplTypeObligation {
434+
span: Span,
435+
item_name: Symbol,
436+
impl_item_def_id: DefId,
437+
trait_item_def_id: DefId,
438+
},
430439
}
431440

432441
// `SubregionOrigin` is used a lot. Make sure it doesn't unintentionally get bigger.
@@ -1810,6 +1819,7 @@ impl<'tcx> SubregionOrigin<'tcx> {
18101819
ReferenceOutlivesReferent(_, a) => a,
18111820
CallReturn(a) => a,
18121821
CompareImplMethodObligation { span, .. } => span,
1822+
CompareImplTypeObligation { span, .. } => span,
18131823
}
18141824
}
18151825

@@ -1833,6 +1843,17 @@ impl<'tcx> SubregionOrigin<'tcx> {
18331843
trait_item_def_id,
18341844
},
18351845

1846+
traits::ObligationCauseCode::CompareImplTypeObligation {
1847+
item_name,
1848+
impl_item_def_id,
1849+
trait_item_def_id,
1850+
} => SubregionOrigin::CompareImplTypeObligation {
1851+
span: cause.span,
1852+
item_name,
1853+
impl_item_def_id,
1854+
trait_item_def_id,
1855+
},
1856+
18361857
_ => default(),
18371858
}
18381859
}

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

+1-1
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ impl<T> Foo for Fooy<T> {
1515
type A<'a> where Self: 'static = (&'a ());
1616
//~^ ERROR the parameter type `T` may not live long enough
1717
type B<'a, 'b> where 'b: 'a = (&'a(), &'b ());
18-
//~^ ERROR lifetime bound not satisfied
18+
//~^ ERROR `impl` associated type
1919
//~| ERROR lifetime bound not satisfied
2020
type C where Self: Copy = String;
2121
//~^ ERROR the trait bound `T: Copy` is not satisfied

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

+6-14
Original file line numberDiff line numberDiff line change
@@ -5,24 +5,16 @@ LL | type A<'a> where Self: 'static = (&'a ());
55
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
66
|
77
= help: consider adding an explicit lifetime bound `T: 'static`...
8-
= note: ...so that the type `Fooy<T>` will meet its required lifetime bounds
8+
= note: ...so that the definition in impl matches the definition from the trait
99

10-
error[E0478]: lifetime bound not satisfied
10+
error: `impl` associated type signature for `B` doesn't match `trait` associated type signature
1111
--> $DIR/impl_bounds.rs:17:5
1212
|
13+
LL | type B<'a, 'b> where 'a: 'b;
14+
| ---------------------------- expected
15+
...
1316
LL | type B<'a, 'b> where 'b: 'a = (&'a(), &'b ());
14-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
15-
|
16-
note: lifetime parameter instantiated with the lifetime `'b` as defined on the associated item at 17:16
17-
--> $DIR/impl_bounds.rs:17:16
18-
|
19-
LL | type B<'a, 'b> where 'b: 'a = (&'a(), &'b ());
20-
| ^^
21-
note: but lifetime parameter must outlive the lifetime `'a` as defined on the associated item at 17:12
22-
--> $DIR/impl_bounds.rs:17:12
23-
|
24-
LL | type B<'a, 'b> where 'b: 'a = (&'a(), &'b ());
25-
| ^^
17+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ found
2618

2719
error[E0478]: lifetime bound not satisfied
2820
--> $DIR/impl_bounds.rs:17:5

src/test/ui/generic-associated-types/issue-86787.stderr

+2-2
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ LL | | <Left as HasChildrenOf>::T: 'a,
99
LL | | <Right as HasChildrenOf>::T: 'a
1010
| | - help: consider adding a where clause: `, <Left as HasChildrenOf>::T: 'a`
1111
LL | | = Either<&'a Left::T, &'a Right::T>;
12-
| |________________________________________^ ...so that the type `<Left as HasChildrenOf>::T` will meet its required lifetime bounds
12+
| |________________________________________^ ...so that the definition in impl matches the definition from the trait
1313

1414
error[E0309]: the associated type `<Right as HasChildrenOf>::T` may not live long enough
1515
--> $DIR/issue-86787.rs:23:5
@@ -22,7 +22,7 @@ LL | | <Left as HasChildrenOf>::T: 'a,
2222
LL | | <Right as HasChildrenOf>::T: 'a
2323
| | - help: consider adding a where clause: `, <Right as HasChildrenOf>::T: 'a`
2424
LL | | = Either<&'a Left::T, &'a Right::T>;
25-
| |________________________________________^ ...so that the type `<Right as HasChildrenOf>::T` will meet its required lifetime bounds
25+
| |________________________________________^ ...so that the definition in impl matches the definition from the trait
2626

2727
error: aborting due to 2 previous errors
2828

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
// check-fail
2+
3+
#![feature(generic_associated_types)]
4+
5+
trait Foo {
6+
type Assoc<'a, 'b>;
7+
}
8+
impl Foo for () {
9+
type Assoc<'a, 'b> where 'a: 'b = ();
10+
//~^ `impl` associated type
11+
}
12+
13+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
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
3+
|
4+
LL | type Assoc<'a, 'b>;
5+
| ------------------- expected
6+
...
7+
LL | type Assoc<'a, 'b> where 'a: 'b = ();
8+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ found
9+
10+
error: aborting due to previous error
11+

0 commit comments

Comments
 (0)