Increase accuracy of lifetime bound on trait object impl suggestion
This commit is contained in:
parent
6513148c14
commit
4e08bab87d
18 changed files with 321 additions and 114 deletions
|
@ -2198,7 +2198,17 @@ pub enum IsAsync {
|
||||||
NotAsync,
|
NotAsync,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, PartialEq, RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
|
#[derive(
|
||||||
|
Copy,
|
||||||
|
Clone,
|
||||||
|
PartialEq,
|
||||||
|
RustcEncodable,
|
||||||
|
RustcDecodable,
|
||||||
|
Debug,
|
||||||
|
HashStable_Generic,
|
||||||
|
Eq,
|
||||||
|
Hash
|
||||||
|
)]
|
||||||
pub enum Defaultness {
|
pub enum Defaultness {
|
||||||
Default { has_value: bool },
|
Default { has_value: bool },
|
||||||
Final,
|
Final,
|
||||||
|
|
|
@ -36,12 +36,13 @@ use crate::traits::{Obligation, PredicateObligations};
|
||||||
|
|
||||||
use rustc_ast::ast;
|
use rustc_ast::ast;
|
||||||
use rustc_hir::def_id::DefId;
|
use rustc_hir::def_id::DefId;
|
||||||
|
use rustc_middle::traits::ObligationCause;
|
||||||
use rustc_middle::ty::error::TypeError;
|
use rustc_middle::ty::error::TypeError;
|
||||||
use rustc_middle::ty::relate::{self, Relate, RelateResult, TypeRelation};
|
use rustc_middle::ty::relate::{self, Relate, RelateResult, TypeRelation};
|
||||||
use rustc_middle::ty::subst::SubstsRef;
|
use rustc_middle::ty::subst::SubstsRef;
|
||||||
use rustc_middle::ty::{self, InferConst, ToPredicate, Ty, TyCtxt, TypeFoldable};
|
use rustc_middle::ty::{self, InferConst, ToPredicate, Ty, TyCtxt, TypeFoldable};
|
||||||
use rustc_middle::ty::{IntType, UintType};
|
use rustc_middle::ty::{IntType, UintType};
|
||||||
use rustc_span::{Span, DUMMY_SP};
|
use rustc_span::DUMMY_SP;
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct CombineFields<'infcx, 'tcx> {
|
pub struct CombineFields<'infcx, 'tcx> {
|
||||||
|
@ -367,10 +368,11 @@ impl<'infcx, 'tcx> CombineFields<'infcx, 'tcx> {
|
||||||
};
|
};
|
||||||
|
|
||||||
debug!("generalize: for_universe = {:?}", for_universe);
|
debug!("generalize: for_universe = {:?}", for_universe);
|
||||||
|
debug!("generalize: trace = {:?}", self.trace);
|
||||||
|
|
||||||
let mut generalize = Generalizer {
|
let mut generalize = Generalizer {
|
||||||
infcx: self.infcx,
|
infcx: self.infcx,
|
||||||
span: self.trace.cause.span,
|
cause: &self.trace.cause,
|
||||||
for_vid_sub_root: self.infcx.inner.borrow_mut().type_variables().sub_root_var(for_vid),
|
for_vid_sub_root: self.infcx.inner.borrow_mut().type_variables().sub_root_var(for_vid),
|
||||||
for_universe,
|
for_universe,
|
||||||
ambient_variance,
|
ambient_variance,
|
||||||
|
@ -414,7 +416,7 @@ struct Generalizer<'cx, 'tcx> {
|
||||||
infcx: &'cx InferCtxt<'cx, 'tcx>,
|
infcx: &'cx InferCtxt<'cx, 'tcx>,
|
||||||
|
|
||||||
/// The span, used when creating new type variables and things.
|
/// The span, used when creating new type variables and things.
|
||||||
span: Span,
|
cause: &'cx ObligationCause<'tcx>,
|
||||||
|
|
||||||
/// The vid of the type variable that is in the process of being
|
/// The vid of the type variable that is in the process of being
|
||||||
/// instantiated; if we find this within the type we are folding,
|
/// instantiated; if we find this within the type we are folding,
|
||||||
|
@ -639,7 +641,7 @@ impl TypeRelation<'tcx> for Generalizer<'_, 'tcx> {
|
||||||
|
|
||||||
// FIXME: This is non-ideal because we don't give a
|
// FIXME: This is non-ideal because we don't give a
|
||||||
// very descriptive origin for this region variable.
|
// very descriptive origin for this region variable.
|
||||||
Ok(self.infcx.next_region_var_in_universe(MiscVariable(self.span), self.for_universe))
|
Ok(self.infcx.next_region_var_in_universe(MiscVariable(self.cause.span), self.for_universe))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn consts(
|
fn consts(
|
||||||
|
|
|
@ -2010,7 +2010,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
||||||
infer::MiscVariable(_) => String::new(),
|
infer::MiscVariable(_) => String::new(),
|
||||||
infer::PatternRegion(_) => " for pattern".to_string(),
|
infer::PatternRegion(_) => " for pattern".to_string(),
|
||||||
infer::AddrOfRegion(_) => " for borrow expression".to_string(),
|
infer::AddrOfRegion(_) => " for borrow expression".to_string(),
|
||||||
infer::Autoref(_) => " for autoref".to_string(),
|
infer::Autoref(_, _) => " for autoref".to_string(),
|
||||||
infer::Coercion(_) => " for automatic coercion".to_string(),
|
infer::Coercion(_) => " for automatic coercion".to_string(),
|
||||||
infer::LateBoundRegion(_, br, infer::FnCall) => {
|
infer::LateBoundRegion(_, br, infer::FnCall) => {
|
||||||
format!(" for lifetime parameter {}in function call", br_string(br))
|
format!(" for lifetime parameter {}in function call", br_string(br))
|
||||||
|
|
|
@ -2,14 +2,14 @@
|
||||||
|
|
||||||
use crate::infer::error_reporting::nice_region_error::NiceRegionError;
|
use crate::infer::error_reporting::nice_region_error::NiceRegionError;
|
||||||
use crate::infer::lexical_region_resolve::RegionResolutionError;
|
use crate::infer::lexical_region_resolve::RegionResolutionError;
|
||||||
|
use crate::infer::{SubregionOrigin, TypeTrace};
|
||||||
|
use crate::traits::ObligationCauseCode;
|
||||||
use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder, ErrorReported};
|
use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder, ErrorReported};
|
||||||
use rustc_hir::def::{DefKind, Res};
|
|
||||||
use rustc_hir::def_id::{DefId, LOCAL_CRATE};
|
use rustc_hir::def_id::{DefId, LOCAL_CRATE};
|
||||||
use rustc_hir::{
|
use rustc_hir::intravisit::{walk_ty, ErasedMap, NestedVisitorMap, Visitor};
|
||||||
GenericBound, Item, ItemKind, Lifetime, LifetimeName, Node, Path, PolyTraitRef, TraitRef,
|
use rustc_hir::{self as hir, GenericBound, Item, ItemKind, Lifetime, LifetimeName, Node, TyKind};
|
||||||
TyKind,
|
use rustc_middle::ty::{self, AssocItemContainer, RegionKind, Ty, TypeFoldable, TypeVisitor};
|
||||||
};
|
use rustc_span::Span;
|
||||||
use rustc_middle::ty::{self, RegionKind, Ty, TypeFoldable, TypeVisitor};
|
|
||||||
|
|
||||||
impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
|
impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
|
||||||
/// Print the error message for lifetime errors when the return type is a static impl Trait.
|
/// Print the error message for lifetime errors when the return type is a static impl Trait.
|
||||||
|
@ -27,6 +27,39 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
|
||||||
) if **sub_r == RegionKind::ReStatic => {
|
) if **sub_r == RegionKind::ReStatic => {
|
||||||
(var_origin, sub_origin, sub_r, sup_origin, sup_r)
|
(var_origin, sub_origin, sub_r, sup_origin, sup_r)
|
||||||
}
|
}
|
||||||
|
RegionResolutionError::ConcreteFailure(
|
||||||
|
SubregionOrigin::Subtype(box TypeTrace { cause, .. }),
|
||||||
|
sub_r,
|
||||||
|
sup_r,
|
||||||
|
) if **sub_r == RegionKind::ReStatic => {
|
||||||
|
// This is for the implicit `'static` requirement coming from `impl dyn Trait {}`.
|
||||||
|
if let ObligationCauseCode::UnifyReceiver(assoc) = &cause.code {
|
||||||
|
let param = self.find_param_with_region(sup_r, sub_r)?;
|
||||||
|
let lifetime = if sup_r.has_name() {
|
||||||
|
format!("lifetime `{}`", sup_r)
|
||||||
|
} else {
|
||||||
|
"an anonymous lifetime `'_`".to_string()
|
||||||
|
};
|
||||||
|
let mut err = struct_span_err!(
|
||||||
|
tcx.sess,
|
||||||
|
cause.span,
|
||||||
|
E0759,
|
||||||
|
"cannot infer an appropriate lifetime"
|
||||||
|
);
|
||||||
|
err.span_label(param.param_ty_span, &format!("this data with {}...", lifetime));
|
||||||
|
err.span_label(
|
||||||
|
cause.span,
|
||||||
|
"...is captured and required to live as long as `'static` here",
|
||||||
|
);
|
||||||
|
if self.find_impl_on_dyn_trait(&mut err, param.param_ty, &assoc.container) {
|
||||||
|
err.emit();
|
||||||
|
return Some(ErrorReported);
|
||||||
|
} else {
|
||||||
|
err.cancel();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return None;
|
||||||
|
}
|
||||||
_ => return None,
|
_ => return None,
|
||||||
};
|
};
|
||||||
debug!(
|
debug!(
|
||||||
|
@ -96,7 +129,11 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
self.find_impl_on_dyn_trait(&mut err, param.param_ty);
|
if let SubregionOrigin::Subtype(box TypeTrace { cause, .. }) = &sup_origin {
|
||||||
|
if let ObligationCauseCode::UnifyReceiver(assoc) = &cause.code {
|
||||||
|
self.find_impl_on_dyn_trait(&mut err, param.param_ty, &assoc.container);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let fn_returns = tcx.return_type_impl_or_dyn_traits(anon_reg_sup.def_id);
|
let fn_returns = tcx.return_type_impl_or_dyn_traits(anon_reg_sup.def_id);
|
||||||
debug!("try_report_static_impl_trait: fn_return={:?}", fn_returns);
|
debug!("try_report_static_impl_trait: fn_return={:?}", fn_returns);
|
||||||
|
@ -222,63 +259,86 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
|
||||||
|
|
||||||
/// When we call a method coming from an `impl Foo for dyn Bar`, `dyn Bar` introduces a default
|
/// When we call a method coming from an `impl Foo for dyn Bar`, `dyn Bar` introduces a default
|
||||||
/// `'static` obligation. Find `impl` blocks that are implemented
|
/// `'static` obligation. Find `impl` blocks that are implemented
|
||||||
fn find_impl_on_dyn_trait(&self, err: &mut DiagnosticBuilder<'_>, ty: Ty<'_>) -> bool {
|
fn find_impl_on_dyn_trait(
|
||||||
|
&self,
|
||||||
|
err: &mut DiagnosticBuilder<'_>,
|
||||||
|
ty: Ty<'_>,
|
||||||
|
container: &AssocItemContainer,
|
||||||
|
) -> bool {
|
||||||
let tcx = self.tcx();
|
let tcx = self.tcx();
|
||||||
|
let mut suggested = false;
|
||||||
|
|
||||||
// Find the trait object types in the argument.
|
// Find the trait object types in the argument.
|
||||||
let mut v = TraitObjectVisitor(vec![]);
|
let mut v = TraitObjectVisitor(vec![]);
|
||||||
v.visit_ty(ty);
|
v.visit_ty(ty);
|
||||||
debug!("TraitObjectVisitor {:?}", v.0);
|
|
||||||
|
|
||||||
// Find all the `impl`s in the local scope that can be called on the type parameter.
|
let container_id = match container {
|
||||||
// FIXME: this doesn't find `impl dyn Trait { /**/ }`.
|
// When the obligation comes from an `impl Foo for dyn Bar {}`, we
|
||||||
|
// have the `DefId` of the `trait` itself, not the relevant `impl`
|
||||||
|
// block. Because of this, we have to look at all the `trait`s
|
||||||
|
// available, and filter out all that are not of `Foo` (this `def_id`)
|
||||||
|
// and not of `Bar` (the `filter_map` later in this method).
|
||||||
|
AssocItemContainer::TraitContainer(def_id) => def_id,
|
||||||
|
|
||||||
|
// When the obligation comes from an `impl dyn Trait {}`, we already
|
||||||
|
// have the `DefId` of the relevant `Item`, so we use it directly.
|
||||||
|
AssocItemContainer::ImplContainer(def_id) => {
|
||||||
|
if let Some(Node::Item(Item { kind: ItemKind::Impl { self_ty, .. }, .. })) =
|
||||||
|
tcx.hir().get_if_local(*def_id)
|
||||||
|
{
|
||||||
|
for found_did in &v.0 {
|
||||||
|
let mut hir_v = HirTraitObjectVisitor(vec![], *found_did);
|
||||||
|
hir_v.visit_ty(self_ty);
|
||||||
|
if let [span] = &hir_v.0[..] {
|
||||||
|
err.span_suggestion_verbose(
|
||||||
|
span.shrink_to_hi(),
|
||||||
|
"this `impl` introduces an implicit `'static` requirement, \
|
||||||
|
consider changing it",
|
||||||
|
" + '_".to_string(),
|
||||||
|
Applicability::MaybeIncorrect,
|
||||||
|
);
|
||||||
|
suggested = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return suggested;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Find all the `impl`s in the local scope that can be called on the type parameter. And
|
||||||
|
// retain all that are `impl`s of the trait that originated the `'static` obligation.
|
||||||
|
// This doesn't find `impl dyn Trait { /**/ }`, but that case is handled above.
|
||||||
let impl_self_tys = tcx
|
let impl_self_tys = tcx
|
||||||
.all_traits(LOCAL_CRATE)
|
.all_traits(LOCAL_CRATE)
|
||||||
.iter()
|
.iter()
|
||||||
.flat_map(|trait_did| tcx.hir().trait_impls(*trait_did))
|
.flat_map(|trait_did| tcx.hir().trait_impls(*trait_did))
|
||||||
.filter_map(|impl_node| {
|
.filter_map(|impl_node| {
|
||||||
let impl_did = tcx.hir().local_def_id(*impl_node);
|
let impl_did = tcx.hir().local_def_id(*impl_node);
|
||||||
if let Some(Node::Item(Item { kind: ItemKind::Impl { self_ty, .. }, .. })) =
|
match tcx.hir().get_if_local(impl_did.to_def_id()) {
|
||||||
tcx.hir().get_if_local(impl_did.to_def_id())
|
Some(Node::Item(Item {
|
||||||
{
|
kind: ItemKind::Impl { self_ty, of_trait: Some(of_trait), .. },
|
||||||
Some(self_ty)
|
..
|
||||||
} else {
|
})) if of_trait.trait_def_id() == Some(*container_id) => Some(self_ty),
|
||||||
None
|
_ => None,
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
let mut suggested = false;
|
|
||||||
|
// Given all the `impl`s of the relevant `trait`, look for those that are implemented for
|
||||||
|
// the trait object in the `fn` parameter type.
|
||||||
for self_ty in impl_self_tys {
|
for self_ty in impl_self_tys {
|
||||||
if let TyKind::TraitObject(
|
for found_did in &v.0 {
|
||||||
poly_trait_refs,
|
let mut hir_v = HirTraitObjectVisitor(vec![], *found_did);
|
||||||
Lifetime { name: LifetimeName::ImplicitObjectLifetimeDefault, .. },
|
hir_v.visit_ty(self_ty);
|
||||||
) = self_ty.kind
|
if let [span] = &hir_v.0[..] {
|
||||||
{
|
err.span_suggestion_verbose(
|
||||||
for p in poly_trait_refs {
|
span.shrink_to_hi(),
|
||||||
if let PolyTraitRef {
|
"this `impl` introduces an implicit `'static` requirement, \
|
||||||
trait_ref:
|
consider changing it",
|
||||||
TraitRef { path: Path { res: Res::Def(DefKind::Trait, did), .. }, .. },
|
" + '_".to_string(),
|
||||||
..
|
Applicability::MaybeIncorrect,
|
||||||
} = p
|
);
|
||||||
{
|
suggested = true;
|
||||||
for found_did in &v.0 {
|
|
||||||
if did == found_did {
|
|
||||||
// We've found an `impl Foo for dyn Bar {}`.
|
|
||||||
// FIXME: we should change this so it also works for
|
|
||||||
// `impl Foo for Box<dyn Bar> {}`.
|
|
||||||
err.span_suggestion_verbose(
|
|
||||||
self_ty.span.shrink_to_hi(),
|
|
||||||
"this `impl` introduces an implicit `'static` requirement, \
|
|
||||||
consider changing it",
|
|
||||||
" + '_".to_string(),
|
|
||||||
Applicability::MaybeIncorrect,
|
|
||||||
);
|
|
||||||
suggested = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
err.emit();
|
|
||||||
return Some(ErrorReported);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
suggested
|
suggested
|
||||||
|
@ -301,3 +361,31 @@ impl TypeVisitor<'_> for TraitObjectVisitor {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Collect all `hir::Ty<'_>` `Span`s for trait objects with an implicit lifetime.
|
||||||
|
struct HirTraitObjectVisitor(Vec<Span>, DefId);
|
||||||
|
|
||||||
|
impl<'tcx> Visitor<'tcx> for HirTraitObjectVisitor {
|
||||||
|
type Map = ErasedMap<'tcx>;
|
||||||
|
|
||||||
|
fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
|
||||||
|
NestedVisitorMap::None
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_ty(&mut self, t: &'tcx hir::Ty<'tcx>) {
|
||||||
|
match t.kind {
|
||||||
|
TyKind::TraitObject(
|
||||||
|
poly_trait_refs,
|
||||||
|
Lifetime { name: LifetimeName::ImplicitObjectLifetimeDefault, .. },
|
||||||
|
) => {
|
||||||
|
for ptr in poly_trait_refs {
|
||||||
|
if Some(self.1) == ptr.trait_ref.trait_def_id() {
|
||||||
|
self.0.push(ptr.span);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
walk_ty(self, t);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -7,20 +7,18 @@ use rustc_hir::def_id::LocalDefId;
|
||||||
use rustc_middle::ty::{self, DefIdTree, Region, Ty};
|
use rustc_middle::ty::{self, DefIdTree, Region, Ty};
|
||||||
use rustc_span::Span;
|
use rustc_span::Span;
|
||||||
|
|
||||||
// The struct contains the information about the anonymous region
|
/// Information about the anonymous region we are searching for.
|
||||||
// we are searching for.
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub(super) struct AnonymousParamInfo<'tcx> {
|
pub(super) struct AnonymousParamInfo<'tcx> {
|
||||||
// the parameter corresponding to the anonymous region
|
/// The parameter corresponding to the anonymous region.
|
||||||
pub param: &'tcx hir::Param<'tcx>,
|
pub param: &'tcx hir::Param<'tcx>,
|
||||||
// the type corresponding to the anonymopus region parameter
|
/// The type corresponding to the anonymous region parameter.
|
||||||
pub param_ty: Ty<'tcx>,
|
pub param_ty: Ty<'tcx>,
|
||||||
// the ty::BoundRegion corresponding to the anonymous region
|
/// The ty::BoundRegion corresponding to the anonymous region.
|
||||||
pub bound_region: ty::BoundRegion,
|
pub bound_region: ty::BoundRegion,
|
||||||
// param_ty_span contains span of parameter type
|
/// The `Span` of the parameter type.
|
||||||
pub param_ty_span: Span,
|
pub param_ty_span: Span,
|
||||||
// corresponds to id the argument is the first parameter
|
/// Signals that the argument is the first parameter in the declaration.
|
||||||
// in the declaration
|
|
||||||
pub is_first: bool,
|
pub is_first: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -463,7 +463,7 @@ pub enum RegionVariableOrigin {
|
||||||
AddrOfRegion(Span),
|
AddrOfRegion(Span),
|
||||||
|
|
||||||
/// Regions created as part of an autoref of a method receiver
|
/// Regions created as part of an autoref of a method receiver
|
||||||
Autoref(Span),
|
Autoref(Span, ty::AssocItem),
|
||||||
|
|
||||||
/// Regions created as part of an automatic coercion
|
/// Regions created as part of an automatic coercion
|
||||||
Coercion(Span),
|
Coercion(Span),
|
||||||
|
@ -1800,15 +1800,15 @@ impl<'tcx> SubregionOrigin<'tcx> {
|
||||||
impl RegionVariableOrigin {
|
impl RegionVariableOrigin {
|
||||||
pub fn span(&self) -> Span {
|
pub fn span(&self) -> Span {
|
||||||
match *self {
|
match *self {
|
||||||
MiscVariable(a) => a,
|
MiscVariable(a)
|
||||||
PatternRegion(a) => a,
|
| PatternRegion(a)
|
||||||
AddrOfRegion(a) => a,
|
| AddrOfRegion(a)
|
||||||
Autoref(a) => a,
|
| Autoref(a, _)
|
||||||
Coercion(a) => a,
|
| Coercion(a)
|
||||||
EarlyBoundRegion(a, ..) => a,
|
| EarlyBoundRegion(a, ..)
|
||||||
LateBoundRegion(a, ..) => a,
|
| LateBoundRegion(a, ..)
|
||||||
|
| UpvarRegion(_, a) => a,
|
||||||
BoundRegionInCoherence(_) => rustc_span::DUMMY_SP,
|
BoundRegionInCoherence(_) => rustc_span::DUMMY_SP,
|
||||||
UpvarRegion(_, a) => a,
|
|
||||||
NLL(..) => bug!("NLL variable used with `span`"),
|
NLL(..) => bug!("NLL variable used with `span`"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
//! This API is completely unstable and subject to change.
|
//! This API is completely unstable and subject to change.
|
||||||
|
|
||||||
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/")]
|
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/")]
|
||||||
|
#![feature(bindings_after_at)]
|
||||||
#![feature(bool_to_option)]
|
#![feature(bool_to_option)]
|
||||||
#![feature(box_patterns)]
|
#![feature(box_patterns)]
|
||||||
#![feature(box_syntax)]
|
#![feature(box_syntax)]
|
||||||
|
|
|
@ -300,6 +300,8 @@ pub enum ObligationCauseCode<'tcx> {
|
||||||
/// Method receiver
|
/// Method receiver
|
||||||
MethodReceiver,
|
MethodReceiver,
|
||||||
|
|
||||||
|
UnifyReceiver(Rc<ty::AssocItem>),
|
||||||
|
|
||||||
/// `return` with no expression
|
/// `return` with no expression
|
||||||
ReturnNoExpression,
|
ReturnNoExpression,
|
||||||
|
|
||||||
|
|
|
@ -213,6 +213,7 @@ impl<'a, 'tcx> Lift<'tcx> for traits::ObligationCauseCode<'a> {
|
||||||
super::StartFunctionType => Some(super::StartFunctionType),
|
super::StartFunctionType => Some(super::StartFunctionType),
|
||||||
super::IntrinsicType => Some(super::IntrinsicType),
|
super::IntrinsicType => Some(super::IntrinsicType),
|
||||||
super::MethodReceiver => Some(super::MethodReceiver),
|
super::MethodReceiver => Some(super::MethodReceiver),
|
||||||
|
super::UnifyReceiver(ref assoc) => Some(super::UnifyReceiver(assoc.clone())),
|
||||||
super::BlockTailExpression(id) => Some(super::BlockTailExpression(id)),
|
super::BlockTailExpression(id) => Some(super::BlockTailExpression(id)),
|
||||||
super::TrivialBound => Some(super::TrivialBound),
|
super::TrivialBound => Some(super::TrivialBound),
|
||||||
}
|
}
|
||||||
|
|
|
@ -136,7 +136,7 @@ pub struct ResolverOutputs {
|
||||||
pub extern_prelude: FxHashMap<Symbol, bool>,
|
pub extern_prelude: FxHashMap<Symbol, bool>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy, PartialEq, Eq, Debug, HashStable)]
|
#[derive(Clone, Copy, PartialEq, Eq, Debug, HashStable, Hash)]
|
||||||
pub enum AssocItemContainer {
|
pub enum AssocItemContainer {
|
||||||
TraitContainer(DefId),
|
TraitContainer(DefId),
|
||||||
ImplContainer(DefId),
|
ImplContainer(DefId),
|
||||||
|
@ -184,7 +184,7 @@ pub enum ImplPolarity {
|
||||||
Reservation,
|
Reservation,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, PartialEq, HashStable)]
|
#[derive(Copy, Clone, Debug, PartialEq, HashStable, Eq, Hash)]
|
||||||
pub struct AssocItem {
|
pub struct AssocItem {
|
||||||
pub def_id: DefId,
|
pub def_id: DefId,
|
||||||
#[stable_hasher(project(name))]
|
#[stable_hasher(project(name))]
|
||||||
|
@ -199,7 +199,7 @@ pub struct AssocItem {
|
||||||
pub fn_has_self_parameter: bool,
|
pub fn_has_self_parameter: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, PartialEq, Debug, HashStable)]
|
#[derive(Copy, Clone, PartialEq, Debug, HashStable, Eq, Hash)]
|
||||||
pub enum AssocKind {
|
pub enum AssocKind {
|
||||||
Const,
|
Const,
|
||||||
Fn,
|
Fn,
|
||||||
|
@ -316,7 +316,7 @@ impl<'tcx> AssociatedItems<'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq, Eq, Copy, RustcEncodable, RustcDecodable, HashStable)]
|
#[derive(Clone, Debug, PartialEq, Eq, Copy, RustcEncodable, RustcDecodable, HashStable, Hash)]
|
||||||
pub enum Visibility {
|
pub enum Visibility {
|
||||||
/// Visible everywhere (including in other crates).
|
/// Visible everywhere (including in other crates).
|
||||||
Public,
|
Public,
|
||||||
|
|
|
@ -1706,6 +1706,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
|
||||||
| ObligationCauseCode::IntrinsicType
|
| ObligationCauseCode::IntrinsicType
|
||||||
| ObligationCauseCode::MethodReceiver
|
| ObligationCauseCode::MethodReceiver
|
||||||
| ObligationCauseCode::ReturnNoExpression
|
| ObligationCauseCode::ReturnNoExpression
|
||||||
|
| ObligationCauseCode::UnifyReceiver(_)
|
||||||
| ObligationCauseCode::MiscObligation => {}
|
| ObligationCauseCode::MiscObligation => {}
|
||||||
ObligationCauseCode::SliceOrArrayElem => {
|
ObligationCauseCode::SliceOrArrayElem => {
|
||||||
err.note("slice and array elements must have `Sized` type");
|
err.note("slice and array elements must have `Sized` type");
|
||||||
|
|
|
@ -6,6 +6,7 @@ use crate::hir::def_id::DefId;
|
||||||
use crate::hir::GenericArg;
|
use crate::hir::GenericArg;
|
||||||
use rustc_hir as hir;
|
use rustc_hir as hir;
|
||||||
use rustc_infer::infer::{self, InferOk};
|
use rustc_infer::infer::{self, InferOk};
|
||||||
|
use rustc_middle::traits::ObligationCauseCode;
|
||||||
use rustc_middle::ty::adjustment::{Adjust, Adjustment, PointerCast};
|
use rustc_middle::ty::adjustment::{Adjust, Adjustment, PointerCast};
|
||||||
use rustc_middle::ty::adjustment::{AllowTwoPhase, AutoBorrow, AutoBorrowMutability};
|
use rustc_middle::ty::adjustment::{AllowTwoPhase, AutoBorrow, AutoBorrowMutability};
|
||||||
use rustc_middle::ty::fold::TypeFoldable;
|
use rustc_middle::ty::fold::TypeFoldable;
|
||||||
|
@ -15,6 +16,7 @@ use rustc_span::Span;
|
||||||
use rustc_trait_selection::traits;
|
use rustc_trait_selection::traits;
|
||||||
|
|
||||||
use std::ops::Deref;
|
use std::ops::Deref;
|
||||||
|
use std::rc::Rc;
|
||||||
|
|
||||||
struct ConfirmContext<'a, 'tcx> {
|
struct ConfirmContext<'a, 'tcx> {
|
||||||
fcx: &'a FnCtxt<'a, 'tcx>,
|
fcx: &'a FnCtxt<'a, 'tcx>,
|
||||||
|
@ -91,7 +93,11 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
|
||||||
// signature (which is also done during probing).
|
// signature (which is also done during probing).
|
||||||
let method_sig_rcvr =
|
let method_sig_rcvr =
|
||||||
self.normalize_associated_types_in(self.span, &method_sig.inputs()[0]);
|
self.normalize_associated_types_in(self.span, &method_sig.inputs()[0]);
|
||||||
self.unify_receivers(self_ty, method_sig_rcvr);
|
debug!(
|
||||||
|
"confirm: self_ty={:?} method_sig_rcvr={:?} method_sig={:?} method_predicates={:?}",
|
||||||
|
self_ty, method_sig_rcvr, method_sig, method_predicates
|
||||||
|
);
|
||||||
|
self.unify_receivers(self_ty, method_sig_rcvr, &pick);
|
||||||
|
|
||||||
let (method_sig, method_predicates) =
|
let (method_sig, method_predicates) =
|
||||||
self.normalize_associated_types_in(self.span, &(method_sig, method_predicates));
|
self.normalize_associated_types_in(self.span, &(method_sig, method_predicates));
|
||||||
|
@ -150,7 +156,7 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
|
||||||
self.structurally_resolved_type(autoderef.span(), autoderef.final_ty(false));
|
self.structurally_resolved_type(autoderef.span(), autoderef.final_ty(false));
|
||||||
|
|
||||||
if let Some(mutbl) = pick.autoref {
|
if let Some(mutbl) = pick.autoref {
|
||||||
let region = self.next_region_var(infer::Autoref(self.span));
|
let region = self.next_region_var(infer::Autoref(self.span, pick.item));
|
||||||
target = self.tcx.mk_ref(region, ty::TypeAndMut { mutbl, ty: target });
|
target = self.tcx.mk_ref(region, ty::TypeAndMut { mutbl, ty: target });
|
||||||
let mutbl = match mutbl {
|
let mutbl = match mutbl {
|
||||||
hir::Mutability::Not => AutoBorrowMutability::Not,
|
hir::Mutability::Not => AutoBorrowMutability::Not,
|
||||||
|
@ -334,8 +340,18 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn unify_receivers(&mut self, self_ty: Ty<'tcx>, method_self_ty: Ty<'tcx>) {
|
fn unify_receivers(
|
||||||
match self.at(&self.misc(self.span), self.param_env).sup(method_self_ty, self_ty) {
|
&mut self,
|
||||||
|
self_ty: Ty<'tcx>,
|
||||||
|
method_self_ty: Ty<'tcx>,
|
||||||
|
pick: &probe::Pick<'tcx>,
|
||||||
|
) {
|
||||||
|
debug!(
|
||||||
|
"unify_receivers: self_ty={:?} method_self_ty={:?} span={:?} pick={:?}",
|
||||||
|
self_ty, method_self_ty, self.span, pick
|
||||||
|
);
|
||||||
|
let cause = self.cause(self.span, ObligationCauseCode::UnifyReceiver(Rc::new(pick.item)));
|
||||||
|
match self.at(&cause, self.param_env).sup(method_self_ty, self_ty) {
|
||||||
Ok(InferOk { obligations, value: () }) => {
|
Ok(InferOk { obligations, value: () }) => {
|
||||||
self.register_predicates(obligations);
|
self.register_predicates(obligations);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,14 +0,0 @@
|
||||||
trait OtherTrait<'a> {}
|
|
||||||
impl<'a> OtherTrait<'a> for &'a () {}
|
|
||||||
|
|
||||||
trait ObjectTrait {}
|
|
||||||
|
|
||||||
impl dyn ObjectTrait {
|
|
||||||
fn use_self(&self) -> &() { panic!() }
|
|
||||||
}
|
|
||||||
|
|
||||||
fn use_it<'a>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> + 'a {
|
|
||||||
val.use_self() //~ ERROR mismatched types
|
|
||||||
}
|
|
||||||
|
|
||||||
fn main() {}
|
|
|
@ -1,18 +0,0 @@
|
||||||
error[E0308]: mismatched types
|
|
||||||
--> $DIR/impl-on-dyn-trait-with-implicit-static-bound-without-suggestion.rs:11:9
|
|
||||||
|
|
|
||||||
LL | val.use_self()
|
|
||||||
| ^^^^^^^^ lifetime mismatch
|
|
||||||
|
|
|
||||||
= note: expected reference `&(dyn ObjectTrait + 'static)`
|
|
||||||
found reference `&(dyn ObjectTrait + 'a)`
|
|
||||||
note: the lifetime `'a` as defined on the function body at 10:11...
|
|
||||||
--> $DIR/impl-on-dyn-trait-with-implicit-static-bound-without-suggestion.rs:10:11
|
|
||||||
|
|
|
||||||
LL | fn use_it<'a>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> + 'a {
|
|
||||||
| ^^
|
|
||||||
= note: ...does not necessarily outlive the static lifetime
|
|
||||||
|
|
||||||
error: aborting due to previous error
|
|
||||||
|
|
||||||
For more information about this error, try `rustc --explain E0308`.
|
|
|
@ -9,10 +9,12 @@ mod foo {
|
||||||
trait MyTrait {
|
trait MyTrait {
|
||||||
fn use_self(&self) -> &();
|
fn use_self(&self) -> &();
|
||||||
}
|
}
|
||||||
|
trait Irrelevant {}
|
||||||
|
|
||||||
impl MyTrait for dyn ObjectTrait + '_ {
|
impl MyTrait for dyn ObjectTrait + '_ {
|
||||||
fn use_self(&self) -> &() { panic!() }
|
fn use_self(&self) -> &() { panic!() }
|
||||||
}
|
}
|
||||||
|
impl Irrelevant for dyn ObjectTrait {}
|
||||||
|
|
||||||
fn use_it<'a>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> + 'a {
|
fn use_it<'a>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> + 'a {
|
||||||
val.use_self() //~ ERROR cannot infer an appropriate lifetime
|
val.use_self() //~ ERROR cannot infer an appropriate lifetime
|
||||||
|
@ -24,14 +26,48 @@ mod bar {
|
||||||
trait MyTrait {
|
trait MyTrait {
|
||||||
fn use_self(&self) -> &();
|
fn use_self(&self) -> &();
|
||||||
}
|
}
|
||||||
|
trait Irrelevant {}
|
||||||
|
|
||||||
impl MyTrait for dyn ObjectTrait + '_ {
|
impl MyTrait for dyn ObjectTrait + '_ {
|
||||||
fn use_self(&self) -> &() { panic!() }
|
fn use_self(&self) -> &() { panic!() }
|
||||||
}
|
}
|
||||||
|
impl Irrelevant for dyn ObjectTrait {}
|
||||||
|
|
||||||
fn use_it<'a>(val: &'a dyn ObjectTrait) -> &'a () {
|
fn use_it<'a>(val: &'a dyn ObjectTrait) -> &'a () {
|
||||||
val.use_self() //~ ERROR cannot infer an appropriate lifetime
|
val.use_self() //~ ERROR cannot infer an appropriate lifetime
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mod baz {
|
||||||
|
trait ObjectTrait {}
|
||||||
|
trait MyTrait {
|
||||||
|
fn use_self(&self) -> &();
|
||||||
|
}
|
||||||
|
trait Irrelevant {}
|
||||||
|
|
||||||
|
impl MyTrait for Box<dyn ObjectTrait + '_> {
|
||||||
|
fn use_self(&self) -> &() { panic!() }
|
||||||
|
}
|
||||||
|
impl Irrelevant for Box<dyn ObjectTrait> {}
|
||||||
|
|
||||||
|
fn use_it<'a>(val: &'a Box<dyn ObjectTrait + 'a>) -> &'a () {
|
||||||
|
val.use_self() //~ ERROR cannot infer an appropriate lifetime
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mod bat {
|
||||||
|
trait OtherTrait<'a> {}
|
||||||
|
impl<'a> OtherTrait<'a> for &'a () {}
|
||||||
|
|
||||||
|
trait ObjectTrait {}
|
||||||
|
|
||||||
|
impl dyn ObjectTrait + '_ {
|
||||||
|
fn use_self(&self) -> &() { panic!() }
|
||||||
|
}
|
||||||
|
|
||||||
|
fn use_it<'a>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> + 'a {
|
||||||
|
val.use_self() //~ ERROR cannot infer an appropriate lifetime
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn main() {}
|
fn main() {}
|
||||||
|
|
|
@ -0,0 +1,22 @@
|
||||||
|
error[E0521]: borrowed data escapes outside of function
|
||||||
|
--> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:20:9
|
||||||
|
|
|
||||||
|
LL | fn use_it<'a>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> + 'a {
|
||||||
|
| --- `val` is a reference that is only valid in the function body
|
||||||
|
LL | val.use_self()
|
||||||
|
| ^^^^^^^^^^^^^^ `val` escapes the function body here
|
||||||
|
|
|
||||||
|
= help: consider replacing `'a` with `'static`
|
||||||
|
|
||||||
|
error[E0521]: borrowed data escapes outside of function
|
||||||
|
--> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:69:9
|
||||||
|
|
|
||||||
|
LL | fn use_it<'a>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> + 'a {
|
||||||
|
| --- `val` is a reference that is only valid in the function body
|
||||||
|
LL | val.use_self()
|
||||||
|
| ^^^^^^^^^^^^^^ `val` escapes the function body here
|
||||||
|
|
|
||||||
|
= help: consider replacing `'a` with `'static`
|
||||||
|
|
||||||
|
error: aborting due to 2 previous errors
|
||||||
|
|
|
@ -9,10 +9,12 @@ mod foo {
|
||||||
trait MyTrait {
|
trait MyTrait {
|
||||||
fn use_self(&self) -> &();
|
fn use_self(&self) -> &();
|
||||||
}
|
}
|
||||||
|
trait Irrelevant {}
|
||||||
|
|
||||||
impl MyTrait for dyn ObjectTrait {
|
impl MyTrait for dyn ObjectTrait {
|
||||||
fn use_self(&self) -> &() { panic!() }
|
fn use_self(&self) -> &() { panic!() }
|
||||||
}
|
}
|
||||||
|
impl Irrelevant for dyn ObjectTrait {}
|
||||||
|
|
||||||
fn use_it<'a>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> + 'a {
|
fn use_it<'a>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> + 'a {
|
||||||
val.use_self() //~ ERROR cannot infer an appropriate lifetime
|
val.use_self() //~ ERROR cannot infer an appropriate lifetime
|
||||||
|
@ -24,14 +26,48 @@ mod bar {
|
||||||
trait MyTrait {
|
trait MyTrait {
|
||||||
fn use_self(&self) -> &();
|
fn use_self(&self) -> &();
|
||||||
}
|
}
|
||||||
|
trait Irrelevant {}
|
||||||
|
|
||||||
impl MyTrait for dyn ObjectTrait {
|
impl MyTrait for dyn ObjectTrait {
|
||||||
fn use_self(&self) -> &() { panic!() }
|
fn use_self(&self) -> &() { panic!() }
|
||||||
}
|
}
|
||||||
|
impl Irrelevant for dyn ObjectTrait {}
|
||||||
|
|
||||||
fn use_it<'a>(val: &'a dyn ObjectTrait) -> &'a () {
|
fn use_it<'a>(val: &'a dyn ObjectTrait) -> &'a () {
|
||||||
val.use_self() //~ ERROR cannot infer an appropriate lifetime
|
val.use_self() //~ ERROR cannot infer an appropriate lifetime
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mod baz {
|
||||||
|
trait ObjectTrait {}
|
||||||
|
trait MyTrait {
|
||||||
|
fn use_self(&self) -> &();
|
||||||
|
}
|
||||||
|
trait Irrelevant {}
|
||||||
|
|
||||||
|
impl MyTrait for Box<dyn ObjectTrait> {
|
||||||
|
fn use_self(&self) -> &() { panic!() }
|
||||||
|
}
|
||||||
|
impl Irrelevant for Box<dyn ObjectTrait> {}
|
||||||
|
|
||||||
|
fn use_it<'a>(val: &'a Box<dyn ObjectTrait + 'a>) -> &'a () {
|
||||||
|
val.use_self() //~ ERROR cannot infer an appropriate lifetime
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mod bat {
|
||||||
|
trait OtherTrait<'a> {}
|
||||||
|
impl<'a> OtherTrait<'a> for &'a () {}
|
||||||
|
|
||||||
|
trait ObjectTrait {}
|
||||||
|
|
||||||
|
impl dyn ObjectTrait {
|
||||||
|
fn use_self(&self) -> &() { panic!() }
|
||||||
|
}
|
||||||
|
|
||||||
|
fn use_it<'a>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> + 'a {
|
||||||
|
val.use_self() //~ ERROR cannot infer an appropriate lifetime
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn main() {}
|
fn main() {}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
error[E0759]: cannot infer an appropriate lifetime
|
error[E0759]: cannot infer an appropriate lifetime
|
||||||
--> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:18:13
|
--> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:20:13
|
||||||
|
|
|
|
||||||
LL | fn use_it<'a>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> + 'a {
|
LL | fn use_it<'a>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> + 'a {
|
||||||
| ------------------- this data with lifetime `'a`...
|
| ------------------- this data with lifetime `'a`...
|
||||||
|
@ -12,7 +12,20 @@ LL | impl MyTrait for dyn ObjectTrait + '_ {
|
||||||
| ^^^^
|
| ^^^^
|
||||||
|
|
||||||
error[E0759]: cannot infer an appropriate lifetime
|
error[E0759]: cannot infer an appropriate lifetime
|
||||||
--> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:33:13
|
--> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:69:13
|
||||||
|
|
|
||||||
|
LL | fn use_it<'a>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> + 'a {
|
||||||
|
| ------------------- this data with lifetime `'a`...
|
||||||
|
LL | val.use_self()
|
||||||
|
| ^^^^^^^^ ...is captured and required to live as long as `'static` here
|
||||||
|
|
|
||||||
|
help: this `impl` introduces an implicit `'static` requirement, consider changing it
|
||||||
|
|
|
||||||
|
LL | impl dyn ObjectTrait + '_ {
|
||||||
|
| ^^^^
|
||||||
|
|
||||||
|
error[E0759]: cannot infer an appropriate lifetime
|
||||||
|
--> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:37:13
|
||||||
|
|
|
|
||||||
LL | fn use_it<'a>(val: &'a dyn ObjectTrait) -> &'a () {
|
LL | fn use_it<'a>(val: &'a dyn ObjectTrait) -> &'a () {
|
||||||
| ------------------- this data with lifetime `'a`...
|
| ------------------- this data with lifetime `'a`...
|
||||||
|
@ -24,6 +37,19 @@ help: this `impl` introduces an implicit `'static` requirement, consider changin
|
||||||
LL | impl MyTrait for dyn ObjectTrait + '_ {
|
LL | impl MyTrait for dyn ObjectTrait + '_ {
|
||||||
| ^^^^
|
| ^^^^
|
||||||
|
|
||||||
error: aborting due to 2 previous errors
|
error[E0759]: cannot infer an appropriate lifetime
|
||||||
|
--> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:54:13
|
||||||
|
|
|
||||||
|
LL | fn use_it<'a>(val: &'a Box<dyn ObjectTrait + 'a>) -> &'a () {
|
||||||
|
| ----------------------------- this data with lifetime `'a`...
|
||||||
|
LL | val.use_self()
|
||||||
|
| ^^^^^^^^ ...is captured and required to live as long as `'static` here
|
||||||
|
|
|
||||||
|
help: this `impl` introduces an implicit `'static` requirement, consider changing it
|
||||||
|
|
|
||||||
|
LL | impl MyTrait for Box<dyn ObjectTrait + '_> {
|
||||||
|
| ^^^^
|
||||||
|
|
||||||
|
error: aborting due to 4 previous errors
|
||||||
|
|
||||||
For more information about this error, try `rustc --explain E0759`.
|
For more information about this error, try `rustc --explain E0759`.
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue