mirror of https://github.com/rust-lang/rust.git
Rollup merge of #92683 - jackh726:issue-92033, r=estebank
Suggest copying trait associated type bounds on lifetime error Closes #92033 Kind of the most simple suggestion to make - we don't try to be fancy. Turns out, it's still pretty useful (the couple existing tests that trigger this error end up fixed - for this error - upon applying the fix). r? ``@estebank`` cc ``@nikomatsakis``
This commit is contained in:
commit
dd111262b2
|
@ -64,7 +64,7 @@ impl<'cx, 'tcx> NiceRegionError<'cx, 'tcx> {
|
||||||
.or_else(|| self.try_report_mismatched_static_lifetime())
|
.or_else(|| self.try_report_mismatched_static_lifetime())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn regions(&self) -> Option<(Span, ty::Region<'tcx>, ty::Region<'tcx>)> {
|
pub(super) fn regions(&self) -> Option<(Span, ty::Region<'tcx>, ty::Region<'tcx>)> {
|
||||||
match (&self.error, self.regions) {
|
match (&self.error, self.regions) {
|
||||||
(Some(ConcreteFailure(origin, sub, sup)), None) => Some((origin.span(), *sub, *sup)),
|
(Some(ConcreteFailure(origin, sub, sup)), None) => Some((origin.span(), *sub, *sup)),
|
||||||
(Some(SubSupConflict(_, _, origin, sub, _, sup, _)), None) => {
|
(Some(SubSupConflict(_, _, origin, sub, _, sup, _)), None) => {
|
||||||
|
|
|
@ -102,6 +102,9 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
||||||
"...so that the definition in impl matches the definition from the trait",
|
"...so that the definition in impl matches the definition from the trait",
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
infer::CheckAssociatedTypeBounds { ref parent, .. } => {
|
||||||
|
self.note_region_origin(err, &parent);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -345,6 +348,55 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
||||||
trait_item_def_id,
|
trait_item_def_id,
|
||||||
&format!("`{}: {}`", sup, sub),
|
&format!("`{}: {}`", sup, sub),
|
||||||
),
|
),
|
||||||
|
infer::CheckAssociatedTypeBounds { impl_item_def_id, trait_item_def_id, parent } => {
|
||||||
|
let mut err = self.report_concrete_failure(*parent, sub, sup);
|
||||||
|
|
||||||
|
let trait_item_span = self.tcx.def_span(trait_item_def_id);
|
||||||
|
let item_name = self.tcx.item_name(impl_item_def_id);
|
||||||
|
err.span_label(
|
||||||
|
trait_item_span,
|
||||||
|
format!("definition of `{}` from trait", item_name),
|
||||||
|
);
|
||||||
|
|
||||||
|
let trait_predicates = self.tcx.explicit_predicates_of(trait_item_def_id);
|
||||||
|
let impl_predicates = self.tcx.explicit_predicates_of(impl_item_def_id);
|
||||||
|
|
||||||
|
let impl_predicates: rustc_data_structures::stable_set::FxHashSet<_> =
|
||||||
|
impl_predicates.predicates.into_iter().map(|(pred, _)| pred).collect();
|
||||||
|
let clauses: Vec<_> = trait_predicates
|
||||||
|
.predicates
|
||||||
|
.into_iter()
|
||||||
|
.filter(|&(pred, _)| !impl_predicates.contains(pred))
|
||||||
|
.map(|(pred, _)| format!("{}", pred))
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
if !clauses.is_empty() {
|
||||||
|
let where_clause_span = self
|
||||||
|
.tcx
|
||||||
|
.hir()
|
||||||
|
.get_generics(impl_item_def_id.expect_local())
|
||||||
|
.unwrap()
|
||||||
|
.where_clause
|
||||||
|
.tail_span_for_suggestion();
|
||||||
|
|
||||||
|
let suggestion = format!(
|
||||||
|
"{} {}",
|
||||||
|
if !impl_predicates.is_empty() { "," } else { " where" },
|
||||||
|
clauses.join(", "),
|
||||||
|
);
|
||||||
|
err.span_suggestion(
|
||||||
|
where_clause_span,
|
||||||
|
&format!(
|
||||||
|
"try copying {} from the trait",
|
||||||
|
if clauses.len() > 1 { "these clauses" } else { "this clause" }
|
||||||
|
),
|
||||||
|
suggestion,
|
||||||
|
rustc_errors::Applicability::MaybeIncorrect,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -438,6 +438,13 @@ pub enum SubregionOrigin<'tcx> {
|
||||||
/// Comparing the signature and requirements of an impl associated type
|
/// Comparing the signature and requirements of an impl associated type
|
||||||
/// against the containing trait
|
/// against the containing trait
|
||||||
CompareImplTypeObligation { span: Span, impl_item_def_id: DefId, trait_item_def_id: DefId },
|
CompareImplTypeObligation { span: Span, impl_item_def_id: DefId, trait_item_def_id: DefId },
|
||||||
|
|
||||||
|
/// Checking that the bounds of a trait's associated type hold for a given impl
|
||||||
|
CheckAssociatedTypeBounds {
|
||||||
|
parent: Box<SubregionOrigin<'tcx>>,
|
||||||
|
impl_item_def_id: DefId,
|
||||||
|
trait_item_def_id: DefId,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
// `SubregionOrigin` is used a lot. Make sure it doesn't unintentionally get bigger.
|
// `SubregionOrigin` is used a lot. Make sure it doesn't unintentionally get bigger.
|
||||||
|
@ -1832,6 +1839,7 @@ impl<'tcx> SubregionOrigin<'tcx> {
|
||||||
ReferenceOutlivesReferent(_, a) => a,
|
ReferenceOutlivesReferent(_, a) => a,
|
||||||
CompareImplMethodObligation { span, .. } => span,
|
CompareImplMethodObligation { span, .. } => span,
|
||||||
CompareImplTypeObligation { span, .. } => span,
|
CompareImplTypeObligation { span, .. } => span,
|
||||||
|
CheckAssociatedTypeBounds { ref parent, .. } => parent.span(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1862,6 +1870,15 @@ impl<'tcx> SubregionOrigin<'tcx> {
|
||||||
trait_item_def_id,
|
trait_item_def_id,
|
||||||
},
|
},
|
||||||
|
|
||||||
|
traits::ObligationCauseCode::CheckAssociatedTypeBounds {
|
||||||
|
impl_item_def_id,
|
||||||
|
trait_item_def_id,
|
||||||
|
} => SubregionOrigin::CheckAssociatedTypeBounds {
|
||||||
|
impl_item_def_id,
|
||||||
|
trait_item_def_id,
|
||||||
|
parent: Box::new(default()),
|
||||||
|
},
|
||||||
|
|
||||||
_ => default(),
|
_ => default(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -285,6 +285,12 @@ pub enum ObligationCauseCode<'tcx> {
|
||||||
trait_item_def_id: DefId,
|
trait_item_def_id: DefId,
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/// Checking that the bounds of a trait's associated type hold for a given impl
|
||||||
|
CheckAssociatedTypeBounds {
|
||||||
|
impl_item_def_id: DefId,
|
||||||
|
trait_item_def_id: DefId,
|
||||||
|
},
|
||||||
|
|
||||||
/// Checking that this expression can be assigned where it needs to be
|
/// Checking that this expression can be assigned where it needs to be
|
||||||
// FIXME(eddyb) #11161 is the original Expr required?
|
// FIXME(eddyb) #11161 is the original Expr required?
|
||||||
ExprAssignable,
|
ExprAssignable,
|
||||||
|
|
|
@ -1928,7 +1928,8 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
|
||||||
| ObligationCauseCode::AwaitableExpr(_)
|
| ObligationCauseCode::AwaitableExpr(_)
|
||||||
| ObligationCauseCode::ForLoopIterator
|
| ObligationCauseCode::ForLoopIterator
|
||||||
| ObligationCauseCode::QuestionMark
|
| ObligationCauseCode::QuestionMark
|
||||||
| ObligationCauseCode::LetElse => {}
|
| ObligationCauseCode::LetElse
|
||||||
|
| ObligationCauseCode::CheckAssociatedTypeBounds { .. } => {}
|
||||||
ObligationCauseCode::SliceOrArrayElem => {
|
ObligationCauseCode::SliceOrArrayElem => {
|
||||||
err.note("slice and array elements must have `Sized` type");
|
err.note("slice and array elements must have `Sized` type");
|
||||||
}
|
}
|
||||||
|
|
|
@ -1378,7 +1378,14 @@ pub fn check_type_bounds<'tcx>(
|
||||||
let mut selcx = traits::SelectionContext::new(&infcx);
|
let mut selcx = traits::SelectionContext::new(&infcx);
|
||||||
|
|
||||||
let impl_ty_hir_id = tcx.hir().local_def_id_to_hir_id(impl_ty.def_id.expect_local());
|
let impl_ty_hir_id = tcx.hir().local_def_id_to_hir_id(impl_ty.def_id.expect_local());
|
||||||
let normalize_cause = traits::ObligationCause::misc(impl_ty_span, impl_ty_hir_id);
|
let normalize_cause = ObligationCause::new(
|
||||||
|
impl_ty_span,
|
||||||
|
impl_ty_hir_id,
|
||||||
|
ObligationCauseCode::CheckAssociatedTypeBounds {
|
||||||
|
impl_item_def_id: impl_ty.def_id,
|
||||||
|
trait_item_def_id: trait_ty.def_id,
|
||||||
|
},
|
||||||
|
);
|
||||||
let mk_cause = |span: Span| {
|
let mk_cause = |span: Span| {
|
||||||
let code = if span.is_dummy() {
|
let code = if span.is_dummy() {
|
||||||
traits::MiscObligation
|
traits::MiscObligation
|
||||||
|
|
|
@ -19,8 +19,13 @@ LL | type B<'a, 'b> where 'b: 'a = (&'a(), &'b ());
|
||||||
error[E0478]: lifetime bound not satisfied
|
error[E0478]: lifetime bound not satisfied
|
||||||
--> $DIR/impl_bounds.rs:17:35
|
--> $DIR/impl_bounds.rs:17:35
|
||||||
|
|
|
|
||||||
|
LL | type B<'a, 'b> where 'a: 'b;
|
||||||
|
| ---------------------------- definition of `B` from trait
|
||||||
|
...
|
||||||
LL | type B<'a, 'b> where 'b: 'a = (&'a(), &'b ());
|
LL | type B<'a, 'b> where 'b: 'a = (&'a(), &'b ());
|
||||||
| ^^^^^^^^^^^^^^^
|
| - ^^^^^^^^^^^^^^^
|
||||||
|
| |
|
||||||
|
| help: try copying this clause from the trait: `, 'a: 'b`
|
||||||
|
|
|
|
||||||
note: lifetime parameter instantiated with the lifetime `'a` as defined here
|
note: lifetime parameter instantiated with the lifetime `'a` as defined here
|
||||||
--> $DIR/impl_bounds.rs:17:12
|
--> $DIR/impl_bounds.rs:17:12
|
||||||
|
|
|
@ -8,7 +8,7 @@ trait A<'a> {
|
||||||
// FIXME(generic_associated_types): Remove one of the below bounds
|
// FIXME(generic_associated_types): Remove one of the below bounds
|
||||||
// https://github.com/rust-lang/rust/pull/90678#discussion_r744976085
|
// https://github.com/rust-lang/rust/pull/90678#discussion_r744976085
|
||||||
where
|
where
|
||||||
'a: 'b, Self: 'a, Self: 'b;
|
Self: 'a, Self: 'b;
|
||||||
|
|
||||||
fn a(&'a self) -> Self::B<'a>;
|
fn a(&'a self) -> Self::B<'a>;
|
||||||
}
|
}
|
||||||
|
@ -17,8 +17,7 @@ struct C;
|
||||||
|
|
||||||
impl<'a> A<'a> for C {
|
impl<'a> A<'a> for C {
|
||||||
type B<'b> = impl Clone;
|
type B<'b> = impl Clone;
|
||||||
//~^ ERROR: lifetime bound not satisfied
|
//~^ ERROR: could not find defining uses
|
||||||
//~| ERROR: could not find defining uses
|
|
||||||
|
|
||||||
fn a(&'a self) -> Self::B<'a> {} //~ ERROR: non-defining opaque type use in defining scope
|
fn a(&'a self) -> Self::B<'a> {} //~ ERROR: non-defining opaque type use in defining scope
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,22 +1,5 @@
|
||||||
error[E0478]: lifetime bound not satisfied
|
|
||||||
--> $DIR/issue-88595.rs:19:18
|
|
||||||
|
|
|
||||||
LL | type B<'b> = impl Clone;
|
|
||||||
| ^^^^^^^^^^
|
|
||||||
|
|
|
||||||
note: lifetime parameter instantiated with the lifetime `'a` as defined here
|
|
||||||
--> $DIR/issue-88595.rs:18:6
|
|
||||||
|
|
|
||||||
LL | impl<'a> A<'a> for C {
|
|
||||||
| ^^
|
|
||||||
note: but lifetime parameter must outlive the lifetime `'b` as defined here
|
|
||||||
--> $DIR/issue-88595.rs:19:12
|
|
||||||
|
|
|
||||||
LL | type B<'b> = impl Clone;
|
|
||||||
| ^^
|
|
||||||
|
|
||||||
error: non-defining opaque type use in defining scope
|
error: non-defining opaque type use in defining scope
|
||||||
--> $DIR/issue-88595.rs:23:23
|
--> $DIR/issue-88595.rs:22:23
|
||||||
|
|
|
|
||||||
LL | fn a(&'a self) -> Self::B<'a> {}
|
LL | fn a(&'a self) -> Self::B<'a> {}
|
||||||
| ^^^^^^^^^^^
|
| ^^^^^^^^^^^
|
||||||
|
@ -35,6 +18,5 @@ error: could not find defining uses
|
||||||
LL | type B<'b> = impl Clone;
|
LL | type B<'b> = impl Clone;
|
||||||
| ^^^^^^^^^^
|
| ^^^^^^^^^^
|
||||||
|
|
||||||
error: aborting due to 3 previous errors
|
error: aborting due to 2 previous errors
|
||||||
|
|
||||||
For more information about this error, try `rustc --explain E0478`.
|
|
||||||
|
|
|
@ -1,8 +1,13 @@
|
||||||
error[E0477]: the type `&mut ()` does not fulfill the required lifetime
|
error[E0477]: the type `&mut ()` does not fulfill the required lifetime
|
||||||
--> $DIR/issue-90014.rs:14:20
|
--> $DIR/issue-90014.rs:14:20
|
||||||
|
|
|
|
||||||
|
LL | type Fut<'a> where Self: 'a;
|
||||||
|
| ---------------------------- definition of `Fut` from trait
|
||||||
|
...
|
||||||
LL | type Fut<'a> = impl Future<Output = ()>;
|
LL | type Fut<'a> = impl Future<Output = ()>;
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
| - ^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
| |
|
||||||
|
| help: try copying this clause from the trait: `where Self: 'a`
|
||||||
|
|
|
|
||||||
note: type must outlive the lifetime `'a` as defined here
|
note: type must outlive the lifetime `'a` as defined here
|
||||||
--> $DIR/issue-90014.rs:14:14
|
--> $DIR/issue-90014.rs:14:14
|
||||||
|
|
|
@ -0,0 +1,39 @@
|
||||||
|
#![feature(generic_associated_types)]
|
||||||
|
|
||||||
|
struct Texture;
|
||||||
|
|
||||||
|
trait Surface {
|
||||||
|
type TextureIter<'a>: Iterator<Item = &'a Texture>
|
||||||
|
where
|
||||||
|
Self: 'a;
|
||||||
|
|
||||||
|
fn get_texture(&self) -> Self::TextureIter<'_>;
|
||||||
|
}
|
||||||
|
|
||||||
|
trait Swapchain {
|
||||||
|
type Surface<'a>: Surface
|
||||||
|
where
|
||||||
|
Self: 'a;
|
||||||
|
|
||||||
|
fn get_surface(&self) -> Self::Surface<'_>;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'s> Surface for &'s Texture {
|
||||||
|
type TextureIter<'a> = std::option::IntoIter<&'a Texture>;
|
||||||
|
//~^ ERROR the type
|
||||||
|
|
||||||
|
fn get_texture(&self) -> Self::TextureIter<'_> {
|
||||||
|
let option: Option<&Texture> = Some(self);
|
||||||
|
option.into_iter()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Swapchain for Texture {
|
||||||
|
type Surface<'a> = &'a Texture;
|
||||||
|
|
||||||
|
fn get_surface(&self) -> Self::Surface<'_> {
|
||||||
|
self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {}
|
|
@ -0,0 +1,22 @@
|
||||||
|
error[E0477]: the type `&'s Texture` does not fulfill the required lifetime
|
||||||
|
--> $DIR/issue-92033.rs:22:28
|
||||||
|
|
|
||||||
|
LL | / type TextureIter<'a>: Iterator<Item = &'a Texture>
|
||||||
|
LL | | where
|
||||||
|
LL | | Self: 'a;
|
||||||
|
| |_________________- definition of `TextureIter` from trait
|
||||||
|
...
|
||||||
|
LL | type TextureIter<'a> = std::option::IntoIter<&'a Texture>;
|
||||||
|
| - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
| |
|
||||||
|
| help: try copying this clause from the trait: `where Self: 'a`
|
||||||
|
|
|
||||||
|
note: type must outlive the lifetime `'a` as defined here
|
||||||
|
--> $DIR/issue-92033.rs:22:22
|
||||||
|
|
|
||||||
|
LL | type TextureIter<'a> = std::option::IntoIter<&'a Texture>;
|
||||||
|
| ^^
|
||||||
|
|
||||||
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0477`.
|
Loading…
Reference in New Issue