mirror of
https://github.com/rust-lang/rust.git
synced 2025-02-16 17:03:35 +00:00
Rollup merge of #82066 - matthewjasper:trait-ref-fix, r=jackh726
Ensure valid TraitRefs are created for GATs This fixes `ProjectionTy::trait_ref` to use the correct substs. Places that need all of the substs have been updated to not use `trait_ref`. r? ````@jackh726````
This commit is contained in:
commit
66211f6657
@ -914,6 +914,7 @@ impl<'a> State<'a> {
|
||||
|
||||
pub fn print_assoc_constraint(&mut self, constraint: &ast::AssocTyConstraint) {
|
||||
self.print_ident(constraint.ident);
|
||||
constraint.gen_args.as_ref().map(|args| self.print_generic_args(args, false));
|
||||
self.s.space();
|
||||
match &constraint.kind {
|
||||
ast::AssocTyConstraintKind::Equality { ty } => {
|
||||
|
@ -242,6 +242,7 @@ language_item_table! {
|
||||
|
||||
Deref, sym::deref, deref_trait, Target::Trait;
|
||||
DerefMut, sym::deref_mut, deref_mut_trait, Target::Trait;
|
||||
DerefTarget, sym::deref_target, deref_target, Target::AssocTy;
|
||||
Receiver, sym::receiver, receiver_trait, Target::Trait;
|
||||
|
||||
Fn, kw::Fn, fn_trait, Target::Trait;
|
||||
|
@ -55,6 +55,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
||||
|
||||
pub trait ToTrace<'tcx>: Relate<'tcx> + Copy {
|
||||
fn to_trace(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
cause: &ObligationCause<'tcx>,
|
||||
a_is_expected: bool,
|
||||
a: Self,
|
||||
@ -178,7 +179,7 @@ impl<'a, 'tcx> At<'a, 'tcx> {
|
||||
where
|
||||
T: ToTrace<'tcx>,
|
||||
{
|
||||
let trace = ToTrace::to_trace(self.cause, a_is_expected, a, b);
|
||||
let trace = ToTrace::to_trace(self.infcx.tcx, self.cause, a_is_expected, a, b);
|
||||
Trace { at: self, trace, a_is_expected }
|
||||
}
|
||||
}
|
||||
@ -251,6 +252,7 @@ impl<'a, 'tcx> Trace<'a, 'tcx> {
|
||||
|
||||
impl<'tcx> ToTrace<'tcx> for Ty<'tcx> {
|
||||
fn to_trace(
|
||||
_: TyCtxt<'tcx>,
|
||||
cause: &ObligationCause<'tcx>,
|
||||
a_is_expected: bool,
|
||||
a: Self,
|
||||
@ -262,6 +264,7 @@ impl<'tcx> ToTrace<'tcx> for Ty<'tcx> {
|
||||
|
||||
impl<'tcx> ToTrace<'tcx> for ty::Region<'tcx> {
|
||||
fn to_trace(
|
||||
_: TyCtxt<'tcx>,
|
||||
cause: &ObligationCause<'tcx>,
|
||||
a_is_expected: bool,
|
||||
a: Self,
|
||||
@ -273,6 +276,7 @@ impl<'tcx> ToTrace<'tcx> for ty::Region<'tcx> {
|
||||
|
||||
impl<'tcx> ToTrace<'tcx> for &'tcx Const<'tcx> {
|
||||
fn to_trace(
|
||||
_: TyCtxt<'tcx>,
|
||||
cause: &ObligationCause<'tcx>,
|
||||
a_is_expected: bool,
|
||||
a: Self,
|
||||
@ -284,6 +288,7 @@ impl<'tcx> ToTrace<'tcx> for &'tcx Const<'tcx> {
|
||||
|
||||
impl<'tcx> ToTrace<'tcx> for ty::TraitRef<'tcx> {
|
||||
fn to_trace(
|
||||
_: TyCtxt<'tcx>,
|
||||
cause: &ObligationCause<'tcx>,
|
||||
a_is_expected: bool,
|
||||
a: Self,
|
||||
@ -298,6 +303,7 @@ impl<'tcx> ToTrace<'tcx> for ty::TraitRef<'tcx> {
|
||||
|
||||
impl<'tcx> ToTrace<'tcx> for ty::PolyTraitRef<'tcx> {
|
||||
fn to_trace(
|
||||
_: TyCtxt<'tcx>,
|
||||
cause: &ObligationCause<'tcx>,
|
||||
a_is_expected: bool,
|
||||
a: Self,
|
||||
@ -309,3 +315,20 @@ impl<'tcx> ToTrace<'tcx> for ty::PolyTraitRef<'tcx> {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> ToTrace<'tcx> for ty::ProjectionTy<'tcx> {
|
||||
fn to_trace(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
cause: &ObligationCause<'tcx>,
|
||||
a_is_expected: bool,
|
||||
a: Self,
|
||||
b: Self,
|
||||
) -> TypeTrace<'tcx> {
|
||||
let a_ty = tcx.mk_projection(a.item_def_id, a.substs);
|
||||
let b_ty = tcx.mk_projection(b.item_def_id, b.substs);
|
||||
TypeTrace {
|
||||
cause: cause.clone(),
|
||||
values: Types(ExpectedFound::new(a_is_expected, a_ty, b_ty)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
use crate::traits::{ObligationCause, ObligationCauseCode};
|
||||
use crate::ty::diagnostics::suggest_constraining_type_param;
|
||||
use crate::ty::print::{FmtPrinter, Printer};
|
||||
use crate::ty::{self, BoundRegionKind, Region, Ty, TyCtxt};
|
||||
use rustc_errors::Applicability::{MachineApplicable, MaybeIncorrect};
|
||||
use rustc_errors::{pluralize, DiagnosticBuilder};
|
||||
@ -405,14 +406,22 @@ impl<'tcx> TyCtxt<'tcx> {
|
||||
{
|
||||
// Synthesize the associated type restriction `Add<Output = Expected>`.
|
||||
// FIXME: extract this logic for use in other diagnostics.
|
||||
let trait_ref = proj.trait_ref(self);
|
||||
let (trait_ref, assoc_substs) = proj.trait_ref_and_own_substs(self);
|
||||
let path =
|
||||
self.def_path_str_with_substs(trait_ref.def_id, trait_ref.substs);
|
||||
let item_name = self.item_name(proj.item_def_id);
|
||||
let item_args = self.format_generic_args(assoc_substs);
|
||||
|
||||
let path = if path.ends_with('>') {
|
||||
format!("{}, {} = {}>", &path[..path.len() - 1], item_name, p)
|
||||
format!(
|
||||
"{}, {}{} = {}>",
|
||||
&path[..path.len() - 1],
|
||||
item_name,
|
||||
item_args,
|
||||
p
|
||||
)
|
||||
} else {
|
||||
format!("{}<{} = {}>", path, item_name, p)
|
||||
format!("{}<{}{} = {}>", path, item_name, item_args, p)
|
||||
};
|
||||
note = !suggest_constraining_type_param(
|
||||
self,
|
||||
@ -561,7 +570,7 @@ impl<T> Trait<T> for X {
|
||||
ty: Ty<'tcx>,
|
||||
) -> bool {
|
||||
let assoc = self.associated_item(proj_ty.item_def_id);
|
||||
let trait_ref = proj_ty.trait_ref(self);
|
||||
let (trait_ref, assoc_substs) = proj_ty.trait_ref_and_own_substs(self);
|
||||
if let Some(item) = self.hir().get_if_local(body_owner_def_id) {
|
||||
if let Some(hir_generics) = item.generics() {
|
||||
// Get the `DefId` for the type parameter corresponding to `A` in `<A as T>::Foo`.
|
||||
@ -595,6 +604,7 @@ impl<T> Trait<T> for X {
|
||||
&trait_ref,
|
||||
pred.bounds,
|
||||
&assoc,
|
||||
assoc_substs,
|
||||
ty,
|
||||
msg,
|
||||
) {
|
||||
@ -612,6 +622,7 @@ impl<T> Trait<T> for X {
|
||||
&trait_ref,
|
||||
param.bounds,
|
||||
&assoc,
|
||||
assoc_substs,
|
||||
ty,
|
||||
msg,
|
||||
);
|
||||
@ -697,6 +708,7 @@ impl<T> Trait<T> for X {
|
||||
db,
|
||||
self.def_span(def_id),
|
||||
&assoc,
|
||||
proj_ty.trait_ref_and_own_substs(self).1,
|
||||
values.found,
|
||||
&msg,
|
||||
) {
|
||||
@ -861,6 +873,7 @@ fn foo(&self) -> Self::T { String::new() }
|
||||
trait_ref: &ty::TraitRef<'tcx>,
|
||||
bounds: hir::GenericBounds<'_>,
|
||||
assoc: &ty::AssocItem,
|
||||
assoc_substs: &[ty::GenericArg<'tcx>],
|
||||
ty: Ty<'tcx>,
|
||||
msg: &str,
|
||||
) -> bool {
|
||||
@ -870,7 +883,12 @@ fn foo(&self) -> Self::T { String::new() }
|
||||
// Relate the type param against `T` in `<A as T>::Foo`.
|
||||
ptr.trait_ref.trait_def_id() == Some(trait_ref.def_id)
|
||||
&& self.constrain_associated_type_structured_suggestion(
|
||||
db, ptr.span, assoc, ty, msg,
|
||||
db,
|
||||
ptr.span,
|
||||
assoc,
|
||||
assoc_substs,
|
||||
ty,
|
||||
msg,
|
||||
)
|
||||
}
|
||||
_ => false,
|
||||
@ -884,6 +902,7 @@ fn foo(&self) -> Self::T { String::new() }
|
||||
db: &mut DiagnosticBuilder<'_>,
|
||||
span: Span,
|
||||
assoc: &ty::AssocItem,
|
||||
assoc_substs: &[ty::GenericArg<'tcx>],
|
||||
ty: Ty<'tcx>,
|
||||
msg: &str,
|
||||
) -> bool {
|
||||
@ -895,11 +914,20 @@ fn foo(&self) -> Self::T { String::new() }
|
||||
let span = Span::new(pos, pos, span.ctxt());
|
||||
(span, format!(", {} = {}", assoc.ident, ty))
|
||||
} else {
|
||||
(span.shrink_to_hi(), format!("<{} = {}>", assoc.ident, ty))
|
||||
let item_args = self.format_generic_args(assoc_substs);
|
||||
(span.shrink_to_hi(), format!("<{}{} = {}>", assoc.ident, item_args, ty))
|
||||
};
|
||||
db.span_suggestion_verbose(span, msg, sugg, MaybeIncorrect);
|
||||
return true;
|
||||
}
|
||||
false
|
||||
}
|
||||
|
||||
fn format_generic_args(self, args: &[ty::GenericArg<'tcx>]) -> String {
|
||||
let mut item_args = String::new();
|
||||
FmtPrinter::new(self, &mut item_args, hir::def::Namespace::TypeNS)
|
||||
.path_generic_args(Ok, args)
|
||||
.expect("could not write to `String`.");
|
||||
item_args
|
||||
}
|
||||
}
|
||||
|
@ -1289,8 +1289,22 @@ impl<'tcx> PolyProjectionPredicate<'tcx> {
|
||||
self.skip_binder().projection_ty.item_def_id
|
||||
}
|
||||
|
||||
/// Returns the `DefId` of the trait of the associated item being projected.
|
||||
#[inline]
|
||||
pub fn to_poly_trait_ref(&self, tcx: TyCtxt<'tcx>) -> PolyTraitRef<'tcx> {
|
||||
pub fn trait_def_id(&self, tcx: TyCtxt<'tcx>) -> DefId {
|
||||
self.skip_binder().projection_ty.trait_def_id(tcx)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn projection_self_ty(&self) -> Binder<Ty<'tcx>> {
|
||||
self.map_bound(|predicate| predicate.projection_ty.self_ty())
|
||||
}
|
||||
|
||||
/// Get the [PolyTraitRef] required for this projection to be well formed.
|
||||
/// Note that for generic associated types the predicates of the associated
|
||||
/// type also need to be checked.
|
||||
#[inline]
|
||||
pub fn required_poly_trait_ref(&self, tcx: TyCtxt<'tcx>) -> PolyTraitRef<'tcx> {
|
||||
// Note: unlike with `TraitRef::to_poly_trait_ref()`,
|
||||
// `self.0.trait_ref` is permitted to have escaping regions.
|
||||
// This is because here `self` has a `Binder` and so does our
|
||||
|
@ -17,7 +17,7 @@ use rustc_hir as hir;
|
||||
use rustc_hir::def_id::DefId;
|
||||
use rustc_index::vec::Idx;
|
||||
use rustc_macros::HashStable;
|
||||
use rustc_span::symbol::{kw, Ident, Symbol};
|
||||
use rustc_span::symbol::{kw, Symbol};
|
||||
use rustc_target::abi::VariantIdx;
|
||||
use rustc_target::spec::abi;
|
||||
use std::borrow::Cow;
|
||||
@ -1112,36 +1112,35 @@ pub struct ProjectionTy<'tcx> {
|
||||
}
|
||||
|
||||
impl<'tcx> ProjectionTy<'tcx> {
|
||||
/// Construct a `ProjectionTy` by searching the trait from `trait_ref` for the
|
||||
/// associated item named `item_name`.
|
||||
pub fn from_ref_and_name(
|
||||
tcx: TyCtxt<'_>,
|
||||
trait_ref: ty::TraitRef<'tcx>,
|
||||
item_name: Ident,
|
||||
) -> ProjectionTy<'tcx> {
|
||||
let item_def_id = tcx
|
||||
.associated_items(trait_ref.def_id)
|
||||
.find_by_name_and_kind(tcx, item_name, ty::AssocKind::Type, trait_ref.def_id)
|
||||
.unwrap()
|
||||
.def_id;
|
||||
pub fn trait_def_id(&self, tcx: TyCtxt<'tcx>) -> DefId {
|
||||
tcx.associated_item(self.item_def_id).container.id()
|
||||
}
|
||||
|
||||
ProjectionTy { substs: trait_ref.substs, item_def_id }
|
||||
/// Extracts the underlying trait reference and own substs from this projection.
|
||||
/// For example, if this is a projection of `<T as StreamingIterator>::Item<'a>`,
|
||||
/// then this function would return a `T: Iterator` trait reference and `['a]` as the own substs
|
||||
pub fn trait_ref_and_own_substs(
|
||||
&self,
|
||||
tcx: TyCtxt<'tcx>,
|
||||
) -> (ty::TraitRef<'tcx>, &'tcx [ty::GenericArg<'tcx>]) {
|
||||
let def_id = tcx.associated_item(self.item_def_id).container.id();
|
||||
let trait_generics = tcx.generics_of(def_id);
|
||||
(
|
||||
ty::TraitRef { def_id, substs: self.substs.truncate_to(tcx, trait_generics) },
|
||||
&self.substs[trait_generics.count()..],
|
||||
)
|
||||
}
|
||||
|
||||
/// Extracts the underlying trait reference from this projection.
|
||||
/// For example, if this is a projection of `<T as Iterator>::Item`,
|
||||
/// then this function would return a `T: Iterator` trait reference.
|
||||
///
|
||||
/// WARNING: This will drop the substs for generic associated types
|
||||
/// consider calling [Self::trait_ref_and_own_substs] to get those
|
||||
/// as well.
|
||||
pub fn trait_ref(&self, tcx: TyCtxt<'tcx>) -> ty::TraitRef<'tcx> {
|
||||
// FIXME: This method probably shouldn't exist at all, since it's not
|
||||
// clear what this method really intends to do. Be careful when
|
||||
// using this method since the resulting TraitRef additionally
|
||||
// contains the substs for the assoc_item, which strictly speaking
|
||||
// is not correct
|
||||
let def_id = tcx.associated_item(self.item_def_id).container.id();
|
||||
// Include substitutions for generic arguments of associated types
|
||||
let assoc_item = tcx.associated_item(self.item_def_id);
|
||||
let substs_assoc_item = self.substs.truncate_to(tcx, tcx.generics_of(assoc_item.def_id));
|
||||
ty::TraitRef { def_id, substs: substs_assoc_item }
|
||||
let def_id = self.trait_def_id(tcx);
|
||||
ty::TraitRef { def_id, substs: self.substs.truncate_to(tcx, tcx.generics_of(def_id)) }
|
||||
}
|
||||
|
||||
pub fn self_ty(&self) -> Ty<'tcx> {
|
||||
@ -1493,12 +1492,11 @@ impl<'tcx> ExistentialProjection<'tcx> {
|
||||
/// For example, if this is a projection of `exists T. <T as Iterator>::Item == X`,
|
||||
/// then this function would return a `exists T. T: Iterator` existential trait
|
||||
/// reference.
|
||||
pub fn trait_ref(&self, tcx: TyCtxt<'_>) -> ty::ExistentialTraitRef<'tcx> {
|
||||
// FIXME(generic_associated_types): substs is the substs of the
|
||||
// associated type, which should be truncated to get the correct substs
|
||||
// for the trait.
|
||||
pub fn trait_ref(&self, tcx: TyCtxt<'tcx>) -> ty::ExistentialTraitRef<'tcx> {
|
||||
let def_id = tcx.associated_item(self.item_def_id).container.id();
|
||||
ty::ExistentialTraitRef { def_id, substs: self.substs }
|
||||
let subst_count = tcx.generics_of(def_id).count() - 1;
|
||||
let substs = tcx.intern_substs(&self.substs[..subst_count]);
|
||||
ty::ExistentialTraitRef { def_id, substs }
|
||||
}
|
||||
|
||||
pub fn with_self_ty(
|
||||
@ -1517,6 +1515,20 @@ impl<'tcx> ExistentialProjection<'tcx> {
|
||||
ty: self.ty,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn erase_self_ty(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
projection_predicate: ty::ProjectionPredicate<'tcx>,
|
||||
) -> Self {
|
||||
// Assert there is a Self.
|
||||
projection_predicate.projection_ty.substs.type_at(0);
|
||||
|
||||
Self {
|
||||
item_def_id: projection_predicate.projection_ty.item_def_id,
|
||||
substs: tcx.intern_substs(&projection_predicate.projection_ty.substs[1..]),
|
||||
ty: projection_predicate.ty,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> PolyExistentialProjection<'tcx> {
|
||||
|
@ -77,6 +77,12 @@ trait DefIdVisitor<'tcx> {
|
||||
fn visit_trait(&mut self, trait_ref: TraitRef<'tcx>) -> ControlFlow<Self::BreakTy> {
|
||||
self.skeleton().visit_trait(trait_ref)
|
||||
}
|
||||
fn visit_projection_ty(
|
||||
&mut self,
|
||||
projection: ty::ProjectionTy<'tcx>,
|
||||
) -> ControlFlow<Self::BreakTy> {
|
||||
self.skeleton().visit_projection_ty(projection)
|
||||
}
|
||||
fn visit_predicates(
|
||||
&mut self,
|
||||
predicates: ty::GenericPredicates<'tcx>,
|
||||
@ -101,6 +107,20 @@ where
|
||||
if self.def_id_visitor.shallow() { ControlFlow::CONTINUE } else { substs.visit_with(self) }
|
||||
}
|
||||
|
||||
fn visit_projection_ty(
|
||||
&mut self,
|
||||
projection: ty::ProjectionTy<'tcx>,
|
||||
) -> ControlFlow<V::BreakTy> {
|
||||
let (trait_ref, assoc_substs) =
|
||||
projection.trait_ref_and_own_substs(self.def_id_visitor.tcx());
|
||||
self.visit_trait(trait_ref)?;
|
||||
if self.def_id_visitor.shallow() {
|
||||
ControlFlow::CONTINUE
|
||||
} else {
|
||||
assoc_substs.iter().try_for_each(|subst| subst.visit_with(self))
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_predicate(&mut self, predicate: ty::Predicate<'tcx>) -> ControlFlow<V::BreakTy> {
|
||||
match predicate.kind().skip_binder() {
|
||||
ty::PredicateKind::Trait(ty::TraitPredicate { trait_ref }, _) => {
|
||||
@ -108,7 +128,7 @@ where
|
||||
}
|
||||
ty::PredicateKind::Projection(ty::ProjectionPredicate { projection_ty, ty }) => {
|
||||
ty.visit_with(self)?;
|
||||
self.visit_trait(projection_ty.trait_ref(self.def_id_visitor.tcx()))
|
||||
self.visit_projection_ty(projection_ty)
|
||||
}
|
||||
ty::PredicateKind::TypeOutlives(ty::OutlivesPredicate(ty, _region)) => {
|
||||
ty.visit_with(self)
|
||||
@ -197,7 +217,7 @@ where
|
||||
return ControlFlow::CONTINUE;
|
||||
}
|
||||
// This will also visit substs if necessary, so we don't need to recurse.
|
||||
return self.visit_trait(proj.trait_ref(tcx));
|
||||
return self.visit_projection_ty(proj);
|
||||
}
|
||||
ty::Dynamic(predicates, ..) => {
|
||||
// All traits in the list are considered the "primary" part of the type
|
||||
@ -1203,10 +1223,9 @@ impl<'tcx> Visitor<'tcx> for TypePrivacyVisitor<'tcx> {
|
||||
}
|
||||
|
||||
for (poly_predicate, _) in bounds.projection_bounds {
|
||||
let tcx = self.tcx;
|
||||
if self.visit(poly_predicate.skip_binder().ty).is_break()
|
||||
|| self
|
||||
.visit_trait(poly_predicate.skip_binder().projection_ty.trait_ref(tcx))
|
||||
.visit_projection_ty(poly_predicate.skip_binder().projection_ty)
|
||||
.is_break()
|
||||
{
|
||||
return;
|
||||
|
@ -6,7 +6,6 @@ use rustc_infer::infer::InferCtxt;
|
||||
use rustc_middle::ty::{self, TraitRef, Ty, TyCtxt, WithConstness};
|
||||
use rustc_middle::ty::{ToPredicate, TypeFoldable};
|
||||
use rustc_session::DiagnosticMessageId;
|
||||
use rustc_span::symbol::{sym, Ident};
|
||||
use rustc_span::Span;
|
||||
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
@ -146,11 +145,10 @@ impl<'a, 'tcx> Autoderef<'a, 'tcx> {
|
||||
let normalized_ty = fulfillcx.normalize_projection_type(
|
||||
&self.infcx,
|
||||
self.param_env,
|
||||
ty::ProjectionTy::from_ref_and_name(
|
||||
tcx,
|
||||
trait_ref,
|
||||
Ident::with_dummy_span(sym::Target),
|
||||
),
|
||||
ty::ProjectionTy {
|
||||
item_def_id: tcx.lang_items().deref_target()?,
|
||||
substs: trait_ref.substs,
|
||||
},
|
||||
cause,
|
||||
);
|
||||
if let Err(e) = fulfillcx.select_where_possible(&self.infcx) {
|
||||
|
@ -1589,8 +1589,7 @@ impl<'a, 'tcx> InferCtxtPrivExt<'tcx> for InferCtxt<'a, 'tcx> {
|
||||
self.emit_inference_failure_err(body_id, span, a.into(), vec![], ErrorCode::E0282)
|
||||
}
|
||||
ty::PredicateKind::Projection(data) => {
|
||||
let trait_ref = bound_predicate.rebind(data).to_poly_trait_ref(self.tcx);
|
||||
let self_ty = trait_ref.skip_binder().self_ty();
|
||||
let self_ty = data.projection_ty.self_ty();
|
||||
let ty = data.ty;
|
||||
if predicate.references_error() {
|
||||
return;
|
||||
|
@ -6,6 +6,7 @@ use rustc_errors::ErrorReported;
|
||||
use rustc_infer::traits::{TraitEngine, TraitEngineExt as _, TraitObligation};
|
||||
use rustc_middle::mir::interpret::ErrorHandled;
|
||||
use rustc_middle::ty::error::ExpectedFound;
|
||||
use rustc_middle::ty::subst::SubstsRef;
|
||||
use rustc_middle::ty::ToPredicate;
|
||||
use rustc_middle::ty::{self, Binder, Const, Ty, TypeFoldable};
|
||||
use std::marker::PhantomData;
|
||||
@ -633,9 +634,9 @@ impl<'a, 'b, 'tcx> FulfillProcessor<'a, 'b, 'tcx> {
|
||||
// only reason we can fail to make progress on
|
||||
// trait selection is because we don't have enough
|
||||
// information about the types in the trait.
|
||||
*stalled_on = trait_ref_infer_vars(
|
||||
*stalled_on = substs_infer_vars(
|
||||
self.selcx,
|
||||
trait_obligation.predicate.map_bound(|pred| pred.trait_ref),
|
||||
trait_obligation.predicate.map_bound(|pred| pred.trait_ref.substs),
|
||||
);
|
||||
|
||||
debug!(
|
||||
@ -663,9 +664,9 @@ impl<'a, 'b, 'tcx> FulfillProcessor<'a, 'b, 'tcx> {
|
||||
match project::poly_project_and_unify_type(self.selcx, &project_obligation) {
|
||||
Ok(Ok(Some(os))) => ProcessResult::Changed(mk_pending(os)),
|
||||
Ok(Ok(None)) => {
|
||||
*stalled_on = trait_ref_infer_vars(
|
||||
*stalled_on = substs_infer_vars(
|
||||
self.selcx,
|
||||
project_obligation.predicate.to_poly_trait_ref(tcx),
|
||||
project_obligation.predicate.map_bound(|pred| pred.projection_ty.substs),
|
||||
);
|
||||
ProcessResult::Unchanged
|
||||
}
|
||||
@ -678,16 +679,15 @@ impl<'a, 'b, 'tcx> FulfillProcessor<'a, 'b, 'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the set of inference variables contained in a trait ref.
|
||||
fn trait_ref_infer_vars<'a, 'tcx>(
|
||||
/// Returns the set of inference variables contained in `substs`.
|
||||
fn substs_infer_vars<'a, 'tcx>(
|
||||
selcx: &mut SelectionContext<'a, 'tcx>,
|
||||
trait_ref: ty::PolyTraitRef<'tcx>,
|
||||
substs: ty::Binder<SubstsRef<'tcx>>,
|
||||
) -> Vec<TyOrConstInferVar<'tcx>> {
|
||||
selcx
|
||||
.infcx()
|
||||
.resolve_vars_if_possible(trait_ref)
|
||||
.skip_binder()
|
||||
.substs
|
||||
.resolve_vars_if_possible(substs)
|
||||
.skip_binder() // ok because this check doesn't care about regions
|
||||
.iter()
|
||||
// FIXME(eddyb) try using `skip_current_subtree` to skip everything that
|
||||
// doesn't contain inference variables, not just the outermost level.
|
||||
|
@ -292,11 +292,7 @@ fn predicate_references_self(
|
||||
//
|
||||
// This is ALT2 in issue #56288, see that for discussion of the
|
||||
// possible alternatives.
|
||||
if data.projection_ty.trait_ref(tcx).substs[1..].iter().any(has_self_ty) {
|
||||
Some(sp)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
if data.projection_ty.substs[1..].iter().any(has_self_ty) { Some(sp) } else { None }
|
||||
}
|
||||
ty::PredicateKind::WellFormed(..)
|
||||
| ty::PredicateKind::ObjectSafe(..)
|
||||
|
@ -741,11 +741,7 @@ fn project_type<'cx, 'tcx>(
|
||||
return Err(ProjectionTyError::TraitSelectionError(SelectionError::Overflow));
|
||||
}
|
||||
|
||||
let obligation_trait_ref = &obligation.predicate.trait_ref(selcx.tcx());
|
||||
|
||||
debug!(?obligation_trait_ref);
|
||||
|
||||
if obligation_trait_ref.references_error() {
|
||||
if obligation.predicate.references_error() {
|
||||
return Ok(ProjectedTy::Progress(Progress::error(selcx.tcx())));
|
||||
}
|
||||
|
||||
@ -754,19 +750,19 @@ fn project_type<'cx, 'tcx>(
|
||||
// Make sure that the following procedures are kept in order. ParamEnv
|
||||
// needs to be first because it has highest priority, and Select checks
|
||||
// the return value of push_candidate which assumes it's ran at last.
|
||||
assemble_candidates_from_param_env(selcx, obligation, &obligation_trait_ref, &mut candidates);
|
||||
assemble_candidates_from_param_env(selcx, obligation, &mut candidates);
|
||||
|
||||
assemble_candidates_from_trait_def(selcx, obligation, &obligation_trait_ref, &mut candidates);
|
||||
assemble_candidates_from_trait_def(selcx, obligation, &mut candidates);
|
||||
|
||||
assemble_candidates_from_object_ty(selcx, obligation, &obligation_trait_ref, &mut candidates);
|
||||
assemble_candidates_from_object_ty(selcx, obligation, &mut candidates);
|
||||
|
||||
if let ProjectionTyCandidateSet::Single(ProjectionTyCandidate::Object(_)) = candidates {
|
||||
// Avoid normalization cycle from selection (see
|
||||
// `assemble_candidates_from_object_ty`).
|
||||
// FIXME(lazy_normalization): Lazy normalization should save us from
|
||||
// having to do special case this.
|
||||
// having to special case this.
|
||||
} else {
|
||||
assemble_candidates_from_impls(selcx, obligation, &obligation_trait_ref, &mut candidates);
|
||||
assemble_candidates_from_impls(selcx, obligation, &mut candidates);
|
||||
};
|
||||
|
||||
match candidates {
|
||||
@ -792,14 +788,12 @@ fn project_type<'cx, 'tcx>(
|
||||
fn assemble_candidates_from_param_env<'cx, 'tcx>(
|
||||
selcx: &mut SelectionContext<'cx, 'tcx>,
|
||||
obligation: &ProjectionTyObligation<'tcx>,
|
||||
obligation_trait_ref: &ty::TraitRef<'tcx>,
|
||||
candidate_set: &mut ProjectionTyCandidateSet<'tcx>,
|
||||
) {
|
||||
debug!("assemble_candidates_from_param_env(..)");
|
||||
assemble_candidates_from_predicates(
|
||||
selcx,
|
||||
obligation,
|
||||
obligation_trait_ref,
|
||||
candidate_set,
|
||||
ProjectionTyCandidate::ParamEnv,
|
||||
obligation.param_env.caller_bounds().iter(),
|
||||
@ -820,7 +814,6 @@ fn assemble_candidates_from_param_env<'cx, 'tcx>(
|
||||
fn assemble_candidates_from_trait_def<'cx, 'tcx>(
|
||||
selcx: &mut SelectionContext<'cx, 'tcx>,
|
||||
obligation: &ProjectionTyObligation<'tcx>,
|
||||
obligation_trait_ref: &ty::TraitRef<'tcx>,
|
||||
candidate_set: &mut ProjectionTyCandidateSet<'tcx>,
|
||||
) {
|
||||
debug!("assemble_candidates_from_trait_def(..)");
|
||||
@ -828,7 +821,7 @@ fn assemble_candidates_from_trait_def<'cx, 'tcx>(
|
||||
let tcx = selcx.tcx();
|
||||
// Check whether the self-type is itself a projection.
|
||||
// If so, extract what we know from the trait and try to come up with a good answer.
|
||||
let bounds = match *obligation_trait_ref.self_ty().kind() {
|
||||
let bounds = match *obligation.predicate.self_ty().kind() {
|
||||
ty::Projection(ref data) => tcx.item_bounds(data.item_def_id).subst(tcx, data.substs),
|
||||
ty::Opaque(def_id, substs) => tcx.item_bounds(def_id).subst(tcx, substs),
|
||||
ty::Infer(ty::TyVar(_)) => {
|
||||
@ -843,7 +836,6 @@ fn assemble_candidates_from_trait_def<'cx, 'tcx>(
|
||||
assemble_candidates_from_predicates(
|
||||
selcx,
|
||||
obligation,
|
||||
obligation_trait_ref,
|
||||
candidate_set,
|
||||
ProjectionTyCandidate::TraitDef,
|
||||
bounds.iter(),
|
||||
@ -863,14 +855,13 @@ fn assemble_candidates_from_trait_def<'cx, 'tcx>(
|
||||
fn assemble_candidates_from_object_ty<'cx, 'tcx>(
|
||||
selcx: &mut SelectionContext<'cx, 'tcx>,
|
||||
obligation: &ProjectionTyObligation<'tcx>,
|
||||
obligation_trait_ref: &ty::TraitRef<'tcx>,
|
||||
candidate_set: &mut ProjectionTyCandidateSet<'tcx>,
|
||||
) {
|
||||
debug!("assemble_candidates_from_object_ty(..)");
|
||||
|
||||
let tcx = selcx.tcx();
|
||||
|
||||
let self_ty = obligation_trait_ref.self_ty();
|
||||
let self_ty = obligation.predicate.self_ty();
|
||||
let object_ty = selcx.infcx().shallow_resolve(self_ty);
|
||||
let data = match object_ty.kind() {
|
||||
ty::Dynamic(data, ..) => data,
|
||||
@ -890,7 +881,6 @@ fn assemble_candidates_from_object_ty<'cx, 'tcx>(
|
||||
assemble_candidates_from_predicates(
|
||||
selcx,
|
||||
obligation,
|
||||
obligation_trait_ref,
|
||||
candidate_set,
|
||||
ProjectionTyCandidate::Object,
|
||||
env_predicates,
|
||||
@ -901,7 +891,6 @@ fn assemble_candidates_from_object_ty<'cx, 'tcx>(
|
||||
fn assemble_candidates_from_predicates<'cx, 'tcx>(
|
||||
selcx: &mut SelectionContext<'cx, 'tcx>,
|
||||
obligation: &ProjectionTyObligation<'tcx>,
|
||||
obligation_trait_ref: &ty::TraitRef<'tcx>,
|
||||
candidate_set: &mut ProjectionTyCandidateSet<'tcx>,
|
||||
ctor: fn(ty::PolyProjectionPredicate<'tcx>) -> ProjectionTyCandidate<'tcx>,
|
||||
env_predicates: impl Iterator<Item = ty::Predicate<'tcx>>,
|
||||
@ -921,8 +910,7 @@ fn assemble_candidates_from_predicates<'cx, 'tcx>(
|
||||
&& infcx.probe(|_| {
|
||||
selcx.match_projection_projections(
|
||||
obligation,
|
||||
obligation_trait_ref,
|
||||
&data,
|
||||
data,
|
||||
potentially_unnormalized_candidates,
|
||||
)
|
||||
});
|
||||
@ -948,14 +936,13 @@ fn assemble_candidates_from_predicates<'cx, 'tcx>(
|
||||
fn assemble_candidates_from_impls<'cx, 'tcx>(
|
||||
selcx: &mut SelectionContext<'cx, 'tcx>,
|
||||
obligation: &ProjectionTyObligation<'tcx>,
|
||||
obligation_trait_ref: &ty::TraitRef<'tcx>,
|
||||
candidate_set: &mut ProjectionTyCandidateSet<'tcx>,
|
||||
) {
|
||||
debug!("assemble_candidates_from_impls");
|
||||
|
||||
// If we are resolving `<T as TraitRef<...>>::Item == Type`,
|
||||
// start out by selecting the predicate `T as TraitRef<...>`:
|
||||
let poly_trait_ref = ty::Binder::dummy(*obligation_trait_ref);
|
||||
let poly_trait_ref = obligation.predicate.trait_ref(selcx.tcx()).to_poly_trait_ref();
|
||||
let trait_obligation = obligation.with(poly_trait_ref.to_poly_trait_predicate());
|
||||
let _ = selcx.infcx().commit_if_ok(|_| {
|
||||
let impl_source = match selcx.select(&trait_obligation) {
|
||||
@ -1410,25 +1397,25 @@ fn confirm_param_env_candidate<'cx, 'tcx>(
|
||||
poly_cache_entry,
|
||||
);
|
||||
|
||||
let cache_trait_ref = cache_entry.projection_ty.trait_ref(infcx.tcx);
|
||||
let obligation_trait_ref = obligation.predicate.trait_ref(infcx.tcx);
|
||||
let cache_projection = cache_entry.projection_ty;
|
||||
let obligation_projection = obligation.predicate;
|
||||
let mut nested_obligations = Vec::new();
|
||||
let cache_trait_ref = if potentially_unnormalized_candidate {
|
||||
let cache_projection = if potentially_unnormalized_candidate {
|
||||
ensure_sufficient_stack(|| {
|
||||
normalize_with_depth_to(
|
||||
selcx,
|
||||
obligation.param_env,
|
||||
obligation.cause.clone(),
|
||||
obligation.recursion_depth + 1,
|
||||
cache_trait_ref,
|
||||
cache_projection,
|
||||
&mut nested_obligations,
|
||||
)
|
||||
})
|
||||
} else {
|
||||
cache_trait_ref
|
||||
cache_projection
|
||||
};
|
||||
|
||||
match infcx.at(cause, param_env).eq(cache_trait_ref, obligation_trait_ref) {
|
||||
match infcx.at(cause, param_env).eq(cache_projection, obligation_projection) {
|
||||
Ok(InferOk { value: _, obligations }) => {
|
||||
nested_obligations.extend(obligations);
|
||||
assoc_ty_own_obligations(selcx, obligation, &mut nested_obligations);
|
||||
|
@ -32,6 +32,7 @@ use rustc_errors::ErrorReported;
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::def_id::DefId;
|
||||
use rustc_hir::Constness;
|
||||
use rustc_infer::infer::LateBoundRegionConversionTime;
|
||||
use rustc_middle::dep_graph::{DepKind, DepNodeIndex};
|
||||
use rustc_middle::mir::interpret::ErrorHandled;
|
||||
use rustc_middle::ty::fast_reject;
|
||||
@ -1254,32 +1255,33 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||
pub(super) fn match_projection_projections(
|
||||
&mut self,
|
||||
obligation: &ProjectionTyObligation<'tcx>,
|
||||
obligation_trait_ref: &ty::TraitRef<'tcx>,
|
||||
data: &PolyProjectionPredicate<'tcx>,
|
||||
env_predicate: PolyProjectionPredicate<'tcx>,
|
||||
potentially_unnormalized_candidates: bool,
|
||||
) -> bool {
|
||||
let mut nested_obligations = Vec::new();
|
||||
let projection_ty = if potentially_unnormalized_candidates {
|
||||
let (infer_predicate, _) = self.infcx.replace_bound_vars_with_fresh_vars(
|
||||
obligation.cause.span,
|
||||
LateBoundRegionConversionTime::HigherRankedType,
|
||||
env_predicate,
|
||||
);
|
||||
let infer_projection = if potentially_unnormalized_candidates {
|
||||
ensure_sufficient_stack(|| {
|
||||
project::normalize_with_depth_to(
|
||||
self,
|
||||
obligation.param_env,
|
||||
obligation.cause.clone(),
|
||||
obligation.recursion_depth + 1,
|
||||
data.map_bound(|data| data.projection_ty),
|
||||
infer_predicate.projection_ty,
|
||||
&mut nested_obligations,
|
||||
)
|
||||
})
|
||||
} else {
|
||||
data.map_bound(|data| data.projection_ty)
|
||||
infer_predicate.projection_ty
|
||||
};
|
||||
|
||||
// FIXME(generic_associated_types): Compare the whole projections
|
||||
let data_poly_trait_ref = projection_ty.map_bound(|proj| proj.trait_ref(self.tcx()));
|
||||
let obligation_poly_trait_ref = ty::Binder::dummy(*obligation_trait_ref);
|
||||
self.infcx
|
||||
.at(&obligation.cause, obligation.param_env)
|
||||
.sup(obligation_poly_trait_ref, data_poly_trait_ref)
|
||||
.sup(obligation.predicate, infer_projection)
|
||||
.map_or(false, |InferOk { obligations, value: () }| {
|
||||
self.evaluate_predicates_recursively(
|
||||
TraitObligationStackList::empty(&ProvisionalEvaluationCache::default()),
|
||||
|
@ -779,14 +779,11 @@ impl<'tcx> LowerInto<'tcx, chalk_solve::rust_ir::AliasEqBound<RustInterner<'tcx>
|
||||
self,
|
||||
interner: &RustInterner<'tcx>,
|
||||
) -> chalk_solve::rust_ir::AliasEqBound<RustInterner<'tcx>> {
|
||||
let trait_ref = self.projection_ty.trait_ref(interner.tcx);
|
||||
let (trait_ref, own_substs) = self.projection_ty.trait_ref_and_own_substs(interner.tcx);
|
||||
chalk_solve::rust_ir::AliasEqBound {
|
||||
trait_bound: trait_ref.lower_into(interner),
|
||||
associated_ty_id: chalk_ir::AssocTypeId(self.projection_ty.item_def_id),
|
||||
parameters: self.projection_ty.substs[trait_ref.substs.len()..]
|
||||
.iter()
|
||||
.map(|arg| arg.lower_into(interner))
|
||||
.collect(),
|
||||
parameters: own_substs.iter().map(|arg| arg.lower_into(interner)).collect(),
|
||||
value: self.ty.lower_into(interner),
|
||||
}
|
||||
}
|
||||
|
@ -985,10 +985,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
||||
//
|
||||
// We want to produce `<B as SuperTrait<i32>>::T == foo`.
|
||||
|
||||
debug!(
|
||||
"add_predicates_for_ast_type_binding(hir_ref_id {:?}, trait_ref {:?}, binding {:?}, bounds {:?}",
|
||||
hir_ref_id, trait_ref, binding, bounds
|
||||
);
|
||||
debug!(?hir_ref_id, ?trait_ref, ?binding, ?bounds, "add_predicates_for_ast_type_binding",);
|
||||
let tcx = self.tcx();
|
||||
|
||||
let candidate =
|
||||
@ -1326,37 +1323,35 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
||||
debug!("regular_traits: {:?}", regular_traits);
|
||||
debug!("auto_traits: {:?}", auto_traits);
|
||||
|
||||
// Transform a `PolyTraitRef` into a `PolyExistentialTraitRef` by
|
||||
// removing the dummy `Self` type (`trait_object_dummy_self`).
|
||||
let trait_ref_to_existential = |trait_ref: ty::TraitRef<'tcx>| {
|
||||
if trait_ref.self_ty() != dummy_self {
|
||||
// FIXME: There appears to be a missing filter on top of `expand_trait_aliases`,
|
||||
// which picks up non-supertraits where clauses - but also, the object safety
|
||||
// completely ignores trait aliases, which could be object safety hazards. We
|
||||
// `delay_span_bug` here to avoid an ICE in stable even when the feature is
|
||||
// disabled. (#66420)
|
||||
tcx.sess.delay_span_bug(
|
||||
DUMMY_SP,
|
||||
&format!(
|
||||
"trait_ref_to_existential called on {:?} with non-dummy Self",
|
||||
trait_ref,
|
||||
),
|
||||
);
|
||||
}
|
||||
ty::ExistentialTraitRef::erase_self_ty(tcx, trait_ref)
|
||||
};
|
||||
|
||||
// Erase the `dummy_self` (`trait_object_dummy_self`) used above.
|
||||
let existential_trait_refs =
|
||||
regular_traits.iter().map(|i| i.trait_ref().map_bound(trait_ref_to_existential));
|
||||
let existential_trait_refs = regular_traits.iter().map(|i| {
|
||||
i.trait_ref().map_bound(|trait_ref: ty::TraitRef<'tcx>| {
|
||||
if trait_ref.self_ty() != dummy_self {
|
||||
// FIXME: There appears to be a missing filter on top of `expand_trait_aliases`,
|
||||
// which picks up non-supertraits where clauses - but also, the object safety
|
||||
// completely ignores trait aliases, which could be object safety hazards. We
|
||||
// `delay_span_bug` here to avoid an ICE in stable even when the feature is
|
||||
// disabled. (#66420)
|
||||
tcx.sess.delay_span_bug(
|
||||
DUMMY_SP,
|
||||
&format!(
|
||||
"trait_ref_to_existential called on {:?} with non-dummy Self",
|
||||
trait_ref,
|
||||
),
|
||||
);
|
||||
}
|
||||
ty::ExistentialTraitRef::erase_self_ty(tcx, trait_ref)
|
||||
})
|
||||
});
|
||||
let existential_projections = bounds.projection_bounds.iter().map(|(bound, _)| {
|
||||
bound.map_bound(|b| {
|
||||
let trait_ref = trait_ref_to_existential(b.projection_ty.trait_ref(tcx));
|
||||
ty::ExistentialProjection {
|
||||
ty: b.ty,
|
||||
item_def_id: b.projection_ty.item_def_id,
|
||||
substs: trait_ref.substs,
|
||||
if b.projection_ty.self_ty() != dummy_self {
|
||||
tcx.sess.delay_span_bug(
|
||||
DUMMY_SP,
|
||||
&format!("trait_ref_to_existential called on {:?} with non-dummy Self", b),
|
||||
);
|
||||
}
|
||||
ty::ExistentialProjection::erase_self_ty(tcx, b)
|
||||
})
|
||||
});
|
||||
|
||||
|
@ -208,7 +208,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
});
|
||||
|
||||
// Even if we can't infer the full signature, we may be able to
|
||||
// infer the kind. This can occur if there is a trait-reference
|
||||
// infer the kind. This can occur when we elaborate a predicate
|
||||
// like `F : Fn<A>`. Note that due to subtyping we could encounter
|
||||
// many viable options, so pick the most restrictive.
|
||||
let expected_kind = self
|
||||
@ -234,11 +234,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
|
||||
debug!("deduce_sig_from_projection({:?})", projection);
|
||||
|
||||
let trait_ref = projection.to_poly_trait_ref(tcx);
|
||||
let trait_def_id = projection.trait_def_id(tcx);
|
||||
|
||||
let is_fn = tcx.fn_trait_kind_from_lang_item(trait_ref.def_id()).is_some();
|
||||
let is_fn = tcx.fn_trait_kind_from_lang_item(trait_def_id).is_some();
|
||||
let gen_trait = tcx.require_lang_item(LangItem::Generator, cause_span);
|
||||
let is_gen = gen_trait == trait_ref.def_id();
|
||||
let is_gen = gen_trait == trait_def_id;
|
||||
if !is_fn && !is_gen {
|
||||
debug!("deduce_sig_from_projection: not fn or generator");
|
||||
return None;
|
||||
@ -256,7 +256,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
}
|
||||
|
||||
let input_tys = if is_fn {
|
||||
let arg_param_ty = trait_ref.skip_binder().substs.type_at(1);
|
||||
let arg_param_ty = projection.skip_binder().projection_ty.substs.type_at(1);
|
||||
let arg_param_ty = self.resolve_vars_if_possible(arg_param_ty);
|
||||
debug!("deduce_sig_from_projection: arg_param_ty={:?}", arg_param_ty);
|
||||
|
||||
@ -662,9 +662,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
};
|
||||
|
||||
// Check that this is a projection from the `Future` trait.
|
||||
let trait_ref = predicate.projection_ty.trait_ref(self.tcx);
|
||||
let trait_def_id = predicate.projection_ty.trait_def_id(self.tcx);
|
||||
let future_trait = self.tcx.require_lang_item(LangItem::Future, Some(cause_span));
|
||||
if trait_ref.def_id != future_trait {
|
||||
if trait_def_id != future_trait {
|
||||
debug!("deduce_future_output_from_projection: not a future");
|
||||
return None;
|
||||
}
|
||||
|
@ -769,9 +769,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
.filter_map(move |obligation| {
|
||||
let bound_predicate = obligation.predicate.kind();
|
||||
match bound_predicate.skip_binder() {
|
||||
ty::PredicateKind::Projection(data) => {
|
||||
Some((bound_predicate.rebind(data).to_poly_trait_ref(self.tcx), obligation))
|
||||
}
|
||||
ty::PredicateKind::Projection(data) => Some((
|
||||
bound_predicate.rebind(data).required_poly_trait_ref(self.tcx),
|
||||
obligation,
|
||||
)),
|
||||
ty::PredicateKind::Trait(data, _) => {
|
||||
Some((bound_predicate.rebind(data).to_poly_trait_ref(), obligation))
|
||||
}
|
||||
|
@ -23,6 +23,7 @@ use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt;
|
||||
use rustc_trait_selection::traits::Obligation;
|
||||
|
||||
use std::cmp::Ordering;
|
||||
use std::iter;
|
||||
|
||||
use super::probe::Mode;
|
||||
use super::{CandidateSource, MethodError, NoMatchData};
|
||||
@ -648,21 +649,25 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
ty::PredicateKind::Projection(pred) => {
|
||||
let pred = bound_predicate.rebind(pred);
|
||||
// `<Foo as Iterator>::Item = String`.
|
||||
let trait_ref =
|
||||
pred.skip_binder().projection_ty.trait_ref(self.tcx);
|
||||
let assoc = self
|
||||
.tcx
|
||||
.associated_item(pred.skip_binder().projection_ty.item_def_id);
|
||||
let ty = pred.skip_binder().ty;
|
||||
let obligation = format!("{}::{} = {}", trait_ref, assoc.ident, ty);
|
||||
let quiet = format!(
|
||||
"<_ as {}>::{} = {}",
|
||||
trait_ref.print_only_trait_path(),
|
||||
assoc.ident,
|
||||
ty
|
||||
let projection_ty = pred.skip_binder().projection_ty;
|
||||
|
||||
let substs_with_infer_self = tcx.mk_substs(
|
||||
iter::once(tcx.mk_ty_var(ty::TyVid { index: 0 }).into())
|
||||
.chain(projection_ty.substs.iter().skip(1)),
|
||||
);
|
||||
bound_span_label(trait_ref.self_ty(), &obligation, &quiet);
|
||||
Some((obligation, trait_ref.self_ty()))
|
||||
|
||||
let quiet_projection_ty = ty::ProjectionTy {
|
||||
substs: substs_with_infer_self,
|
||||
item_def_id: projection_ty.item_def_id,
|
||||
};
|
||||
|
||||
let ty = pred.skip_binder().ty;
|
||||
|
||||
let obligation = format!("{} = {}", projection_ty, ty);
|
||||
let quiet = format!("{} = {}", quiet_projection_ty, ty);
|
||||
|
||||
bound_span_label(projection_ty.self_ty(), &obligation, &quiet);
|
||||
Some((obligation, projection_ty.self_ty()))
|
||||
}
|
||||
ty::PredicateKind::Trait(poly_trait_ref, _) => {
|
||||
let p = poly_trait_ref.trait_ref;
|
||||
|
@ -198,7 +198,7 @@ pub fn setup_constraining_predicates<'tcx>(
|
||||
// `<<T as Bar>::Baz as Iterator>::Output = <U as Iterator>::Output`
|
||||
// Then the projection only applies if `T` is known, but it still
|
||||
// does not determine `U`.
|
||||
let inputs = parameters_for(&projection.projection_ty.trait_ref(tcx), true);
|
||||
let inputs = parameters_for(&projection.projection_ty, true);
|
||||
let relies_only_on_inputs = inputs.iter().all(|p| input_parameters.contains(&p));
|
||||
if !relies_only_on_inputs {
|
||||
continue;
|
||||
|
@ -64,6 +64,7 @@ pub trait Deref {
|
||||
/// The resulting type after dereferencing.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[rustc_diagnostic_item = "deref_target"]
|
||||
#[cfg_attr(not(bootstrap), lang = "deref_target")]
|
||||
type Target: ?Sized;
|
||||
|
||||
/// Dereferences the value.
|
||||
|
@ -13,4 +13,6 @@ impl X for () {
|
||||
type Y<T> where Self: Sized = u32;
|
||||
}
|
||||
|
||||
fn f<T: X<Y<()> = i32>>() {}
|
||||
|
||||
fn main() { }
|
||||
|
@ -0,0 +1,17 @@
|
||||
// Test that correct syntax is used in suggestion to constrain associated type
|
||||
|
||||
#![feature(generic_associated_types)]
|
||||
//~^ WARNING the feature `generic_associated_types` is incomplete
|
||||
|
||||
trait X {
|
||||
type Y<T>;
|
||||
}
|
||||
|
||||
fn f<T: X>(a: T::Y<i32>) {
|
||||
//~^ HELP consider constraining the associated type `<T as X>::Y<i32>` to `Vec<i32>`
|
||||
//~| SUGGESTION Y<i32> = Vec<i32>>
|
||||
let b: Vec<i32> = a;
|
||||
//~^ ERROR mismatched types
|
||||
}
|
||||
|
||||
fn main() {}
|
@ -0,0 +1,27 @@
|
||||
warning: the feature `generic_associated_types` is incomplete and may not be safe to use and/or cause compiler crashes
|
||||
--> $DIR/constraint-assoc-type-suggestion.rs:3:12
|
||||
|
|
||||
LL | #![feature(generic_associated_types)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: `#[warn(incomplete_features)]` on by default
|
||||
= note: see issue #44265 <https://github.com/rust-lang/rust/issues/44265> for more information
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/constraint-assoc-type-suggestion.rs:13:23
|
||||
|
|
||||
LL | let b: Vec<i32> = a;
|
||||
| -------- ^ expected struct `Vec`, found associated type
|
||||
| |
|
||||
| expected due to this
|
||||
|
|
||||
= note: expected struct `Vec<i32>`
|
||||
found associated type `<T as X>::Y<i32>`
|
||||
help: consider constraining the associated type `<T as X>::Y<i32>` to `Vec<i32>`
|
||||
|
|
||||
LL | fn f<T: X<Y<i32> = Vec<i32>>>(a: T::Y<i32>) {
|
||||
| ^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to previous error; 1 warning emitted
|
||||
|
||||
For more information about this error, try `rustc --explain E0308`.
|
@ -0,0 +1,35 @@
|
||||
// run-pass
|
||||
|
||||
#![allow(incomplete_features)]
|
||||
#![feature(generic_associated_types)]
|
||||
|
||||
pub trait X {
|
||||
type Y<'a>;
|
||||
fn m(&self) -> Self::Y<'_>;
|
||||
}
|
||||
|
||||
impl X for () {
|
||||
type Y<'a> = &'a ();
|
||||
|
||||
fn m(&self) -> Self::Y<'_> {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
fn f(x: &impl for<'a> X<Y<'a> = &'a ()>) -> &() {
|
||||
x.m()
|
||||
}
|
||||
|
||||
fn g<T: for<'a> X<Y<'a> = &'a ()>>(x: &T) -> &() {
|
||||
x.m()
|
||||
}
|
||||
|
||||
fn h(x: &()) -> &() {
|
||||
x.m()
|
||||
}
|
||||
|
||||
fn main() {
|
||||
f(&());
|
||||
g(&());
|
||||
h(&());
|
||||
}
|
@ -1,11 +1,11 @@
|
||||
#![feature(generic_associated_types)]
|
||||
//~^ WARNING the feature
|
||||
//~^ WARNING the feature
|
||||
|
||||
pub trait SubTrait {}
|
||||
|
||||
pub trait SuperTrait {
|
||||
type SubType<'a>: SubTrait;
|
||||
//~^ ERROR missing generics for associated
|
||||
//~^ ERROR missing generics for associated
|
||||
|
||||
fn get_sub<'a>(&'a mut self) -> Self::SubType<'a>;
|
||||
}
|
||||
@ -36,6 +36,4 @@ impl SuperTrait for SuperStruct {
|
||||
|
||||
fn main() {
|
||||
let sub: Box<dyn SuperTrait<SubType = SubStruct>> = Box::new(SuperStruct::new(0));
|
||||
//~^ ERROR the trait
|
||||
//~| ERROR the trait
|
||||
}
|
||||
|
@ -23,41 +23,6 @@ help: use angle brackets to add missing lifetime argument
|
||||
LL | type SubType<'a><'a>: SubTrait;
|
||||
| ^^^^
|
||||
|
||||
error[E0038]: the trait `SuperTrait` cannot be made into an object
|
||||
--> $DIR/issue-76535.rs:38:14
|
||||
|
|
||||
LL | let sub: Box<dyn SuperTrait<SubType = SubStruct>> = Box::new(SuperStruct::new(0));
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `SuperTrait` cannot be made into an object
|
||||
|
|
||||
= help: consider moving `get_sub` to another trait
|
||||
note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
|
||||
--> $DIR/issue-76535.rs:10:37
|
||||
|
|
||||
LL | pub trait SuperTrait {
|
||||
| ---------- this trait cannot be made into an object...
|
||||
...
|
||||
LL | fn get_sub<'a>(&'a mut self) -> Self::SubType<'a>;
|
||||
| ^^^^^^^^^^^^^^^^^ ...because method `get_sub` references the `Self` type in its return type
|
||||
error: aborting due to previous error; 1 warning emitted
|
||||
|
||||
error[E0038]: the trait `SuperTrait` cannot be made into an object
|
||||
--> $DIR/issue-76535.rs:38:57
|
||||
|
|
||||
LL | let sub: Box<dyn SuperTrait<SubType = SubStruct>> = Box::new(SuperStruct::new(0));
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `SuperTrait` cannot be made into an object
|
||||
|
|
||||
= help: consider moving `get_sub` to another trait
|
||||
note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
|
||||
--> $DIR/issue-76535.rs:10:37
|
||||
|
|
||||
LL | pub trait SuperTrait {
|
||||
| ---------- this trait cannot be made into an object...
|
||||
...
|
||||
LL | fn get_sub<'a>(&'a mut self) -> Self::SubType<'a>;
|
||||
| ^^^^^^^^^^^^^^^^^ ...because method `get_sub` references the `Self` type in its return type
|
||||
= note: required because of the requirements on the impl of `CoerceUnsized<Box<dyn SuperTrait<SubType = SubStruct<'_>>>>` for `Box<SuperStruct>`
|
||||
= note: required by cast to type `Box<dyn SuperTrait<SubType = SubStruct<'_>>>`
|
||||
|
||||
error: aborting due to 3 previous errors; 1 warning emitted
|
||||
|
||||
Some errors have detailed explanations: E0038, E0107.
|
||||
For more information about an error, try `rustc --explain E0038`.
|
||||
For more information about this error, try `rustc --explain E0107`.
|
||||
|
@ -19,7 +19,7 @@ impl<'a, T> RefCont<'a, T> for Box<T> {
|
||||
|
||||
trait MapLike<K, V> {
|
||||
type VRefCont<'a>: RefCont<'a, V>;
|
||||
//~^ ERROR missing generics
|
||||
//~^ ERROR missing generics
|
||||
fn get<'a>(&'a self, key: &K) -> Option<Self::VRefCont<'a>>;
|
||||
}
|
||||
|
||||
@ -42,6 +42,5 @@ impl<K, V: Default> MapLike<K, V> for Source {
|
||||
fn main() {
|
||||
let m = Box::new(std::collections::BTreeMap::<u8, u8>::new())
|
||||
as Box<dyn MapLike<u8, u8, VRefCont = dyn RefCont<'_, u8>>>;
|
||||
//~^ ERROR the trait
|
||||
//~^^^ ERROR the trait
|
||||
//~^^ ERROR type mismatch resolving
|
||||
}
|
||||
|
@ -14,41 +14,17 @@ help: use angle brackets to add missing lifetime argument
|
||||
LL | type VRefCont<'a><'a>: RefCont<'a, V>;
|
||||
| ^^^^
|
||||
|
||||
error[E0038]: the trait `MapLike` cannot be made into an object
|
||||
--> $DIR/issue-79422.rs:44:12
|
||||
|
|
||||
LL | as Box<dyn MapLike<u8, u8, VRefCont = dyn RefCont<'_, u8>>>;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `MapLike` cannot be made into an object
|
||||
|
|
||||
= help: consider moving `get` to another trait
|
||||
note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
|
||||
--> $DIR/issue-79422.rs:23:38
|
||||
|
|
||||
LL | trait MapLike<K, V> {
|
||||
| ------- this trait cannot be made into an object...
|
||||
...
|
||||
LL | fn get<'a>(&'a self, key: &K) -> Option<Self::VRefCont<'a>>;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ ...because method `get` references the `Self` type in its return type
|
||||
|
||||
error[E0038]: the trait `MapLike` cannot be made into an object
|
||||
error[E0271]: type mismatch resolving `<BTreeMap<u8, u8> as MapLike<u8, u8>>::VRefCont<'static> == (dyn RefCont<'_, u8> + 'static)`
|
||||
--> $DIR/issue-79422.rs:43:13
|
||||
|
|
||||
LL | let m = Box::new(std::collections::BTreeMap::<u8, u8>::new())
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `MapLike` cannot be made into an object
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected trait object `dyn RefCont`, found reference
|
||||
|
|
||||
= help: consider moving `get` to another trait
|
||||
note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
|
||||
--> $DIR/issue-79422.rs:23:38
|
||||
|
|
||||
LL | trait MapLike<K, V> {
|
||||
| ------- this trait cannot be made into an object...
|
||||
...
|
||||
LL | fn get<'a>(&'a self, key: &K) -> Option<Self::VRefCont<'a>>;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ ...because method `get` references the `Self` type in its return type
|
||||
= note: required because of the requirements on the impl of `CoerceUnsized<Box<dyn MapLike<u8, u8, VRefCont = (dyn RefCont<'_, u8> + 'static)>>>` for `Box<BTreeMap<u8, u8>>`
|
||||
= note: required by cast to type `Box<dyn MapLike<u8, u8, VRefCont = (dyn RefCont<'_, u8> + 'static)>>`
|
||||
= note: expected trait object `(dyn RefCont<'_, u8> + 'static)`
|
||||
found reference `&'static u8`
|
||||
= note: required for the cast to the object type `dyn MapLike<u8, u8, VRefCont = (dyn RefCont<'_, u8> + 'static)>`
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0038, E0107.
|
||||
For more information about an error, try `rustc --explain E0038`.
|
||||
Some errors have detailed explanations: E0107, E0271.
|
||||
For more information about an error, try `rustc --explain E0107`.
|
||||
|
@ -0,0 +1,35 @@
|
||||
// Test that the predicate printed in an unresolved method error prints the
|
||||
// generics for a generic associated type.
|
||||
|
||||
#![feature(generic_associated_types)]
|
||||
//~^ WARNING the feature `generic_associated_types` is incomplete
|
||||
//~| NOTE `#[warn(incomplete_features)]` on by default
|
||||
//~| NOTE see issue #44265
|
||||
|
||||
trait X {
|
||||
type Y<T>;
|
||||
}
|
||||
|
||||
trait M {
|
||||
fn f(&self) {}
|
||||
}
|
||||
|
||||
impl<T: X<Y<i32> = i32>> M for T {}
|
||||
|
||||
struct S;
|
||||
//~^ NOTE method `f` not found for this
|
||||
//~| NOTE doesn't satisfy `<S as X>::Y<i32> = i32`
|
||||
//~| NOTE doesn't satisfy `S: M`
|
||||
|
||||
impl X for S {
|
||||
type Y<T> = bool;
|
||||
}
|
||||
|
||||
fn f(a: S) {
|
||||
a.f();
|
||||
//~^ ERROR the method `f` exists for struct `S`, but its trait bounds were not satisfied
|
||||
//~| NOTE method cannot be called on `S` due to unsatisfied trait bounds
|
||||
//~| NOTE the following trait bounds were not satisfied:
|
||||
}
|
||||
|
||||
fn main() {}
|
@ -0,0 +1,29 @@
|
||||
warning: the feature `generic_associated_types` is incomplete and may not be safe to use and/or cause compiler crashes
|
||||
--> $DIR/method-unsatified-assoc-type-predicate.rs:4:12
|
||||
|
|
||||
LL | #![feature(generic_associated_types)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: `#[warn(incomplete_features)]` on by default
|
||||
= note: see issue #44265 <https://github.com/rust-lang/rust/issues/44265> for more information
|
||||
|
||||
error[E0599]: the method `f` exists for struct `S`, but its trait bounds were not satisfied
|
||||
--> $DIR/method-unsatified-assoc-type-predicate.rs:29:7
|
||||
|
|
||||
LL | struct S;
|
||||
| ---------
|
||||
| |
|
||||
| method `f` not found for this
|
||||
| doesn't satisfy `<S as X>::Y<i32> = i32`
|
||||
| doesn't satisfy `S: M`
|
||||
...
|
||||
LL | a.f();
|
||||
| ^ method cannot be called on `S` due to unsatisfied trait bounds
|
||||
|
|
||||
= note: the following trait bounds were not satisfied:
|
||||
`<S as X>::Y<i32> = i32`
|
||||
which is required by `S: M`
|
||||
|
||||
error: aborting due to previous error; 1 warning emitted
|
||||
|
||||
For more information about this error, try `rustc --explain E0599`.
|
@ -0,0 +1,36 @@
|
||||
#![allow(incomplete_features)]
|
||||
#![feature(generic_associated_types)]
|
||||
|
||||
pub trait X {
|
||||
type Y<'a>;
|
||||
fn m(&self) -> Self::Y<'_>;
|
||||
}
|
||||
|
||||
impl X for () {
|
||||
type Y<'a> = &'a ();
|
||||
|
||||
fn m(&self) -> Self::Y<'_> {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
fn f(x: &impl for<'a> X<Y<'a> = &'a ()>) -> &'static () {
|
||||
x.m()
|
||||
//~^ ERROR explicit lifetime required
|
||||
}
|
||||
|
||||
fn g<T: for<'a> X<Y<'a> = &'a ()>>(x: &T) -> &'static () {
|
||||
x.m()
|
||||
//~^ ERROR explicit lifetime required
|
||||
}
|
||||
|
||||
fn h(x: &()) -> &'static () {
|
||||
x.m()
|
||||
//~^ ERROR explicit lifetime required
|
||||
}
|
||||
|
||||
fn main() {
|
||||
f(&());
|
||||
g(&());
|
||||
h(&());
|
||||
}
|
@ -0,0 +1,27 @@
|
||||
error[E0621]: explicit lifetime required in the type of `x`
|
||||
--> $DIR/projection-type-lifetime-mismatch.rs:18:5
|
||||
|
|
||||
LL | fn f(x: &impl for<'a> X<Y<'a> = &'a ()>) -> &'static () {
|
||||
| ------------------------------- help: add explicit lifetime `'static` to the type of `x`: `&'static impl for<'a> X<Y<'a> = &'a ()>`
|
||||
LL | x.m()
|
||||
| ^^^^^ lifetime `'static` required
|
||||
|
||||
error[E0621]: explicit lifetime required in the type of `x`
|
||||
--> $DIR/projection-type-lifetime-mismatch.rs:23:5
|
||||
|
|
||||
LL | fn g<T: for<'a> X<Y<'a> = &'a ()>>(x: &T) -> &'static () {
|
||||
| -- help: add explicit lifetime `'static` to the type of `x`: `&'static T`
|
||||
LL | x.m()
|
||||
| ^^^^^ lifetime `'static` required
|
||||
|
||||
error[E0621]: explicit lifetime required in the type of `x`
|
||||
--> $DIR/projection-type-lifetime-mismatch.rs:28:5
|
||||
|
|
||||
LL | fn h(x: &()) -> &'static () {
|
||||
| --- help: add explicit lifetime `'static` to the type of `x`: `&'static ()`
|
||||
LL | x.m()
|
||||
| ^^^^^ lifetime `'static` required
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0621`.
|
@ -0,0 +1,28 @@
|
||||
#![allow(incomplete_features)]
|
||||
#![feature(generic_associated_types)]
|
||||
|
||||
pub trait X {
|
||||
type Y<'a: 'static>;
|
||||
//~^ WARNING unnecessary lifetime parameter
|
||||
}
|
||||
|
||||
impl X for () {
|
||||
type Y<'a> = &'a ();
|
||||
}
|
||||
|
||||
struct B<'a, T: for<'r> X<Y<'r> = &'r ()>> {
|
||||
f: <T as X>::Y<'a>,
|
||||
//~^ ERROR lifetime bound not satisfied
|
||||
}
|
||||
|
||||
struct C<'a, T: X> {
|
||||
f: <T as X>::Y<'a>,
|
||||
//~^ ERROR lifetime bound not satisfied
|
||||
}
|
||||
|
||||
struct D<'a> {
|
||||
f: <() as X>::Y<'a>,
|
||||
//~^ ERROR lifetime bound not satisfied
|
||||
}
|
||||
|
||||
fn main() {}
|
@ -0,0 +1,50 @@
|
||||
warning: unnecessary lifetime parameter `'a`
|
||||
--> $DIR/unsatified-item-lifetime-bound.rs:5:12
|
||||
|
|
||||
LL | type Y<'a: 'static>;
|
||||
| ^^^^^^^^^^^
|
||||
|
|
||||
= help: you can use the `'static` lifetime directly, in place of `'a`
|
||||
|
||||
error[E0478]: lifetime bound not satisfied
|
||||
--> $DIR/unsatified-item-lifetime-bound.rs:14:8
|
||||
|
|
||||
LL | f: <T as X>::Y<'a>,
|
||||
| ^^^^^^^^^^^^^^^
|
||||
|
|
||||
note: lifetime parameter instantiated with the lifetime `'a` as defined on the struct at 13:10
|
||||
--> $DIR/unsatified-item-lifetime-bound.rs:13:10
|
||||
|
|
||||
LL | struct B<'a, T: for<'r> X<Y<'r> = &'r ()>> {
|
||||
| ^^
|
||||
= note: but lifetime parameter must outlive the static lifetime
|
||||
|
||||
error[E0478]: lifetime bound not satisfied
|
||||
--> $DIR/unsatified-item-lifetime-bound.rs:19:8
|
||||
|
|
||||
LL | f: <T as X>::Y<'a>,
|
||||
| ^^^^^^^^^^^^^^^
|
||||
|
|
||||
note: lifetime parameter instantiated with the lifetime `'a` as defined on the struct at 18:10
|
||||
--> $DIR/unsatified-item-lifetime-bound.rs:18:10
|
||||
|
|
||||
LL | struct C<'a, T: X> {
|
||||
| ^^
|
||||
= note: but lifetime parameter must outlive the static lifetime
|
||||
|
||||
error[E0478]: lifetime bound not satisfied
|
||||
--> $DIR/unsatified-item-lifetime-bound.rs:24:8
|
||||
|
|
||||
LL | f: <() as X>::Y<'a>,
|
||||
| ^^^^^^^^^^^^^^^^
|
||||
|
|
||||
note: lifetime parameter instantiated with the lifetime `'a` as defined on the struct at 23:10
|
||||
--> $DIR/unsatified-item-lifetime-bound.rs:23:10
|
||||
|
|
||||
LL | struct D<'a> {
|
||||
| ^^
|
||||
= note: but lifetime parameter must outlive the static lifetime
|
||||
|
||||
error: aborting due to 3 previous errors; 1 warning emitted
|
||||
|
||||
For more information about this error, try `rustc --explain E0478`.
|
Loading…
Reference in New Issue
Block a user