Auto merge of #93803 - cjgillot:unify-bounds, r=oli-obk

Handle generic bounds in a uniform way in HIR

Generic bounds in HIR used to be split between bounds in the parameter definition and bounds in a where clause. This PR attempts to store all of those as where predicates.

This effectively desugars
```rust
fn foo<T: Default, U>(x: impl Copy) where U: Clone
```
into
```rust
fn foo<T, U, _V>(x: _V) where T: Default, U: Clone, _V: Copy
```
(where _V is actually hidden and called "impl Copy").

I managed to make compiler warnings more uniform.
About rustdoc: is making this desugaring user-visible acceptable?
About clippy: I don't understand the subtle logic in the `needless-lifetimes` lint.

r? `@estebank`
This commit is contained in:
bors 2022-04-30 13:52:29 +00:00
commit d201c812d4
120 changed files with 1500 additions and 1464 deletions

View File

@ -397,6 +397,7 @@ pub struct GenericParam {
pub bounds: GenericBounds,
pub is_placeholder: bool,
pub kind: GenericParamKind,
pub colon_span: Option<Span>,
}
impl GenericParam {

View File

@ -867,9 +867,12 @@ pub fn noop_flat_map_generic_param<T: MutVisitor>(
mut param: GenericParam,
vis: &mut T,
) -> SmallVec<[GenericParam; 1]> {
let GenericParam { id, ident, attrs, bounds, kind, is_placeholder: _ } = &mut param;
let GenericParam { id, ident, attrs, bounds, kind, colon_span, is_placeholder: _ } = &mut param;
vis.visit_id(id);
vis.visit_ident(ident);
if let Some(ref mut colon_span) = colon_span {
vis.visit_span(colon_span);
}
visit_thin_attrs(attrs, vis);
visit_vec(bounds, |bound| noop_visit_param_bound(bound, vis));
match kind {

View File

@ -267,9 +267,14 @@ impl<'hir> LoweringContext<'_, 'hir> {
this.lower_maybe_async_body(span, &decl, asyncness, body.as_deref());
let (generics, decl) =
this.add_implicit_generics(generics, id, |this, idty| {
this.add_implicit_generics(generics, id, |this, idty, idpb| {
let ret_id = asyncness.opt_return_id();
this.lower_fn_decl(&decl, Some((id, idty)), FnDeclKind::Fn, ret_id)
this.lower_fn_decl(
&decl,
Some((id, idty, idpb)),
FnDeclKind::Fn,
ret_id,
)
});
let sig = hir::FnSig {
decl,
@ -384,7 +389,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
// lifetime to be added, but rather a reference to a
// parent lifetime.
let (generics, (trait_ref, lowered_ty)) =
self.add_implicit_generics(ast_generics, id, |this, _| {
self.add_implicit_generics(ast_generics, id, |this, _, _| {
let trait_ref = trait_ref.as_ref().map(|trait_ref| {
this.lower_trait_ref(
trait_ref,
@ -410,7 +415,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
ImplPolarity::Positive => ImplPolarity::Positive,
ImplPolarity::Negative(s) => ImplPolarity::Negative(self.lower_span(s)),
};
hir::ItemKind::Impl(hir::Impl {
hir::ItemKind::Impl(self.arena.alloc(hir::Impl {
unsafety: self.lower_unsafety(unsafety),
polarity,
defaultness,
@ -420,7 +425,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
of_trait: trait_ref,
self_ty: lowered_ty,
items: new_impl_items,
})
}))
}
ItemKind::Trait(box Trait {
is_auto,
@ -649,7 +654,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
ForeignItemKind::Fn(box Fn { ref sig, ref generics, .. }) => {
let fdec = &sig.decl;
let (generics, (fn_dec, fn_args)) =
self.add_implicit_generics(generics, i.id, |this, _| {
self.add_implicit_generics(generics, i.id, |this, _, _| {
(
// Disallow `impl Trait` in foreign items.
this.lower_fn_decl(fdec, None, FnDeclKind::ExternFn, None),
@ -1226,10 +1231,10 @@ impl<'hir> LoweringContext<'_, 'hir> {
id: NodeId,
kind: FnDeclKind,
is_async: Option<NodeId>,
) -> (hir::Generics<'hir>, hir::FnSig<'hir>) {
) -> (&'hir hir::Generics<'hir>, hir::FnSig<'hir>) {
let header = self.lower_fn_header(sig.header);
let (generics, decl) = self.add_implicit_generics(generics, id, |this, idty| {
this.lower_fn_decl(&sig.decl, Some((id, idty)), kind, is_async)
let (generics, decl) = self.add_implicit_generics(generics, id, |this, idty, idpb| {
this.lower_fn_decl(&sig.decl, Some((id, idty, idpb)), kind, is_async)
});
(generics, hir::FnSig { header, decl, span: self.lower_span(sig.span) })
}
@ -1289,7 +1294,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
pub(super) fn lower_generics_mut(
&mut self,
generics: &Generics,
itctx: ImplTraitContext<'_, 'hir>,
mut itctx: ImplTraitContext<'_, 'hir>,
) -> GenericsCtor<'hir> {
// Error if `?Trait` bounds in where clauses don't refer directly to type parameters.
// Note: we used to clone these bounds directly onto the type parameter (and avoid lowering
@ -1338,9 +1343,24 @@ impl<'hir> LoweringContext<'_, 'hir> {
}
}
let mut predicates = SmallVec::new();
predicates.extend(generics.params.iter().filter_map(|param| {
let bounds = self.lower_param_bounds(&param.bounds, itctx.reborrow());
self.lower_generic_bound_predicate(param.ident, param.id, &param.kind, bounds)
}));
predicates.extend(
generics
.where_clause
.predicates
.iter()
.map(|predicate| self.lower_where_predicate(predicate)),
);
GenericsCtor {
params: self.lower_generic_params_mut(&generics.params, itctx).collect(),
where_clause: self.lower_where_clause(&generics.where_clause),
params: self.lower_generic_params_mut(&generics.params).collect(),
predicates,
has_where_clause: !generics.where_clause.predicates.is_empty(),
where_clause_span: self.lower_span(generics.where_clause.span),
span: self.lower_span(generics.span),
}
}
@ -1349,17 +1369,74 @@ impl<'hir> LoweringContext<'_, 'hir> {
&mut self,
generics: &Generics,
itctx: ImplTraitContext<'_, 'hir>,
) -> hir::Generics<'hir> {
) -> &'hir hir::Generics<'hir> {
let generics_ctor = self.lower_generics_mut(generics, itctx);
generics_ctor.into_generics(self.arena)
}
fn lower_where_clause(&mut self, wc: &WhereClause) -> hir::WhereClause<'hir> {
hir::WhereClause {
predicates: self.arena.alloc_from_iter(
wc.predicates.iter().map(|predicate| self.lower_where_predicate(predicate)),
),
span: self.lower_span(wc.span),
pub(super) fn lower_generic_bound_predicate(
&mut self,
ident: Ident,
id: NodeId,
kind: &GenericParamKind,
bounds: &'hir [hir::GenericBound<'hir>],
) -> Option<hir::WherePredicate<'hir>> {
// Do not create a clause if we do not have anything inside it.
if bounds.is_empty() {
return None;
}
let ident = self.lower_ident(ident);
let param_span = ident.span;
let span = bounds
.iter()
.fold(Some(param_span.shrink_to_hi()), |span: Option<Span>, bound| {
let bound_span = bound.span();
// We include bounds that come from a `#[derive(_)]` but point at the user's code,
// as we use this method to get a span appropriate for suggestions.
if !bound_span.can_be_used_for_suggestions() {
None
} else if let Some(span) = span {
Some(span.to(bound_span))
} else {
Some(bound_span)
}
})
.unwrap_or(param_span.shrink_to_hi());
match kind {
GenericParamKind::Const { .. } => None,
GenericParamKind::Type { .. } => {
let def_id = self.resolver.local_def_id(id).to_def_id();
let ty_path = self.arena.alloc(hir::Path {
span: param_span,
res: Res::Def(DefKind::TyParam, def_id),
segments: self.arena.alloc_from_iter([hir::PathSegment::from_ident(ident)]),
});
let ty_id = self.next_id();
let bounded_ty =
self.ty_path(ty_id, param_span, hir::QPath::Resolved(None, ty_path));
Some(hir::WherePredicate::BoundPredicate(hir::WhereBoundPredicate {
bounded_ty: self.arena.alloc(bounded_ty),
bounds,
span,
bound_generic_params: &[],
in_where_clause: false,
}))
}
GenericParamKind::Lifetime => {
let ident_span = self.lower_span(ident.span);
let ident = self.lower_ident(ident);
let res = self.resolver.get_lifetime_res(id).unwrap_or_else(|| {
panic!("Missing resolution for lifetime {:?} at {:?}", id, ident.span)
});
let lt_id = self.resolver.next_node_id();
let lifetime = self.new_named_lifetime_with_res(lt_id, ident_span, ident, res);
Some(hir::WherePredicate::RegionPredicate(hir::WhereRegionPredicate {
lifetime,
span,
bounds,
in_where_clause: false,
}))
}
}
}
@ -1371,10 +1448,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
ref bounds,
span,
}) => hir::WherePredicate::BoundPredicate(hir::WhereBoundPredicate {
bound_generic_params: self.lower_generic_params(
bound_generic_params,
ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
),
bound_generic_params: self.lower_generic_params(bound_generic_params),
bounded_ty: self
.lower_ty(bounded_ty, ImplTraitContext::Disallowed(ImplTraitPosition::Type)),
bounds: self.arena.alloc_from_iter(bounds.iter().map(|bound| {
@ -1384,6 +1458,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
)
})),
span: self.lower_span(span),
in_where_clause: true,
}),
WherePredicate::RegionPredicate(WhereRegionPredicate {
ref lifetime,
@ -1396,6 +1471,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
bounds,
ImplTraitContext::Disallowed(ImplTraitPosition::Bound),
),
in_where_clause: true,
}),
WherePredicate::EqPredicate(WhereEqPredicate { id, ref lhs_ty, ref rhs_ty, span }) => {
hir::WherePredicate::EqPredicate(hir::WhereEqPredicate {
@ -1414,16 +1490,20 @@ impl<'hir> LoweringContext<'_, 'hir> {
/// Helper struct for delayed construction of Generics.
pub(super) struct GenericsCtor<'hir> {
pub(super) params: SmallVec<[hir::GenericParam<'hir>; 4]>,
where_clause: hir::WhereClause<'hir>,
pub(super) predicates: SmallVec<[hir::WherePredicate<'hir>; 4]>,
has_where_clause: bool,
where_clause_span: Span,
span: Span,
}
impl<'hir> GenericsCtor<'hir> {
pub(super) fn into_generics(self, arena: &'hir Arena<'hir>) -> hir::Generics<'hir> {
hir::Generics {
pub(super) fn into_generics(self, arena: &'hir Arena<'hir>) -> &'hir hir::Generics<'hir> {
arena.alloc(hir::Generics {
params: arena.alloc_from_iter(self.params),
where_clause: self.where_clause,
predicates: arena.alloc_from_iter(self.predicates),
has_where_clause: self.has_where_clause,
where_clause_span: self.where_clause_span,
span: self.span,
}
})
}
}

View File

@ -259,7 +259,7 @@ enum ImplTraitContext<'b, 'a> {
/// equivalent to a fresh universal parameter like `fn foo<T: Debug>(x: T)`.
///
/// Newly generated parameters should be inserted into the given `Vec`.
Universal(&'b mut Vec<hir::GenericParam<'a>>, LocalDefId),
Universal(&'b mut Vec<hir::GenericParam<'a>>, &'b mut Vec<hir::WherePredicate<'a>>, LocalDefId),
/// Treat `impl Trait` as shorthand for a new opaque type.
/// Example: `fn foo() -> impl Debug`, where `impl Debug` is conceptually
@ -303,7 +303,7 @@ impl<'a> ImplTraitContext<'_, 'a> {
fn reborrow<'this>(&'this mut self) -> ImplTraitContext<'this, 'a> {
use self::ImplTraitContext::*;
match self {
Universal(params, parent) => Universal(params, *parent),
Universal(params, bounds, parent) => Universal(params, bounds, *parent),
ReturnPositionOpaqueTy { origin } => ReturnPositionOpaqueTy { origin: *origin },
TypeAliasesOpaqueTy => TypeAliasesOpaqueTy,
Disallowed(pos) => Disallowed(*pos),
@ -704,10 +704,10 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
Some(hir::GenericParam {
hir_id,
name,
bounds: &[],
span: self.lower_span(ident.span),
pure_wrt_drop: false,
kind: hir::GenericParamKind::Lifetime { kind },
colon_span: None,
})
}
@ -718,14 +718,23 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
&mut self,
generics: &Generics,
parent_node_id: NodeId,
f: impl FnOnce(&mut Self, &mut Vec<hir::GenericParam<'hir>>) -> T,
) -> (hir::Generics<'hir>, T) {
f: impl FnOnce(
&mut Self,
&mut Vec<hir::GenericParam<'hir>>,
&mut Vec<hir::WherePredicate<'hir>>,
) -> T,
) -> (&'hir hir::Generics<'hir>, T) {
let mut impl_trait_defs = Vec::new();
let mut impl_trait_bounds = Vec::new();
let mut lowered_generics = self.lower_generics_mut(
generics,
ImplTraitContext::Universal(&mut impl_trait_defs, self.current_hir_id_owner),
ImplTraitContext::Universal(
&mut impl_trait_defs,
&mut impl_trait_bounds,
self.current_hir_id_owner,
),
);
let res = f(self, &mut impl_trait_defs);
let res = f(self, &mut impl_trait_defs, &mut impl_trait_bounds);
let extra_lifetimes = self.resolver.take_extra_lifetime_params(parent_node_id);
lowered_generics.params.extend(
@ -736,6 +745,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
})
.chain(impl_trait_defs),
);
lowered_generics.predicates.extend(impl_trait_bounds);
let lowered_generics = lowered_generics.into_generics(self.arena);
(lowered_generics, res)
@ -999,7 +1009,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
// so desugar to
//
// fn foo(x: dyn Iterator<Item = impl Debug>)
ImplTraitContext::Universal(_, parent) if self.is_in_dyn_type => {
ImplTraitContext::Universal(_, _, parent) if self.is_in_dyn_type => {
parent_def_id = parent;
(true, itctx)
}
@ -1188,10 +1198,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
}
TyKind::BareFn(ref f) => self.with_lifetime_binder(t.id, |this| {
hir::TyKind::BareFn(this.arena.alloc(hir::BareFnTy {
generic_params: this.lower_generic_params(
&f.generic_params,
ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
),
generic_params: this.lower_generic_params(&f.generic_params),
unsafety: this.lower_unsafety(f.unsafety),
abi: this.lower_extern(f.ext),
decl: this.lower_fn_decl(&f.decl, None, FnDeclKind::Pointer, None),
@ -1274,13 +1281,21 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|this| this.lower_param_bounds(bounds, nested_itctx),
)
}
ImplTraitContext::Universal(in_band_ty_params, parent_def_id) => {
ImplTraitContext::Universal(
in_band_ty_params,
in_band_ty_bounds,
parent_def_id,
) => {
// Add a definition for the in-band `Param`.
let def_id = self.resolver.local_def_id(def_node_id);
let hir_bounds = self.lower_param_bounds(
bounds,
ImplTraitContext::Universal(in_band_ty_params, parent_def_id),
ImplTraitContext::Universal(
in_band_ty_params,
in_band_ty_bounds,
parent_def_id,
),
);
// Set the name to `impl Bound1 + Bound2`.
let ident = Ident::from_str_and_span(&pprust::ty_to_string(t), span);
@ -1288,10 +1303,18 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
hir_id: self.lower_node_id(def_node_id),
name: ParamName::Plain(self.lower_ident(ident)),
pure_wrt_drop: false,
bounds: hir_bounds,
span: self.lower_span(span),
kind: hir::GenericParamKind::Type { default: None, synthetic: true },
colon_span: None,
});
if let Some(preds) = self.lower_generic_bound_predicate(
ident,
def_node_id,
&GenericParamKind::Type { default: None },
hir_bounds,
) {
in_band_ty_bounds.push(preds)
}
hir::TyKind::Path(hir::QPath::Resolved(
None,
@ -1374,8 +1397,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
name: p_name,
span,
pure_wrt_drop: false,
bounds: &[],
kind: hir::GenericParamKind::Lifetime { kind },
colon_span: None,
}
},
));
@ -1383,11 +1406,13 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
debug!("lower_opaque_impl_trait: lifetime_defs={:#?}", lifetime_defs);
let opaque_ty_item = hir::OpaqueTy {
generics: hir::Generics {
generics: self.arena.alloc(hir::Generics {
params: lifetime_defs,
where_clause: hir::WhereClause { predicates: &[], span: lctx.lower_span(span) },
predicates: &[],
has_where_clause: false,
where_clause_span: lctx.lower_span(span),
span: lctx.lower_span(span),
},
}),
bounds: hir_bounds,
origin,
};
@ -1462,7 +1487,11 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
fn lower_fn_decl(
&mut self,
decl: &FnDecl,
mut in_band_ty_params: Option<(NodeId, &mut Vec<hir::GenericParam<'hir>>)>,
mut in_band_ty_params: Option<(
NodeId,
&mut Vec<hir::GenericParam<'hir>>,
&mut Vec<hir::WherePredicate<'hir>>,
)>,
kind: FnDeclKind,
make_ret_async: Option<NodeId>,
) -> &'hir hir::FnDecl<'hir> {
@ -1485,10 +1514,10 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
inputs = &inputs[..inputs.len() - 1];
}
let inputs = self.arena.alloc_from_iter(inputs.iter().map(|param| {
if let Some((_, ibty)) = &mut in_band_ty_params {
if let Some((_, ibty, ibpb)) = &mut in_band_ty_params {
self.lower_ty_direct(
&param.ty,
ImplTraitContext::Universal(ibty, self.current_hir_id_owner),
ImplTraitContext::Universal(ibty, ibpb, self.current_hir_id_owner),
)
} else {
self.lower_ty_direct(
@ -1517,7 +1546,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
match decl.output {
FnRetTy::Ty(ref ty) => {
let context = match in_band_ty_params {
Some((node_id, _)) if kind.impl_trait_return_allowed() => {
Some((node_id, _, _)) if kind.impl_trait_return_allowed() => {
let fn_def_id = self.resolver.local_def_id(node_id);
ImplTraitContext::ReturnPositionOpaqueTy {
origin: hir::OpaqueTyOrigin::FnReturn(fn_def_id),
@ -1708,18 +1737,20 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
name: p_name,
span,
pure_wrt_drop: false,
bounds: &[],
kind: hir::GenericParamKind::Lifetime { kind },
colon_span: None,
}
}));
debug!("lower_async_fn_ret_ty: generic_params={:#?}", generic_params);
let opaque_ty_item = hir::OpaqueTy {
generics: hir::Generics {
generics: this.arena.alloc(hir::Generics {
params: generic_params,
where_clause: hir::WhereClause { predicates: &[], span: this.lower_span(span) },
predicates: &[],
has_where_clause: false,
where_clause_span: this.lower_span(span),
span: this.lower_span(span),
},
}),
bounds: arena_vec![this; future_bound],
origin: hir::OpaqueTyOrigin::AsyncFn(fn_def_id),
};
@ -1923,26 +1954,15 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
fn lower_generic_params_mut<'s>(
&'s mut self,
params: &'s [GenericParam],
mut itctx: ImplTraitContext<'s, 'hir>,
) -> impl Iterator<Item = hir::GenericParam<'hir>> + Captures<'a> + Captures<'s> {
params.iter().map(move |param| self.lower_generic_param(param, itctx.reborrow()))
params.iter().map(move |param| self.lower_generic_param(param))
}
fn lower_generic_params(
&mut self,
params: &[GenericParam],
itctx: ImplTraitContext<'_, 'hir>,
) -> &'hir [hir::GenericParam<'hir>] {
self.arena.alloc_from_iter(self.lower_generic_params_mut(params, itctx))
fn lower_generic_params(&mut self, params: &[GenericParam]) -> &'hir [hir::GenericParam<'hir>] {
self.arena.alloc_from_iter(self.lower_generic_params_mut(params))
}
fn lower_generic_param(
&mut self,
param: &GenericParam,
mut itctx: ImplTraitContext<'_, 'hir>,
) -> hir::GenericParam<'hir> {
let bounds: Vec<_> = self.lower_param_bounds_mut(&param.bounds, itctx.reborrow()).collect();
fn lower_generic_param(&mut self, param: &GenericParam) -> hir::GenericParam<'hir> {
let (name, kind) = match param.kind {
GenericParamKind::Lifetime => {
let param_name = if param.ident.name == kw::StaticLifetime
@ -1989,8 +2009,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
name,
span: self.lower_span(param.span()),
pure_wrt_drop: self.sess.contains_name(&param.attrs, sym::may_dangle),
bounds: self.arena.alloc_from_iter(bounds),
kind,
colon_span: param.colon_span.map(|s| self.lower_span(s)),
}
}
@ -2012,8 +2032,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
p: &PolyTraitRef,
mut itctx: ImplTraitContext<'_, 'hir>,
) -> hir::PolyTraitRef<'hir> {
let bound_generic_params =
self.lower_generic_params(&p.bound_generic_params, itctx.reborrow());
let bound_generic_params = self.lower_generic_params(&p.bound_generic_params);
let trait_ref = self.with_lifetime_binder(p.trait_ref.ref_id, |this| {
this.lower_trait_ref(&p.trait_ref, itctx.reborrow())

View File

@ -95,6 +95,7 @@ fn dummy_annotatable() -> Annotatable {
bounds: Default::default(),
is_placeholder: false,
kind: GenericParamKind::Lifetime,
colon_span: None,
})
}

View File

@ -113,6 +113,7 @@ impl<'a> ExtCtxt<'a> {
bounds,
kind: ast::GenericParamKind::Type { default },
is_placeholder: false,
colon_span: None,
}
}

View File

@ -149,6 +149,7 @@ pub fn placeholder(
ident,
is_placeholder: true,
kind: ast::GenericParamKind::Lifetime,
colon_span: None,
}
}]),
AstFragmentKind::Params => AstFragment::Params(smallvec![ast::Param {

View File

@ -15,11 +15,13 @@ macro_rules! arena_types {
[] block: rustc_hir::Block<'tcx>,
[] bare_fn_ty: rustc_hir::BareFnTy<'tcx>,
[] body: rustc_hir::Body<'tcx>,
[] generics: rustc_hir::Generics<'tcx>,
[] generic_arg: rustc_hir::GenericArg<'tcx>,
[] generic_args: rustc_hir::GenericArgs<'tcx>,
[] generic_bound: rustc_hir::GenericBound<'tcx>,
[] generic_param: rustc_hir::GenericParam<'tcx>,
[] expr: rustc_hir::Expr<'tcx>,
[] impl_: rustc_hir::Impl<'tcx>,
[] let_expr: rustc_hir::Let<'tcx>,
[] expr_field: rustc_hir::ExprField<'tcx>,
[] pat_field: rustc_hir::PatField<'tcx>,

View File

@ -17,7 +17,7 @@ use rustc_error_messages::MultiSpan;
use rustc_index::vec::IndexVec;
use rustc_macros::HashStable_Generic;
use rustc_span::hygiene::MacroKind;
use rustc_span::source_map::{SourceMap, Spanned};
use rustc_span::source_map::Spanned;
use rustc_span::symbol::{kw, sym, Ident, Symbol};
use rustc_span::{def_id::LocalDefId, BytePos, Span, DUMMY_SP};
use rustc_target::asm::InlineAsmRegOrRegClass;
@ -496,61 +496,25 @@ pub enum GenericParamKind<'hir> {
pub struct GenericParam<'hir> {
pub hir_id: HirId,
pub name: ParamName,
pub bounds: GenericBounds<'hir>,
pub span: Span,
pub pure_wrt_drop: bool,
pub kind: GenericParamKind<'hir>,
pub colon_span: Option<Span>,
}
impl<'hir> GenericParam<'hir> {
pub fn bounds_span_for_suggestions(&self) -> Option<Span> {
self.bounds
.iter()
.fold(None, |span: Option<Span>, bound| {
// We include bounds that come from a `#[derive(_)]` but point at the user's code,
// as we use this method to get a span appropriate for suggestions.
if !bound.span().can_be_used_for_suggestions() {
None
} else {
let span = span.map(|s| s.to(bound.span())).unwrap_or_else(|| bound.span());
Some(span)
}
})
.map(|sp| sp.shrink_to_hi())
/// Synthetic type-parameters are inserted after normal ones.
/// In order for normal parameters to be able to refer to synthetic ones,
/// scans them first.
pub fn is_impl_trait(&self) -> bool {
matches!(self.kind, GenericParamKind::Type { synthetic: true, .. })
}
/// Returns the span of `:` after a generic parameter.
/// This can happen for `async fn`, e.g. `async fn f<'_>(&'_ self)`.
///
/// For example:
///
/// ```text
/// fn a<T:>()
/// ^
/// | here
/// here |
/// v
/// fn b<T :>()
///
/// fn c<T
///
/// :>()
/// ^
/// |
/// here
/// ```
pub fn colon_span_for_suggestions(&self, source_map: &SourceMap) -> Option<Span> {
let sp = source_map
.span_extend_while(self.span.shrink_to_hi(), |c| c.is_whitespace() || c == ':')
.ok()?;
let snippet = source_map.span_to_snippet(sp).ok()?;
let offset = snippet.find(':')?;
let colon_sp = sp
.with_lo(BytePos(sp.lo().0 + offset as u32))
.with_hi(BytePos(sp.lo().0 + (offset + ':'.len_utf8()) as u32));
Some(colon_sp)
/// See `lifetime_to_generic_param` in `rustc_ast_lowering` for more information.
pub fn is_elided_lifetime(&self) -> bool {
matches!(self.kind, GenericParamKind::Lifetime { kind: LifetimeParamKind::Elided })
}
}
@ -567,17 +531,22 @@ pub struct GenericParamCount {
#[derive(Debug, HashStable_Generic)]
pub struct Generics<'hir> {
pub params: &'hir [GenericParam<'hir>],
pub where_clause: WhereClause<'hir>,
pub predicates: &'hir [WherePredicate<'hir>],
pub has_where_clause: bool,
pub where_clause_span: Span,
pub span: Span,
}
impl<'hir> Generics<'hir> {
pub const fn empty() -> Generics<'hir> {
Generics {
pub const fn empty() -> &'hir Generics<'hir> {
const NOPE: Generics<'_> = Generics {
params: &[],
where_clause: WhereClause { predicates: &[], span: DUMMY_SP },
predicates: &[],
has_where_clause: false,
where_clause_span: DUMMY_SP,
span: DUMMY_SP,
}
};
&NOPE
}
pub fn get_named(&self, name: Symbol) -> Option<&GenericParam<'_>> {
@ -596,32 +565,122 @@ impl<'hir> Generics<'hir> {
self.params.iter().map(|p| p.span).collect::<Vec<Span>>().into()
}
}
}
/// A where-clause in a definition.
#[derive(Debug, HashStable_Generic)]
pub struct WhereClause<'hir> {
pub predicates: &'hir [WherePredicate<'hir>],
// Only valid if predicates aren't empty.
pub span: Span,
}
impl WhereClause<'_> {
pub fn span(&self) -> Option<Span> {
if self.predicates.is_empty() { None } else { Some(self.span) }
/// If there are generic parameters, return where to introduce a new one.
pub fn span_for_param_suggestion(&self) -> Option<Span> {
if self.params.iter().any(|p| self.span.contains(p.span)) {
// `fn foo<A>(t: impl Trait)`
// ^ suggest `, T: Trait` here
let span = self.span.with_lo(self.span.hi() - BytePos(1)).shrink_to_lo();
Some(span)
} else {
None
}
}
/// The `WhereClause` under normal circumstances points at either the predicates or the empty
pub fn where_clause_span(&self) -> Option<Span> {
if self.predicates.is_empty() { None } else { Some(self.where_clause_span) }
}
/// The `where_span` under normal circumstances points at either the predicates or the empty
/// space where the `where` clause should be. Only of use for diagnostic suggestions.
pub fn span_for_predicates_or_empty_place(&self) -> Span {
self.span
self.where_clause_span
}
/// `Span` where further predicates would be suggested, accounting for trailing commas, like
/// in `fn foo<T>(t: T) where T: Foo,` so we don't suggest two trailing commas.
pub fn tail_span_for_suggestion(&self) -> Span {
pub fn tail_span_for_predicate_suggestion(&self) -> Span {
let end = self.span_for_predicates_or_empty_place().shrink_to_hi();
self.predicates.last().map_or(end, |p| p.span()).shrink_to_hi().to(end)
if self.has_where_clause {
self.predicates
.iter()
.filter(|p| p.in_where_clause())
.last()
.map_or(end, |p| p.span())
.shrink_to_hi()
.to(end)
} else {
end
}
}
pub fn bounds_for_param(
&self,
param_def_id: LocalDefId,
) -> impl Iterator<Item = &WhereBoundPredicate<'_>> {
self.predicates.iter().filter_map(move |pred| match pred {
WherePredicate::BoundPredicate(bp) if bp.is_param_bound(param_def_id.to_def_id()) => {
Some(bp)
}
_ => None,
})
}
pub fn bounds_span_for_suggestions(&self, param_def_id: LocalDefId) -> Option<Span> {
self.bounds_for_param(param_def_id).flat_map(|bp| bp.bounds.iter().rev()).find_map(
|bound| {
// We include bounds that come from a `#[derive(_)]` but point at the user's code,
// as we use this method to get a span appropriate for suggestions.
let bs = bound.span();
if bs.can_be_used_for_suggestions() { Some(bs.shrink_to_hi()) } else { None }
},
)
}
pub fn span_for_predicate_removal(&self, pos: usize) -> Span {
let predicate = &self.predicates[pos];
let span = predicate.span();
if !predicate.in_where_clause() {
// <T: ?Sized, U>
// ^^^^^^^^
return span;
}
// We need to find out which comma to remove.
if pos < self.predicates.len() - 1 {
let next_pred = &self.predicates[pos + 1];
if next_pred.in_where_clause() {
// where T: ?Sized, Foo: Bar,
// ^^^^^^^^^^^
return span.until(next_pred.span());
}
}
if pos > 0 {
let prev_pred = &self.predicates[pos - 1];
if prev_pred.in_where_clause() {
// where Foo: Bar, T: ?Sized,
// ^^^^^^^^^^^
return prev_pred.span().shrink_to_hi().to(span);
}
}
// This is the only predicate in the where clause.
// where T: ?Sized
// ^^^^^^^^^^^^^^^
self.where_clause_span
}
pub fn span_for_bound_removal(&self, predicate_pos: usize, bound_pos: usize) -> Span {
let predicate = &self.predicates[predicate_pos];
let bounds = predicate.bounds();
if bounds.len() == 1 {
return self.span_for_predicate_removal(predicate_pos);
}
let span = bounds[bound_pos].span();
if bound_pos == 0 {
// where T: ?Sized + Bar, Foo: Bar,
// ^^^^^^^^^
span.to(bounds[1].span().shrink_to_lo())
} else {
// where T: Bar + ?Sized, Foo: Bar,
// ^^^^^^^^^
bounds[bound_pos - 1].span().shrink_to_hi().to(span)
}
}
}
@ -644,12 +703,29 @@ impl<'hir> WherePredicate<'hir> {
WherePredicate::EqPredicate(p) => p.span,
}
}
pub fn in_where_clause(&self) -> bool {
match self {
WherePredicate::BoundPredicate(p) => p.in_where_clause,
WherePredicate::RegionPredicate(p) => p.in_where_clause,
WherePredicate::EqPredicate(_) => false,
}
}
pub fn bounds(&self) -> GenericBounds<'hir> {
match self {
WherePredicate::BoundPredicate(p) => p.bounds,
WherePredicate::RegionPredicate(p) => p.bounds,
WherePredicate::EqPredicate(_) => &[],
}
}
}
/// A type bound (e.g., `for<'c> Foo: Send + Clone + 'c`).
#[derive(Debug, HashStable_Generic)]
pub struct WhereBoundPredicate<'hir> {
pub span: Span,
pub in_where_clause: bool,
/// Any generics from a `for` binding.
pub bound_generic_params: &'hir [GenericParam<'hir>],
/// The type being bounded.
@ -661,14 +737,7 @@ pub struct WhereBoundPredicate<'hir> {
impl<'hir> WhereBoundPredicate<'hir> {
/// Returns `true` if `param_def_id` matches the `bounded_ty` of this predicate.
pub fn is_param_bound(&self, param_def_id: DefId) -> bool {
let TyKind::Path(QPath::Resolved(None, path)) = self.bounded_ty.kind else {
return false;
};
match path.res {
Res::Def(DefKind::TyParam, def_id)
| Res::SelfTy { trait_: Some(def_id), alias_to: None } => def_id == param_def_id,
_ => false,
}
self.bounded_ty.as_generic_param().map_or(false, |(def_id, _)| def_id == param_def_id)
}
}
@ -676,6 +745,7 @@ impl<'hir> WhereBoundPredicate<'hir> {
#[derive(Debug, HashStable_Generic)]
pub struct WhereRegionPredicate<'hir> {
pub span: Span,
pub in_where_clause: bool,
pub lifetime: Lifetime,
pub bounds: GenericBounds<'hir>,
}
@ -2075,7 +2145,7 @@ impl TraitItemId {
pub struct TraitItem<'hir> {
pub ident: Ident,
pub def_id: LocalDefId,
pub generics: Generics<'hir>,
pub generics: &'hir Generics<'hir>,
pub kind: TraitItemKind<'hir>,
pub span: Span,
}
@ -2135,7 +2205,7 @@ impl ImplItemId {
pub struct ImplItem<'hir> {
pub ident: Ident,
pub def_id: LocalDefId,
pub generics: Generics<'hir>,
pub generics: &'hir Generics<'hir>,
pub kind: ImplItemKind<'hir>,
pub span: Span,
pub vis_span: Span,
@ -2241,6 +2311,23 @@ pub struct Ty<'hir> {
pub span: Span,
}
impl<'hir> Ty<'hir> {
/// Returns `true` if `param_def_id` matches the `bounded_ty` of this predicate.
pub fn as_generic_param(&self) -> Option<(DefId, Ident)> {
let TyKind::Path(QPath::Resolved(None, path)) = self.kind else {
return None;
};
let [segment] = &path.segments else {
return None;
};
match path.res {
Res::Def(DefKind::TyParam, def_id)
| Res::SelfTy { trait_: Some(def_id), alias_to: None } => Some((def_id, segment.ident)),
_ => None,
}
}
}
/// Not represented directly in the AST; referred to by name through a `ty_path`.
#[derive(Copy, Clone, PartialEq, Eq, Encodable, Decodable, Hash, Debug)]
#[derive(HashStable_Generic)]
@ -2340,7 +2427,7 @@ pub struct BareFnTy<'hir> {
#[derive(Debug, HashStable_Generic)]
pub struct OpaqueTy<'hir> {
pub generics: Generics<'hir>,
pub generics: &'hir Generics<'hir>,
pub bounds: GenericBounds<'hir>,
pub origin: OpaqueTyOrigin,
}
@ -2814,7 +2901,7 @@ pub enum ItemKind<'hir> {
/// A `const` item.
Const(&'hir Ty<'hir>, BodyId),
/// A function declaration.
Fn(FnSig<'hir>, Generics<'hir>, BodyId),
Fn(FnSig<'hir>, &'hir Generics<'hir>, BodyId),
/// A MBE macro definition (`macro_rules!` or `macro`).
Macro(ast::MacroDef, MacroKind),
/// A module.
@ -2824,22 +2911,22 @@ pub enum ItemKind<'hir> {
/// Module-level inline assembly (from `global_asm!`).
GlobalAsm(&'hir InlineAsm<'hir>),
/// A type alias, e.g., `type Foo = Bar<u8>`.
TyAlias(&'hir Ty<'hir>, Generics<'hir>),
TyAlias(&'hir Ty<'hir>, &'hir Generics<'hir>),
/// An opaque `impl Trait` type alias, e.g., `type Foo = impl Bar;`.
OpaqueTy(OpaqueTy<'hir>),
/// An enum definition, e.g., `enum Foo<A, B> {C<A>, D<B>}`.
Enum(EnumDef<'hir>, Generics<'hir>),
Enum(EnumDef<'hir>, &'hir Generics<'hir>),
/// A struct definition, e.g., `struct Foo<A> {x: A}`.
Struct(VariantData<'hir>, Generics<'hir>),
Struct(VariantData<'hir>, &'hir Generics<'hir>),
/// A union definition, e.g., `union Foo<A, B> {x: A, y: B}`.
Union(VariantData<'hir>, Generics<'hir>),
Union(VariantData<'hir>, &'hir Generics<'hir>),
/// A trait definition.
Trait(IsAuto, Unsafety, Generics<'hir>, GenericBounds<'hir>, &'hir [TraitItemRef]),
Trait(IsAuto, Unsafety, &'hir Generics<'hir>, GenericBounds<'hir>, &'hir [TraitItemRef]),
/// A trait alias.
TraitAlias(Generics<'hir>, GenericBounds<'hir>),
TraitAlias(&'hir Generics<'hir>, GenericBounds<'hir>),
/// An implementation, e.g., `impl<A> Trait for Foo { .. }`.
Impl(Impl<'hir>),
Impl(&'hir Impl<'hir>),
}
#[derive(Debug, HashStable_Generic)]
@ -2851,7 +2938,7 @@ pub struct Impl<'hir> {
// decoding as `Span`s cannot be decoded when a `Session` is not available.
pub defaultness_span: Option<Span>,
pub constness: Constness,
pub generics: Generics<'hir>,
pub generics: &'hir Generics<'hir>,
/// The trait being implemented, if any.
pub of_trait: Option<TraitRef<'hir>>,
@ -2993,7 +3080,7 @@ impl ForeignItem<'_> {
#[derive(Debug, HashStable_Generic)]
pub enum ForeignItemKind<'hir> {
/// A foreign function.
Fn(&'hir FnDecl<'hir>, &'hir [Ident], Generics<'hir>),
Fn(&'hir FnDecl<'hir>, &'hir [Ident], &'hir Generics<'hir>),
/// A foreign static item (`static ext: u8`).
Static(&'hir Ty<'hir>, Mutability),
/// A foreign type.
@ -3326,9 +3413,11 @@ mod size_asserts {
rustc_data_structures::static_assert_size!(super::QPath<'static>, 24);
rustc_data_structures::static_assert_size!(super::Ty<'static>, 72);
rustc_data_structures::static_assert_size!(super::GenericBound<'_>, 48);
rustc_data_structures::static_assert_size!(super::Generics<'static>, 56);
rustc_data_structures::static_assert_size!(super::Impl<'static>, 80);
rustc_data_structures::static_assert_size!(super::Item<'static>, 160);
rustc_data_structures::static_assert_size!(super::TraitItem<'static>, 128);
rustc_data_structures::static_assert_size!(super::ImplItem<'static>, 120);
rustc_data_structures::static_assert_size!(super::ForeignItem<'static>, 112);
rustc_data_structures::static_assert_size!(super::Item<'static>, 80);
rustc_data_structures::static_assert_size!(super::TraitItem<'static>, 88);
rustc_data_structures::static_assert_size!(super::ImplItem<'static>, 80);
rustc_data_structures::static_assert_size!(super::ForeignItem<'static>, 72);
}

View File

@ -619,7 +619,7 @@ pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item<'v>) {
visitor.visit_generics(generics);
walk_list!(visitor, visit_trait_ref, of_trait);
visitor.visit_ty(self_ty);
walk_list!(visitor, visit_impl_item_ref, items);
walk_list!(visitor, visit_impl_item_ref, *items);
}
ItemKind::Struct(ref struct_definition, ref generics)
| ItemKind::Union(ref struct_definition, ref generics) => {
@ -899,7 +899,6 @@ pub fn walk_generic_param<'v, V: Visitor<'v>>(visitor: &mut V, param: &'v Generi
}
}
}
walk_list!(visitor, visit_param_bound, param.bounds);
}
pub fn walk_const_param_default<'v, V: Visitor<'v>>(visitor: &mut V, ct: &'v AnonConst) {
@ -908,7 +907,7 @@ pub fn walk_const_param_default<'v, V: Visitor<'v>>(visitor: &mut V, ct: &'v Ano
pub fn walk_generics<'v, V: Visitor<'v>>(visitor: &mut V, generics: &'v Generics<'v>) {
walk_list!(visitor, visit_generic_param, generics.params);
walk_list!(visitor, visit_where_predicate, generics.where_clause.predicates);
walk_list!(visitor, visit_where_predicate, generics.predicates);
}
pub fn walk_where_predicate<'v, V: Visitor<'v>>(

View File

@ -445,7 +445,7 @@ impl<'a> State<'a> {
if let Some(bounds) = bounds {
self.print_bounds(":", bounds);
}
self.print_where_clause(&generics.where_clause);
self.print_where_clause(generics);
if let Some(ty) = ty {
self.space();
self.word_space("=");
@ -465,7 +465,7 @@ impl<'a> State<'a> {
self.print_generic_params(&generics.params);
self.end(); // end the inner ibox
self.print_where_clause(&generics.where_clause);
self.print_where_clause(generics);
self.space();
inner(self);
self.word(";");
@ -626,8 +626,8 @@ impl<'a> State<'a> {
items,
}) => {
self.head("");
self.print_defaultness(defaultness);
self.print_unsafety(unsafety);
self.print_defaultness(*defaultness);
self.print_unsafety(*unsafety);
self.word_nbsp("impl");
if !generics.params.is_empty() {
@ -635,7 +635,7 @@ impl<'a> State<'a> {
self.space();
}
if constness == hir::Constness::Const {
if *constness == hir::Constness::Const {
self.word_nbsp("const");
}
@ -650,12 +650,12 @@ impl<'a> State<'a> {
}
self.print_type(&self_ty);
self.print_where_clause(&generics.where_clause);
self.print_where_clause(generics);
self.space();
self.bopen();
self.print_inner_attributes(attrs);
for impl_item in items {
for impl_item in *items {
self.ann.nested(self, Nested::ImplItem(impl_item.id));
}
self.bclose(item.span);
@ -678,7 +678,7 @@ impl<'a> State<'a> {
}
}
self.print_bounds(":", real_bounds);
self.print_where_clause(&generics.where_clause);
self.print_where_clause(generics);
self.word(" ");
self.bopen();
for trait_item in trait_items {
@ -703,7 +703,7 @@ impl<'a> State<'a> {
}
self.nbsp();
self.print_bounds("=", real_bounds);
self.print_where_clause(&generics.where_clause);
self.print_where_clause(generics);
self.word(";");
self.end(); // end inner head-block
self.end(); // end outer head-block
@ -739,7 +739,7 @@ impl<'a> State<'a> {
self.head("enum");
self.print_name(name);
self.print_generic_params(&generics.params);
self.print_where_clause(&generics.where_clause);
self.print_where_clause(generics);
self.space();
self.print_variants(&enum_definition.variants, span)
}
@ -787,7 +787,7 @@ impl<'a> State<'a> {
});
self.pclose();
}
self.print_where_clause(&generics.where_clause);
self.print_where_clause(generics);
if print_finalizer {
self.word(";");
}
@ -795,7 +795,7 @@ impl<'a> State<'a> {
self.end() // close the outer-box
}
hir::VariantData::Struct(..) => {
self.print_where_clause(&generics.where_clause);
self.print_where_clause(generics);
self.nbsp();
self.bopen();
self.hardbreak_if_not_bol();
@ -1995,7 +1995,7 @@ impl<'a> State<'a> {
self.pclose();
self.print_fn_output(decl);
self.print_where_clause(&generics.where_clause)
self.print_where_clause(generics)
}
fn print_closure_params(&mut self, decl: &hir::FnDecl<'_>, body_id: hir::BodyId) {
@ -2096,21 +2096,8 @@ impl<'a> State<'a> {
self.print_ident(param.name.ident());
match param.kind {
GenericParamKind::Lifetime { .. } => {
let mut sep = ":";
for bound in param.bounds {
match bound {
GenericBound::Outlives(ref lt) => {
self.word(sep);
self.print_lifetime(lt);
sep = "+";
}
_ => panic!(),
}
}
}
GenericParamKind::Lifetime { .. } => {}
GenericParamKind::Type { ref default, .. } => {
self.print_bounds(":", param.bounds);
if let Some(default) = default {
self.space();
self.word_space("=");
@ -2133,15 +2120,15 @@ impl<'a> State<'a> {
self.print_ident(lifetime.name.ident())
}
pub fn print_where_clause(&mut self, where_clause: &hir::WhereClause<'_>) {
if where_clause.predicates.is_empty() {
pub fn print_where_clause(&mut self, generics: &hir::Generics<'_>) {
if generics.predicates.is_empty() {
return;
}
self.space();
self.word_space("where");
for (i, predicate) in where_clause.predicates.iter().enumerate() {
for (i, predicate) in generics.predicates.iter().enumerate() {
if i != 0 {
self.word_space(",");
}
@ -2236,11 +2223,7 @@ impl<'a> State<'a> {
) {
self.ibox(INDENT_UNIT);
self.print_formal_generic_params(generic_params);
let generics = hir::Generics {
params: &[],
where_clause: hir::WhereClause { predicates: &[], span: rustc_span::DUMMY_SP },
span: rustc_span::DUMMY_SP,
};
let generics = hir::Generics::empty();
self.print_fn(
decl,
hir::FnHeader {

View File

@ -2327,6 +2327,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
_ => span,
};
// type_param_span is (span, has_bounds)
let type_param_span = match (generics, bound_kind) {
(Some((_, ref generics, _)), GenericKind::Param(ref param)) => {
// Account for the case where `param` corresponds to `Self`,
@ -2337,25 +2338,18 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
// Get the `hir::Param` to verify whether it already has any bounds.
// We do this to avoid suggesting code that ends up as `T: 'a'b`,
// instead we suggest `T: 'a + 'b` in that case.
let id = hir.local_def_id_to_hir_id(def_id);
let mut has_bounds = false;
if let Node::GenericParam(param) = hir.get(id) {
has_bounds = !param.bounds.is_empty();
}
let sp = self.tcx.def_span(def_id);
let hir_id = self.tcx.hir().local_def_id_to_hir_id(def_id);
let ast_generics = self.tcx.hir().get_generics(hir_id.owner);
let bounds =
ast_generics.and_then(|g| g.bounds_span_for_suggestions(def_id));
// `sp` only covers `T`, change it so that it covers
// `T:` when appropriate
let is_impl_trait = bound_kind.to_string().starts_with("impl ");
let sp = if has_bounds && !is_impl_trait {
sp.to(self
.tcx
.sess
.source_map()
.next_point(self.tcx.sess.source_map().next_point(sp)))
if let Some(span) = bounds {
(span, true)
} else {
sp
};
(sp, has_bounds, is_impl_trait)
let sp = self.tcx.def_span(def_id);
(sp.shrink_to_hi(), false)
}
})
} else {
None
@ -2411,52 +2405,37 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
fn binding_suggestion<'tcx, S: fmt::Display>(
err: &mut Diagnostic,
type_param_span: Option<(Span, bool, bool)>,
type_param_span: Option<(Span, bool)>,
bound_kind: GenericKind<'tcx>,
sub: S,
) {
let msg = "consider adding an explicit lifetime bound";
if let Some((sp, has_lifetimes, is_impl_trait)) = type_param_span {
let suggestion = if is_impl_trait {
format!("{} + {}", bound_kind, sub)
} else {
let tail = if has_lifetimes { " + " } else { "" };
format!("{}: {}{}", bound_kind, sub, tail)
};
err.span_suggestion(
if let Some((sp, has_lifetimes)) = type_param_span {
let suggestion =
if has_lifetimes { format!(" + {}", sub) } else { format!(": {}", sub) };
err.span_suggestion_verbose(
sp,
&format!("{}...", msg),
suggestion,
Applicability::MaybeIncorrect, // Issue #41966
);
} else {
let consider = format!(
"{} {}...",
msg,
if type_param_span.map_or(false, |(_, _, is_impl_trait)| is_impl_trait) {
format!(" `{}` to `{}`", sub, bound_kind)
} else {
format!("`{}: {}`", bound_kind, sub)
},
);
let consider = format!("{} `{}: {}`...", msg, bound_kind, sub,);
err.help(&consider);
}
}
let new_binding_suggestion =
|err: &mut Diagnostic,
type_param_span: Option<(Span, bool, bool)>,
bound_kind: GenericKind<'tcx>| {
|err: &mut Diagnostic, type_param_span: Option<(Span, bool)>| {
let msg = "consider introducing an explicit lifetime bound";
if let Some((sp, has_lifetimes, is_impl_trait)) = type_param_span {
let suggestion = if is_impl_trait {
(sp.shrink_to_hi(), format!(" + {}", new_lt))
if let Some((sp, has_lifetimes)) = type_param_span {
let suggestion = if has_lifetimes {
format!(" + {}", new_lt)
} else {
let tail = if has_lifetimes { " +" } else { "" };
(sp, format!("{}: {}{}", bound_kind, new_lt, tail))
format!(": {}", new_lt)
};
let mut sugg =
vec![suggestion, (span.shrink_to_hi(), format!(" + {}", new_lt))];
vec![(sp, suggestion), (span.shrink_to_hi(), format!(" + {}", new_lt))];
if let Some(lt) = add_lt_sugg {
sugg.push(lt);
sugg.rotate_right(1);
@ -2543,11 +2522,11 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
let pred = format!("{}: {}", bound_kind, sub);
let suggestion = format!(
"{} {}",
if !generics.where_clause.predicates.is_empty() { "," } else { " where" },
if !generics.predicates.is_empty() { "," } else { " where" },
pred,
);
err.span_suggestion(
generics.where_clause.tail_span_for_suggestion(),
generics.tail_span_for_predicate_suggestion(),
"consider adding a where clause",
suggestion,
Applicability::MaybeIncorrect,
@ -2615,7 +2594,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
// suggest:
// fn get_later<'a, G: 'a, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ + 'a
ty::Closure(_, _substs) | ty::Opaque(_, _substs) if return_impl_trait => {
new_binding_suggestion(&mut err, type_param_span, bound_kind);
new_binding_suggestion(&mut err, type_param_span);
}
_ => {
binding_suggestion(&mut err, type_param_span, bound_kind, new_lt);

View File

@ -372,8 +372,8 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
.hir()
.get_generics(impl_item_def_id)
.unwrap()
.where_clause
.tail_span_for_suggestion();
.where_clause_span
.shrink_to_hi();
let suggestion = format!(
"{} {}",

View File

@ -1199,8 +1199,8 @@ impl<'tcx> LateLintPass<'tcx> for InvalidNoMangleItems {
});
}
}
hir::ItemKind::Impl(hir::Impl { ref generics, items, .. }) => {
for it in items {
hir::ItemKind::Impl(hir::Impl { generics, items, .. }) => {
for it in *items {
if let hir::AssocItemKind::Fn { .. } = it.kind {
if let Some(no_mangle_attr) = cx
.sess()
@ -1517,59 +1517,61 @@ impl<'tcx> LateLintPass<'tcx> for TypeAliasBounds {
// Bounds are respected for `type X = impl Trait`
return;
}
let mut suggested_changing_assoc_types = false;
// There must not be a where clause
if !type_alias_generics.where_clause.predicates.is_empty() {
cx.lint(
TYPE_ALIAS_BOUNDS,
|lint| {
let mut err = lint.build("where clauses are not enforced in type aliases");
let spans: Vec<_> = type_alias_generics
.where_clause
.predicates
.iter()
.map(|pred| pred.span())
.collect();
err.set_span(spans);
err.span_suggestion(
type_alias_generics.where_clause.span_for_predicates_or_empty_place(),
"the clause will not be checked when the type alias is used, and should be removed",
String::new(),
Applicability::MachineApplicable,
);
if !suggested_changing_assoc_types {
TypeAliasBounds::suggest_changing_assoc_types(ty, &mut err);
suggested_changing_assoc_types = true;
}
err.emit();
},
);
if type_alias_generics.predicates.is_empty() {
return;
}
// The parameters must not have bounds
for param in type_alias_generics.params.iter() {
let spans: Vec<_> = param.bounds.iter().map(|b| b.span()).collect();
let suggestion = spans
.iter()
.map(|sp| {
let start = param.span.between(*sp); // Include the `:` in `T: Bound`.
(start.to(*sp), String::new())
})
.collect();
if !spans.is_empty() {
cx.struct_span_lint(TYPE_ALIAS_BOUNDS, spans, |lint| {
let mut err =
lint.build("bounds on generic parameters are not enforced in type aliases");
let msg = "the bound will not be checked when the type alias is used, \
and should be removed";
err.multipart_suggestion(msg, suggestion, Applicability::MachineApplicable);
if !suggested_changing_assoc_types {
TypeAliasBounds::suggest_changing_assoc_types(ty, &mut err);
suggested_changing_assoc_types = true;
}
err.emit();
});
let mut where_spans = Vec::new();
let mut inline_spans = Vec::new();
let mut inline_sugg = Vec::new();
for p in type_alias_generics.predicates {
let span = p.span();
if p.in_where_clause() {
where_spans.push(span);
} else {
for b in p.bounds() {
inline_spans.push(b.span());
}
inline_sugg.push((span, String::new()));
}
}
let mut suggested_changing_assoc_types = false;
if !where_spans.is_empty() {
cx.lint(TYPE_ALIAS_BOUNDS, |lint| {
let mut err = lint.build("where clauses are not enforced in type aliases");
err.set_span(where_spans);
err.span_suggestion(
type_alias_generics.where_clause_span,
"the clause will not be checked when the type alias is used, and should be removed",
String::new(),
Applicability::MachineApplicable,
);
if !suggested_changing_assoc_types {
TypeAliasBounds::suggest_changing_assoc_types(ty, &mut err);
suggested_changing_assoc_types = true;
}
err.emit();
});
}
if !inline_spans.is_empty() {
cx.lint(TYPE_ALIAS_BOUNDS, |lint| {
let mut err =
lint.build("bounds on generic parameters are not enforced in type aliases");
err.set_span(inline_spans);
err.multipart_suggestion(
"the bound will not be checked when the type alias is used, and should be removed",
inline_sugg,
Applicability::MachineApplicable,
);
if !suggested_changing_assoc_types {
TypeAliasBounds::suggest_changing_assoc_types(ty, &mut err);
}
err.emit();
});
}
}
}
@ -2085,27 +2087,6 @@ impl ExplicitOutlivesRequirements {
.collect()
}
fn collect_outlived_lifetimes<'tcx>(
&self,
param: &'tcx hir::GenericParam<'tcx>,
tcx: TyCtxt<'tcx>,
inferred_outlives: &'tcx [(ty::Predicate<'tcx>, Span)],
ty_generics: &'tcx ty::Generics,
) -> Vec<ty::Region<'tcx>> {
let index =
ty_generics.param_def_id_to_index[&tcx.hir().local_def_id(param.hir_id).to_def_id()];
match param.kind {
hir::GenericParamKind::Lifetime { .. } => {
Self::lifetimes_outliving_lifetime(inferred_outlives, index)
}
hir::GenericParamKind::Type { .. } => {
Self::lifetimes_outliving_type(inferred_outlives, index)
}
hir::GenericParamKind::Const { .. } => Vec::new(),
}
}
fn collect_outlives_bound_spans<'tcx>(
&self,
tcx: TyCtxt<'tcx>,
@ -2213,41 +2194,11 @@ impl<'tcx> LateLintPass<'tcx> for ExplicitOutlivesRequirements {
let mut bound_count = 0;
let mut lint_spans = Vec::new();
for param in hir_generics.params {
let has_lifetime_bounds = param
.bounds
.iter()
.any(|bound| matches!(bound, hir::GenericBound::Outlives(_)));
if !has_lifetime_bounds {
continue;
}
let relevant_lifetimes =
self.collect_outlived_lifetimes(param, cx.tcx, inferred_outlives, ty_generics);
if relevant_lifetimes.is_empty() {
continue;
}
let bound_spans = self.collect_outlives_bound_spans(
cx.tcx,
&param.bounds,
&relevant_lifetimes,
infer_static,
);
bound_count += bound_spans.len();
lint_spans.extend(self.consolidate_outlives_bound_spans(
param.span.shrink_to_hi(),
&param.bounds,
bound_spans,
));
}
let mut where_lint_spans = Vec::new();
let mut dropped_predicate_count = 0;
let num_predicates = hir_generics.where_clause.predicates.len();
for (i, where_predicate) in hir_generics.where_clause.predicates.iter().enumerate() {
let (relevant_lifetimes, bounds, span) = match where_predicate {
let num_predicates = hir_generics.predicates.len();
for (i, where_predicate) in hir_generics.predicates.iter().enumerate() {
let (relevant_lifetimes, bounds, span, in_where_clause) = match where_predicate {
hir::WherePredicate::RegionPredicate(predicate) => {
if let Some(Region::EarlyBound(index, ..)) =
cx.tcx.named_region(predicate.lifetime.hir_id)
@ -2256,6 +2207,7 @@ impl<'tcx> LateLintPass<'tcx> for ExplicitOutlivesRequirements {
Self::lifetimes_outliving_lifetime(inferred_outlives, index),
&predicate.bounds,
predicate.span,
predicate.in_where_clause,
)
} else {
continue;
@ -2274,6 +2226,7 @@ impl<'tcx> LateLintPass<'tcx> for ExplicitOutlivesRequirements {
Self::lifetimes_outliving_type(inferred_outlives, index),
&predicate.bounds,
predicate.span,
predicate.in_where_clause,
)
}
_ => {
@ -2300,10 +2253,12 @@ impl<'tcx> LateLintPass<'tcx> for ExplicitOutlivesRequirements {
dropped_predicate_count += 1;
}
// If all the bounds on a predicate were inferable and there are
// further predicates, we want to eat the trailing comma.
if drop_predicate && i + 1 < num_predicates {
let next_predicate_span = hir_generics.where_clause.predicates[i + 1].span();
if drop_predicate && !in_where_clause {
lint_spans.push(span);
} else if drop_predicate && i + 1 < num_predicates {
// If all the bounds on a predicate were inferable and there are
// further predicates, we want to eat the trailing comma.
let next_predicate_span = hir_generics.predicates[i + 1].span();
where_lint_spans.push(span.to(next_predicate_span.shrink_to_lo()));
} else {
where_lint_spans.extend(self.consolidate_outlives_bound_spans(
@ -2316,10 +2271,9 @@ impl<'tcx> LateLintPass<'tcx> for ExplicitOutlivesRequirements {
// If all predicates are inferable, drop the entire clause
// (including the `where`)
if num_predicates > 0 && dropped_predicate_count == num_predicates {
if hir_generics.has_where_clause && dropped_predicate_count == num_predicates {
let where_span = hir_generics
.where_clause
.span()
.where_clause_span()
.expect("span of (nonempty) where clause should exist");
// Extend the where clause back to the closing `>` of the
// generics, except for tuple struct, which have the `where`
@ -2346,7 +2300,7 @@ impl<'tcx> LateLintPass<'tcx> for ExplicitOutlivesRequirements {
},
lint_spans
.into_iter()
.map(|span| (span, "".to_owned()))
.map(|span| (span, String::new()))
.collect::<Vec<_>>(),
Applicability::MachineApplicable,
)

View File

@ -1462,8 +1462,8 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
}))
}
hir::ItemKind::Impl(hir::Impl { defaultness, constness, .. }) => {
self.tables.impl_defaultness.set(def_id.index, defaultness);
self.tables.impl_constness.set(def_id.index, constness);
self.tables.impl_defaultness.set(def_id.index, *defaultness);
self.tables.impl_constness.set(def_id.index, *constness);
let trait_ref = self.tcx.impl_trait_ref(def_id);
if let Some(trait_ref) = trait_ref {

View File

@ -11,7 +11,7 @@ use rustc_data_structures::fx::FxHashMap;
use rustc_errors::{Applicability, Diagnostic, DiagnosticArgValue, IntoDiagnosticArg};
use rustc_hir as hir;
use rustc_hir::def_id::DefId;
use rustc_hir::{QPath, TyKind, WhereBoundPredicate, WherePredicate};
use rustc_hir::WherePredicate;
use rustc_span::Span;
impl<'tcx> IntoDiagnosticArg for Ty<'tcx> {
@ -156,13 +156,13 @@ pub fn suggest_arbitrary_trait_bound(
_ => {}
}
// Suggest a where clause bound for a non-type parameter.
let (action, prefix) = if generics.where_clause.predicates.is_empty() {
("introducing a", " where ")
} else {
let (action, prefix) = if generics.has_where_clause {
("extending the", ", ")
} else {
("introducing a", " where ")
};
err.span_suggestion_verbose(
generics.where_clause.tail_span_for_suggestion(),
generics.tail_span_for_predicate_suggestion(),
&format!(
"consider {} `where` bound, but there might be an alternative better way to express \
this requirement",
@ -183,104 +183,37 @@ enum SuggestChangingConstraintsMessage<'a> {
}
fn suggest_removing_unsized_bound(
tcx: TyCtxt<'_>,
generics: &hir::Generics<'_>,
suggestions: &mut Vec<(Span, String, SuggestChangingConstraintsMessage<'_>)>,
param_name: &str,
param: &hir::GenericParam<'_>,
def_id: Option<DefId>,
) {
// See if there's a `?Sized` bound that can be removed to suggest that.
// First look at the `where` clause because we can have `where T: ?Sized`,
// then look at params.
for (where_pos, predicate) in generics.where_clause.predicates.iter().enumerate() {
match predicate {
WherePredicate::BoundPredicate(WhereBoundPredicate {
bounded_ty:
hir::Ty {
kind:
hir::TyKind::Path(hir::QPath::Resolved(
None,
hir::Path {
segments: [segment],
res: hir::def::Res::Def(hir::def::DefKind::TyParam, _),
..
},
)),
..
},
bounds,
span,
..
}) if segment.ident.as_str() == param_name => {
for (pos, bound) in bounds.iter().enumerate() {
match bound {
hir::GenericBound::Trait(poly, hir::TraitBoundModifier::Maybe)
if poly.trait_ref.trait_def_id() == def_id => {}
_ => continue,
}
let sp = match (
bounds.len(),
pos,
generics.where_clause.predicates.len(),
where_pos,
) {
// where T: ?Sized
// ^^^^^^^^^^^^^^^
(1, _, 1, _) => generics.where_clause.span,
// where Foo: Bar, T: ?Sized,
// ^^^^^^^^^^^
(1, _, len, pos) if pos == len - 1 => generics.where_clause.predicates
[pos - 1]
.span()
.shrink_to_hi()
.to(*span),
// where T: ?Sized, Foo: Bar,
// ^^^^^^^^^^^
(1, _, _, pos) => {
span.until(generics.where_clause.predicates[pos + 1].span())
}
// where T: ?Sized + Bar, Foo: Bar,
// ^^^^^^^^^
(_, 0, _, _) => bound.span().to(bounds[1].span().shrink_to_lo()),
// where T: Bar + ?Sized, Foo: Bar,
// ^^^^^^^^^
(_, pos, _, _) => bounds[pos - 1].span().shrink_to_hi().to(bound.span()),
};
let param_def_id = tcx.hir().local_def_id(param.hir_id);
for (where_pos, predicate) in generics.predicates.iter().enumerate() {
let WherePredicate::BoundPredicate(predicate) = predicate else {
continue;
};
if !predicate.is_param_bound(param_def_id.to_def_id()) {
continue;
};
suggestions.push((
sp,
String::new(),
SuggestChangingConstraintsMessage::RemovingQSized,
));
}
for (pos, bound) in predicate.bounds.iter().enumerate() {
let hir::GenericBound::Trait(poly, hir::TraitBoundModifier::Maybe) = bound else {
continue;
};
if poly.trait_ref.trait_def_id() != def_id {
continue;
}
_ => {}
}
}
for (pos, bound) in param.bounds.iter().enumerate() {
match bound {
hir::GenericBound::Trait(poly, hir::TraitBoundModifier::Maybe)
if poly.trait_ref.trait_def_id() == def_id =>
{
let sp = match (param.bounds.len(), pos) {
// T: ?Sized,
// ^^^^^^^^
(1, _) => param.span.shrink_to_hi().to(bound.span()),
// T: ?Sized + Bar,
// ^^^^^^^^^
(_, 0) => bound.span().to(param.bounds[1].span().shrink_to_lo()),
// T: Bar + ?Sized,
// ^^^^^^^^^
(_, pos) => param.bounds[pos - 1].span().shrink_to_hi().to(bound.span()),
};
suggestions.push((
sp,
String::new(),
SuggestChangingConstraintsMessage::RemovingQSized,
));
}
_ => {}
let sp = generics.span_for_bound_removal(where_pos, pos);
suggestions.push((
sp,
String::new(),
SuggestChangingConstraintsMessage::RemovingQSized,
));
}
}
}
@ -331,13 +264,7 @@ pub fn suggest_constraining_type_params<'a>(
param.span,
&format!("this type parameter needs to be `{}`", constraint),
);
suggest_removing_unsized_bound(
generics,
&mut suggestions,
param_name,
param,
def_id,
);
suggest_removing_unsized_bound(tcx, generics, &mut suggestions, param, def_id);
}
}
@ -358,76 +285,45 @@ pub fn suggest_constraining_type_params<'a>(
))
};
if param_name.starts_with("impl ") {
// If there's an `impl Trait` used in argument position, suggest
// restricting it:
//
// fn foo(t: impl Foo) { ... }
// --------
// |
// help: consider further restricting this bound with `+ Bar`
//
// Suggestion for tools in this case is:
//
// fn foo(t: impl Foo) { ... }
// --------
// |
// replace with: `impl Foo + Bar`
// `impl Trait` must have at least one trait in the list
let bound_list_non_empty = true;
suggest_restrict(param.span.shrink_to_hi(), bound_list_non_empty);
// When the type parameter has been provided bounds
//
// Message:
// fn foo<T>(t: T) where T: Foo { ... }
// ^^^^^^
// |
// help: consider further restricting this bound with `+ Bar`
//
// Suggestion:
// fn foo<T>(t: T) where T: Foo { ... }
// ^
// |
// replace with: ` + Bar`
//
// Or, if user has provided some bounds, suggest restricting them:
//
// fn foo<T: Foo>(t: T) { ... }
// ---
// |
// help: consider further restricting this bound with `+ Bar`
//
// Suggestion for tools in this case is:
//
// fn foo<T: Foo>(t: T) { ... }
// --
// |
// replace with: `T: Bar +`
let param_def_id = tcx.hir().local_def_id(param.hir_id);
if let Some(span) = generics.bounds_span_for_suggestions(param_def_id) {
suggest_restrict(span, true);
continue;
}
if generics.where_clause.predicates.is_empty()
// Given `trait Base<T = String>: Super<T>` where `T: Copy`, suggest restricting in the
// `where` clause instead of `trait Base<T: Copy = String>: Super<T>`.
&& !matches!(param.kind, hir::GenericParamKind::Type { default: Some(_), .. })
{
if let Some(span) = param.bounds_span_for_suggestions() {
// If user has provided some bounds, suggest restricting them:
//
// fn foo<T: Foo>(t: T) { ... }
// ---
// |
// help: consider further restricting this bound with `+ Bar`
//
// Suggestion for tools in this case is:
//
// fn foo<T: Foo>(t: T) { ... }
// --
// |
// replace with: `T: Bar +`
// `bounds_span_for_suggestions` returns `None` if the list is empty
let bound_list_non_empty = true;
suggest_restrict(span, bound_list_non_empty);
} else {
let (colon, span) = match param.colon_span_for_suggestions(tcx.sess.source_map()) {
// If there is already a colon after generic, do not suggest adding it again
Some(sp) => ("", sp.shrink_to_hi()),
None => (":", param.span.shrink_to_hi()),
};
// If user hasn't provided any bounds, suggest adding a new one:
//
// fn foo<T>(t: T) { ... }
// - help: consider restricting this type parameter with `T: Foo`
suggestions.push((
span,
format!("{colon} {constraint}"),
SuggestChangingConstraintsMessage::RestrictType { ty: param_name },
));
}
} else {
if generics.has_where_clause {
// This part is a bit tricky, because using the `where` clause user can
// provide zero, one or many bounds for the same type parameter, so we
// have following cases to consider:
//
// 1) When the type parameter has been provided zero bounds
// When the type parameter has been provided zero bounds
//
// Message:
// fn foo<X, Y>(x: X, y: Y) where Y: Foo { ... }
@ -436,95 +332,59 @@ pub fn suggest_constraining_type_params<'a>(
// Suggestion:
// fn foo<X, Y>(x: X, y: Y) where Y: Foo { ... }
// - insert: `, X: Bar`
//
//
// 2) When the type parameter has been provided one bound
//
// Message:
// fn foo<T>(t: T) where T: Foo { ... }
// ^^^^^^
// |
// help: consider further restricting this bound with `+ Bar`
//
// Suggestion:
// fn foo<T>(t: T) where T: Foo { ... }
// ^^
// |
// replace with: `T: Bar +`
//
//
// 3) When the type parameter has been provided many bounds
//
// Message:
// fn foo<T>(t: T) where T: Foo, T: Bar {... }
// - help: consider further restricting this type parameter with `where T: Zar`
//
// Suggestion:
// fn foo<T>(t: T) where T: Foo, T: Bar {... }
// - insert: `, T: Zar`
//
// Additionally, there may be no `where` clause whatsoever in the case that this was
// reached because the generic parameter has a default:
//
// Message:
// trait Foo<T=()> {... }
// - help: consider further restricting this type parameter with `where T: Zar`
//
// Suggestion:
// trait Foo<T=()> where T: Zar {... }
// - insert: `where T: Zar`
if matches!(param.kind, hir::GenericParamKind::Type { default: Some(_), .. })
&& generics.where_clause.predicates.len() == 0
{
// Suggest a bound, but there is no existing `where` clause *and* the type param has a
// default (`<T=Foo>`), so we suggest adding `where T: Bar`.
suggestions.push((
generics.where_clause.tail_span_for_suggestion(),
format!(" where {}: {}", param_name, constraint),
SuggestChangingConstraintsMessage::RestrictTypeFurther { ty: param_name },
));
} else {
let mut param_spans = Vec::new();
let mut non_empty = false;
for predicate in generics.where_clause.predicates {
if let WherePredicate::BoundPredicate(WhereBoundPredicate {
span,
bounded_ty,
bounds,
..
}) = predicate
{
if let TyKind::Path(QPath::Resolved(_, path)) = &bounded_ty.kind {
if let Some(segment) = path.segments.first() {
if segment.ident.to_string() == param_name {
non_empty = !bounds.is_empty();
param_spans.push(span);
}
}
}
}
}
match param_spans[..] {
[&param_span] => suggest_restrict(param_span.shrink_to_hi(), non_empty),
_ => {
suggestions.push((
generics.where_clause.tail_span_for_suggestion(),
constraints
.iter()
.map(|&(constraint, _)| format!(", {}: {}", param_name, constraint))
.collect::<String>(),
SuggestChangingConstraintsMessage::RestrictTypeFurther {
ty: param_name,
},
));
}
}
}
suggestions.push((
generics.tail_span_for_predicate_suggestion(),
constraints
.iter()
.map(|&(constraint, _)| format!(", {}: {}", param_name, constraint))
.collect::<String>(),
SuggestChangingConstraintsMessage::RestrictTypeFurther { ty: param_name },
));
continue;
}
// Additionally, there may be no `where` clause but the generic parameter has a default:
//
// Message:
// trait Foo<T=()> {... }
// - help: consider further restricting this type parameter with `where T: Zar`
//
// Suggestion:
// trait Foo<T=()> {... }
// - insert: `where T: Zar`
if matches!(param.kind, hir::GenericParamKind::Type { default: Some(_), .. }) {
// Suggest a bound, but there is no existing `where` clause *and* the type param has a
// default (`<T=Foo>`), so we suggest adding `where T: Bar`.
suggestions.push((
generics.tail_span_for_predicate_suggestion(),
format!(" where {}: {}", param_name, constraint),
SuggestChangingConstraintsMessage::RestrictTypeFurther { ty: param_name },
));
continue;
}
// If user has provided a colon, don't suggest adding another:
//
// fn foo<T:>(t: T) { ... }
// - insert: consider restricting this type parameter with `T: Foo`
if let Some(colon_span) = param.colon_span {
suggestions.push((
colon_span.shrink_to_hi(),
format!(" {}", constraint),
SuggestChangingConstraintsMessage::RestrictType { ty: param_name },
));
continue;
}
// If user hasn't provided any bounds, suggest adding a new one:
//
// fn foo<T>(t: T) { ... }
// - help: consider restricting this type parameter with `T: Foo`
suggestions.push((
param.span.shrink_to_hi(),
format!(": {}", constraint),
SuggestChangingConstraintsMessage::RestrictType { ty: param_name },
));
}
if suggestions.len() == 1 {

View File

@ -602,53 +602,24 @@ impl<T> Trait<T> for X {
} else {
return false;
};
let Some(def_id) = def_id.as_local() else {
return false;
};
// First look in the `where` clause, as this might be
// `fn foo<T>(x: T) where T: Trait`.
for predicate in hir_generics.where_clause.predicates {
if let hir::WherePredicate::BoundPredicate(pred) = predicate {
if let hir::TyKind::Path(hir::QPath::Resolved(None, path)) =
pred.bounded_ty.kind
{
if path.res.opt_def_id() == Some(def_id) {
// This predicate is binding type param `A` in `<A as T>::Foo` to
// something, potentially `T`.
} else {
continue;
}
} else {
continue;
}
if self.constrain_generic_bound_associated_type_structured_suggestion(
diag,
&trait_ref,
pred.bounds,
&assoc,
assoc_substs,
ty,
msg,
false,
) {
return true;
}
}
}
for param in hir_generics.params {
if self.hir().opt_local_def_id(param.hir_id).map(|id| id.to_def_id())
== Some(def_id)
{
// This is type param `A` in `<A as T>::Foo`.
return self.constrain_generic_bound_associated_type_structured_suggestion(
diag,
&trait_ref,
param.bounds,
&assoc,
assoc_substs,
ty,
msg,
false,
);
for pred in hir_generics.bounds_for_param(def_id) {
if self.constrain_generic_bound_associated_type_structured_suggestion(
diag,
&trait_ref,
pred.bounds,
&assoc,
assoc_substs,
ty,
msg,
false,
) {
return true;
}
}
}

View File

@ -30,8 +30,10 @@ impl<'a> Parser<'a> {
let ident = self.parse_ident()?;
// Parse optional colon and param bounds.
let mut colon_span = None;
let bounds = if self.eat(&token::Colon) {
self.parse_generic_bounds(Some(self.prev_token.span))?
colon_span = Some(self.prev_token.span);
self.parse_generic_bounds(colon_span)?
} else {
Vec::new()
};
@ -45,6 +47,7 @@ impl<'a> Parser<'a> {
bounds,
kind: GenericParamKind::Type { default },
is_placeholder: false,
colon_span,
})
}
@ -69,6 +72,7 @@ impl<'a> Parser<'a> {
bounds: Vec::new(),
kind: GenericParamKind::Const { ty, kw_span: const_span, default },
is_placeholder: false,
colon_span: None,
})
}
@ -97,10 +101,10 @@ impl<'a> Parser<'a> {
let param = if this.check_lifetime() {
let lifetime = this.expect_lifetime();
// Parse lifetime parameter.
let bounds = if this.eat(&token::Colon) {
this.parse_lt_param_bounds()
let (colon_span, bounds) = if this.eat(&token::Colon) {
(Some(this.prev_token.span), this.parse_lt_param_bounds())
} else {
Vec::new()
(None, Vec::new())
};
Some(ast::GenericParam {
ident: lifetime.ident,
@ -109,6 +113,7 @@ impl<'a> Parser<'a> {
bounds,
kind: ast::GenericParamKind::Lifetime,
is_placeholder: false,
colon_span,
})
} else if this.check_keyword(kw::Const) {
// Parse const parameter.

View File

@ -512,7 +512,7 @@ impl<'v, 'tcx> ItemLikeVisitor<'v> for LifeSeeder<'tcx> {
if of_trait.is_some() {
self.worklist.push(item.def_id);
}
for impl_item_ref in items {
for impl_item_ref in *items {
let impl_item = self.tcx.hir().impl_item(impl_item_ref.id);
if of_trait.is_some()
|| has_allow_dead_code_or_lang_attr(self.tcx, impl_item.hir_id())

View File

@ -737,7 +737,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'tcx> {
}
}
for impl_item_ref in items {
for impl_item_ref in *items {
let impl_item = self.tcx.associated_item(impl_item_ref.id.def_id);
if let Some(def_id) = impl_item.trait_item_def_id {

View File

@ -1585,12 +1585,7 @@ impl<'a, 'tcx> Visitor<'tcx> for ObsoleteVisiblePrivateTypesVisitor<'a, 'tcx> {
}
fn visit_generics(&mut self, generics: &'tcx hir::Generics<'tcx>) {
for param in generics.params {
for bound in param.bounds {
self.check_generic_bound(bound);
}
}
for predicate in generics.where_clause.predicates {
for predicate in generics.predicates {
match predicate {
hir::WherePredicate::BoundPredicate(bound_pred) => {
for bound in bound_pred.bounds.iter() {

View File

@ -86,7 +86,7 @@ impl ForLifetimeSpanType {
}
}
impl<'tcx> Into<MissingLifetimeSpot<'tcx>> for &'tcx hir::Generics<'tcx> {
impl<'tcx> Into<MissingLifetimeSpot<'tcx>> for &&'tcx hir::Generics<'tcx> {
fn into(self) -> MissingLifetimeSpot<'tcx> {
MissingLifetimeSpot::Generics(self)
}

View File

@ -1328,13 +1328,11 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
match param.kind {
GenericParamKind::Lifetime { .. } => {}
GenericParamKind::Type { ref default, .. } => {
walk_list!(this, visit_param_bound, param.bounds);
if let Some(ref ty) = default {
this.visit_ty(&ty);
}
}
GenericParamKind::Const { ref ty, default } => {
walk_list!(this, visit_param_bound, param.bounds);
this.visit_ty(&ty);
if let Some(default) = default {
this.visit_body(this.tcx.hir().body(default.body));
@ -1342,7 +1340,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
}
}
}
for predicate in generics.where_clause.predicates {
for predicate in generics.predicates {
match predicate {
&hir::WherePredicate::BoundPredicate(hir::WhereBoundPredicate {
ref bounded_ty,
@ -1393,6 +1391,32 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
}) => {
this.visit_lifetime(lifetime);
walk_list!(this, visit_param_bound, bounds);
if lifetime.name != hir::LifetimeName::Static {
for bound in bounds {
let hir::GenericBound::Outlives(ref lt) = bound else {
continue;
};
if lt.name != hir::LifetimeName::Static {
continue;
}
this.insert_lifetime(lt, Region::Static);
this.tcx
.sess
.struct_span_warn(
lifetime.span,
&format!(
"unnecessary lifetime parameter `{}`",
lifetime.name.ident(),
),
)
.help(&format!(
"you can use the `'static` lifetime directly, in place of `{}`",
lifetime.name.ident(),
))
.emit();
}
}
}
&hir::WherePredicate::EqPredicate(hir::WhereEqPredicate {
ref lhs_ty,
@ -1714,10 +1738,8 @@ fn object_lifetime_defaults_for_item<'tcx>(
GenericParamKind::Type { .. } => {
let mut set = Set1::Empty;
add_bounds(&mut set, &param.bounds);
let param_def_id = tcx.hir().local_def_id(param.hir_id);
for predicate in generics.where_clause.predicates {
for predicate in generics.predicates {
// Look for `type: ...` where clauses.
let hir::WherePredicate::BoundPredicate(ref data) = *predicate else { continue };
@ -3124,50 +3146,6 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
// It is a soft error to shadow a lifetime within a parent scope.
self.check_lifetime_param_for_shadowing(old_scope, &lifetime_i);
for bound in lifetime_i.bounds {
match bound {
hir::GenericBound::Outlives(ref lt) => match lt.name {
hir::LifetimeName::Underscore => {
self.tcx.sess.delay_span_bug(
lt.span,
"use of `'_` in illegal place, but not caught by lowering",
);
}
hir::LifetimeName::Static => {
self.insert_lifetime(lt, Region::Static);
self.tcx
.sess
.struct_span_warn(
lifetime_i.span.to(lt.span),
&format!(
"unnecessary lifetime parameter `{}`",
lifetime_i.name.ident(),
),
)
.help(&format!(
"you can use the `'static` lifetime directly, in place of `{}`",
lifetime_i.name.ident(),
))
.emit();
}
hir::LifetimeName::Param(_) | hir::LifetimeName::Implicit => {
self.resolve_lifetime_ref(lt);
}
hir::LifetimeName::ImplicitObjectLifetimeDefault => {
self.tcx.sess.delay_span_bug(
lt.span,
"lowering generated `ImplicitObjectLifetimeDefault` \
outside of an object type",
);
}
hir::LifetimeName::Error => {
// No need to do anything, error already reported.
}
},
_ => bug!(),
}
}
}
}
@ -3326,18 +3304,6 @@ fn insert_late_bound_lifetimes(
// ignore binders here and scrape up all names we see.
let mut appears_in_where_clause = AllCollector::default();
appears_in_where_clause.visit_generics(generics);
for param in generics.params {
if let hir::GenericParamKind::Lifetime { .. } = param.kind {
if !param.bounds.is_empty() {
// `'a: 'b` means both `'a` and `'b` are referenced
appears_in_where_clause
.regions
.insert(hir::LifetimeName::Param(param.name.normalize_to_macros_2_0()));
}
}
}
debug!(?appears_in_where_clause.regions);
// Late bound regions are those that:

View File

@ -1267,13 +1267,11 @@ impl<'tcx> Visitor<'tcx> for DumpVisitor<'tcx> {
match param.kind {
hir::GenericParamKind::Lifetime { .. } => {}
hir::GenericParamKind::Type { ref default, .. } => {
self.process_bounds(param.bounds);
if let Some(ref ty) = default {
self.visit_ty(ty);
}
}
hir::GenericParamKind::Const { ref ty, ref default } => {
self.process_bounds(param.bounds);
self.visit_ty(ty);
if let Some(default) = default {
self.visit_anon_const(default);
@ -1281,7 +1279,7 @@ impl<'tcx> Visitor<'tcx> for DumpVisitor<'tcx> {
}
}
}
for pred in generics.where_clause.predicates {
for pred in generics.predicates {
if let hir::WherePredicate::BoundPredicate(ref wbp) = *pred {
self.process_bounds(wbp.bounds);
self.visit_ty(wbp.bounded_ty);

View File

@ -630,31 +630,6 @@ impl<'hir> Sig for hir::Generics<'hir> {
param_text.push_str(&id_to_string(&scx.tcx.hir(), default.hir_id));
}
}
if !param.bounds.is_empty() {
param_text.push_str(": ");
match param.kind {
hir::GenericParamKind::Lifetime { .. } => {
let bounds = param
.bounds
.iter()
.map(|bound| match bound {
hir::GenericBound::Outlives(lt) => lt.name.ident().to_string(),
_ => panic!(),
})
.collect::<Vec<_>>()
.join(" + ");
param_text.push_str(&bounds);
// FIXME add lifetime bounds refs.
}
hir::GenericParamKind::Type { .. } => {
param_text.push_str(&bounds_to_string(param.bounds));
// FIXME descend properly into bounds.
}
hir::GenericParamKind::Const { .. } => {
// Const generics cannot contain bounds.
}
}
}
text.push_str(&param_text);
text.push(',');
}

View File

@ -2419,26 +2419,15 @@ impl<'a, 'tcx> InferCtxtPrivExt<'a, 'tcx> for InferCtxt<'a, 'tcx> {
};
let sized_trait = self.tcx.lang_items().sized_trait();
debug!("maybe_suggest_unsized_generics: generics.params={:?}", generics.params);
debug!("maybe_suggest_unsized_generics: generics.where_clause={:?}", generics.where_clause);
let param = generics.params.iter().filter(|param| param.span == span).find(|param| {
// Check that none of the explicit trait bounds is `Sized`. Assume that an explicit
// `Sized` bound is there intentionally and we don't need to suggest relaxing it.
param
.bounds
.iter()
.all(|bound| bound.trait_ref().and_then(|tr| tr.trait_def_id()) != sized_trait)
});
let Some(param) = param else {
debug!("maybe_suggest_unsized_generics: generics.predicates={:?}", generics.predicates);
let Some(param) = generics.params.iter().find(|param| param.span == span) else {
return;
};
let param_def_id = self.tcx.hir().local_def_id(param.hir_id).to_def_id();
let preds = generics.where_clause.predicates.iter();
let explicitly_sized = preds
.filter_map(|pred| match pred {
hir::WherePredicate::BoundPredicate(bp) => Some(bp),
_ => None,
})
.filter(|bp| bp.is_param_bound(param_def_id))
let param_def_id = self.tcx.hir().local_def_id(param.hir_id);
// Check that none of the explicit trait bounds is `Sized`. Assume that an explicit
// `Sized` bound is there intentionally and we don't need to suggest relaxing it.
let explicitly_sized = generics
.bounds_for_param(param_def_id)
.flat_map(|bp| bp.bounds)
.any(|bound| bound.trait_ref().and_then(|tr| tr.trait_def_id()) == sized_trait);
if explicitly_sized {
@ -2461,9 +2450,11 @@ impl<'a, 'tcx> InferCtxtPrivExt<'a, 'tcx> for InferCtxt<'a, 'tcx> {
_ => {}
};
// Didn't add an indirection suggestion, so add a general suggestion to relax `Sized`.
let (span, separator) = match param.bounds {
[] => (span.shrink_to_hi(), ":"),
[.., bound] => (bound.span().shrink_to_hi(), " +"),
let (span, separator) = if let Some(s) = generics.bounds_span_for_suggestions(param_def_id)
{
(s, " +")
} else {
(span.shrink_to_hi(), ":")
};
err.span_suggestion_verbose(
span,

View File

@ -319,12 +319,8 @@ pub trait InferCtxtExt<'tcx> {
fn predicate_constraint(generics: &hir::Generics<'_>, pred: String) -> (Span, String) {
(
generics.where_clause.tail_span_for_suggestion(),
format!(
"{} {}",
if !generics.where_clause.predicates.is_empty() { "," } else { " where" },
pred,
),
generics.tail_span_for_predicate_suggestion(),
format!("{} {}", if generics.has_where_clause { "," } else { " where" }, pred,),
)
}
@ -346,7 +342,7 @@ fn suggest_restriction<'tcx>(
// - ^^^^^^^^^ GenericBounds
// |
// &Ident
let span = generics.where_clause.span_for_predicates_or_empty_place();
let span = generics.span_for_predicates_or_empty_place();
if span.from_expansion() || span.desugaring_kind().is_some() {
return;
}
@ -396,21 +392,10 @@ fn suggest_restriction<'tcx>(
let pred = trait_pred.to_predicate(tcx).to_string();
let pred = pred.replace(&impl_trait_str, &type_param_name);
let mut sugg = vec![
// Find the last of the generic parameters contained within the span of
// the generics
match generics
.params
.iter()
.map(|p| p.bounds_span_for_suggestions().unwrap_or(p.span.shrink_to_hi()))
.filter(|&span| generics.span.contains(span) && span.can_be_used_for_suggestions())
.max_by_key(|span| span.hi())
{
// `fn foo(t: impl Trait)`
// ^ suggest `<T: Trait>` here
None => (generics.span, format!("<{}>", type_param)),
// `fn foo<A>(t: impl Trait)`
// ^^^ suggest `<A, T: Trait>` here
Some(span) => (span, format!(", {}", type_param)),
if let Some(span) = generics.span_for_param_suggestion() {
(span, format!(", {}", type_param))
} else {
(generics.span, format!("<{}>", type_param))
},
// `fn foo(t: impl Trait)`
// ^ suggest `where <T as Trait>::A: Bound`

View File

@ -221,7 +221,6 @@ fn get_sized_bounds(tcx: TyCtxt<'_>, trait_def_id: DefId) -> SmallVec<[Span; 1]>
..
}) => Some(
generics
.where_clause
.predicates
.iter()
.filter_map(|pred| {
@ -399,8 +398,8 @@ fn virtual_call_violation_for_method<'tcx>(
// We'll attempt to provide a structured suggestion for `Self: Sized`.
let sugg =
tcx.hir().get_if_local(method.def_id).as_ref().and_then(|node| node.generics()).map(
|generics| match generics.where_clause.predicates {
[] => (" where Self: Sized", generics.where_clause.span),
|generics| match generics.predicates {
[] => (" where Self: Sized", generics.where_clause_span),
[.., pred] => (", Self: Sized", pred.span().shrink_to_hi()),
},
);

View File

@ -924,14 +924,9 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
let self_ty_def_id = tcx.hir().local_def_id(self_ty).to_def_id();
for clause in where_clause {
if let hir::WherePredicate::BoundPredicate(pred) = clause {
match pred.bounded_ty.kind {
hir::TyKind::Path(hir::QPath::Resolved(_, path)) => match path.res {
Res::Def(DefKind::TyParam, def_id) if def_id == self_ty_def_id => {}
_ => continue,
},
_ => continue,
if pred.is_param_bound(self_ty_def_id) {
search_bounds(pred.bounds);
}
search_bounds(pred.bounds);
}
}
}
@ -2389,7 +2384,6 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
bf.unsafety,
bf.abi,
bf.decl,
&hir::Generics::empty(),
None,
Some(ast_ty),
))
@ -2551,8 +2545,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
unsafety: hir::Unsafety,
abi: abi::Abi,
decl: &hir::FnDecl<'_>,
generics: &hir::Generics<'_>,
ident_span: Option<Span>,
generics: Option<&hir::Generics<'_>>,
hir_ty: Option<&hir::Ty<'_>>,
) -> ty::PolyFnSig<'tcx> {
debug!("ty_of_fn");
@ -2565,7 +2558,9 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
let mut visitor = HirPlaceholderCollector::default();
let mut infer_replacements = vec![];
walk_generics(&mut visitor, generics);
if let Some(generics) = generics {
walk_generics(&mut visitor, generics);
}
let input_tys: Vec<_> = decl
.inputs
@ -2617,8 +2612,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
let mut diag = crate::collect::placeholder_type_error_diag(
tcx,
ident_span.map(|sp| sp.shrink_to_hi()),
generics.params,
generics,
visitor.0,
infer_replacements.iter().map(|(s, _)| *s).collect(),
true,

View File

@ -804,7 +804,8 @@ fn compare_synthetic_generics<'tcx>(
iter::zip(impl_m_type_params, trait_m_type_params)
{
if impl_synthetic != trait_synthetic {
let impl_hir_id = tcx.hir().local_def_id_to_hir_id(impl_def_id.expect_local());
let impl_def_id = impl_def_id.expect_local();
let impl_hir_id = tcx.hir().local_def_id_to_hir_id(impl_def_id);
let impl_span = tcx.hir().span(impl_hir_id);
let trait_span = tcx.def_span(trait_def_id);
let mut err = struct_span_err!(
@ -868,14 +869,14 @@ fn compare_synthetic_generics<'tcx>(
hir::ImplItemKind::Fn(ref sig, _) => sig.decl.inputs,
_ => unreachable!(),
};
struct Visitor(Option<Span>, hir::def_id::DefId);
struct Visitor(Option<Span>, hir::def_id::LocalDefId);
impl<'v> intravisit::Visitor<'v> for Visitor {
fn visit_ty(&mut self, ty: &'v hir::Ty<'v>) {
intravisit::walk_ty(self, ty);
if let hir::TyKind::Path(hir::QPath::Resolved(None, ref path)) =
ty.kind
&& let Res::Def(DefKind::TyParam, def_id) = path.res
&& def_id == self.1
&& def_id == self.1.to_def_id()
{
self.0 = Some(ty.span);
}
@ -887,17 +888,7 @@ fn compare_synthetic_generics<'tcx>(
}
let span = visitor.0?;
let bounds =
impl_m.generics.params.iter().find_map(|param| match param.kind {
GenericParamKind::Lifetime { .. } => None,
GenericParamKind::Type { .. } | GenericParamKind::Const { .. } => {
if param.hir_id == impl_hir_id {
Some(&param.bounds)
} else {
None
}
}
})?;
let bounds = impl_m.generics.bounds_for_param(impl_def_id).next()?.bounds;
let bounds = bounds.first()?.span().to(bounds.last()?.span());
let bounds = tcx.sess.source_map().span_to_snippet(bounds).ok()?;

View File

@ -599,17 +599,18 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
kind:
hir::ItemKind::Fn(
hir::FnSig { decl: hir::FnDecl { inputs: fn_parameters, output: fn_return, .. }, .. },
hir::Generics { params, where_clause, .. },
hir::Generics { params, predicates, .. },
_body_id,
),
..
})) = fn_node else { return };
let Some(expected_generic_param) = params.get(expected_ty_as_param.index as usize) else { return };
if params.get(expected_ty_as_param.index as usize).is_none() {
return;
};
// get all where BoundPredicates here, because they are used in to cases below
let where_predicates = where_clause
.predicates
let where_predicates = predicates
.iter()
.filter_map(|p| match p {
WherePredicate::BoundPredicate(hir::WhereBoundPredicate {
@ -640,10 +641,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
where_predicates.iter().flatten().flat_map(|bounds| bounds.iter());
// extract all bounds from the source code using their spans
let all_matching_bounds_strs = expected_generic_param
.bounds
.iter()
.chain(predicates_from_where)
let all_matching_bounds_strs = predicates_from_where
.filter_map(|bound| match bound {
GenericBound::Trait(_, _) => {
self.tcx.sess.source_map().span_to_snippet(bound.span()).ok()

View File

@ -533,12 +533,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
};
if let Some(hir::Node::Item(hir::Item { kind, .. })) = node {
if let Some(g) = kind.generics() {
let key = match g.where_clause.predicates {
let key = match g.predicates {
[.., pred] => (pred.span().shrink_to_hi(), false),
[] => (
g.where_clause.span_for_predicates_or_empty_place(),
true,
),
[] => (g.span_for_predicates_or_empty_place(), true),
};
type_params
.entry(key)
@ -1871,37 +1868,30 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// instead we suggest `T: Foo + Bar` in that case.
match hir.get(id) {
Node::GenericParam(param) => {
let mut impl_trait = false;
let has_bounds =
if let hir::GenericParamKind::Type { synthetic: true, .. } =
&param.kind
{
// We've found `fn foo(x: impl Trait)` instead of
// `fn foo<T>(x: T)`. We want to suggest the correct
// `fn foo(x: impl Trait + TraitBound)` instead of
// `fn foo<T: TraitBound>(x: T)`. (#63706)
impl_trait = true;
param.bounds.get(1)
} else {
param.bounds.get(0)
};
let sp = hir.span(id);
let sp = if let Some(first_bound) = has_bounds {
sp.until(first_bound.span())
} else if let Some(colon_sp) =
// If the generic param is declared with a colon but without bounds:
// fn foo<T:>(t: T) { ... }
param.colon_span_for_suggestions(
self.inh.tcx.sess.source_map(),
)
enum Introducer {
Plus,
Colon,
Nothing,
}
let ast_generics = hir.get_generics(id.owner).unwrap();
let (sp, mut introducer) = if let Some(span) =
ast_generics.bounds_span_for_suggestions(def_id)
{
sp.to(colon_sp)
(span, Introducer::Plus)
} else if let Some(colon_span) = param.colon_span {
(colon_span.shrink_to_hi(), Introducer::Nothing)
} else {
sp
(param.span.shrink_to_hi(), Introducer::Colon)
};
let trait_def_ids: FxHashSet<DefId> = param
.bounds
.iter()
if matches!(
param.kind,
hir::GenericParamKind::Type { synthetic: true, .. },
) {
introducer = Introducer::Plus
}
let trait_def_ids: FxHashSet<DefId> = ast_generics
.bounds_for_param(def_id)
.flat_map(|bp| bp.bounds.iter())
.filter_map(|bound| bound.trait_ref()?.trait_def_id())
.collect();
if !candidates.iter().any(|t| trait_def_ids.contains(&t.def_id)) {
@ -1913,11 +1903,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
)),
candidates.iter().map(|t| {
format!(
"{}{} {}{}",
param.name.ident(),
if impl_trait { " +" } else { ":" },
"{} {}",
match introducer {
Introducer::Plus => " +",
Introducer::Colon => ":",
Introducer::Nothing => "",
},
self.tcx.def_path_str(t.def_id),
if has_bounds.is_some() { " + " } else { "" },
)
}),
Applicability::MaybeIncorrect,

View File

@ -373,16 +373,7 @@ fn typeck_with_fallback<'tcx>(
let (fcx, wf_tys) = if let Some(hir::FnSig { header, decl, .. }) = fn_sig {
let fn_sig = if crate::collect::get_infer_ret_ty(&decl.output).is_some() {
let fcx = FnCtxt::new(&inh, param_env, body.value.hir_id);
<dyn AstConv<'_>>::ty_of_fn(
&fcx,
id,
header.unsafety,
header.abi,
decl,
&hir::Generics::empty(),
None,
None,
)
<dyn AstConv<'_>>::ty_of_fn(&fcx, id, header.unsafety, header.abi, decl, None, None)
} else {
tcx.fn_sig(def_id)
};

View File

@ -420,15 +420,11 @@ fn check_gat_where_clauses(tcx: TyCtxt<'_>, associated_items: &[hir::TraitItemRe
let suggestion = format!(
"{} {}",
if !gat_item_hir.generics.where_clause.predicates.is_empty() {
","
} else {
" where"
},
if !gat_item_hir.generics.predicates.is_empty() { "," } else { " where" },
unsatisfied_bounds.join(", "),
);
err.span_suggestion(
gat_item_hir.generics.where_clause.tail_span_for_suggestion(),
gat_item_hir.generics.tail_span_for_predicate_suggestion(),
&format!("add the required where clause{plural}"),
suggestion,
Applicability::MachineApplicable,
@ -1733,7 +1729,6 @@ fn check_variances_for_type_defn<'tcx>(
let explicitly_bounded_params = Lazy::new(|| {
let icx = crate::collect::ItemCtxt::new(tcx, item.def_id.to_def_id());
hir_generics
.where_clause
.predicates
.iter()
.filter_map(|predicate| match predicate {
@ -1760,8 +1755,7 @@ fn check_variances_for_type_defn<'tcx>(
match param.name {
hir::ParamName::Error => {}
_ => {
let has_explicit_bounds =
!param.bounds.is_empty() || explicitly_bounded_params.contains(&parameter);
let has_explicit_bounds = explicitly_bounded_params.contains(&parameter);
report_bivariance(tcx, param, has_explicit_bounds);
}
}
@ -1819,13 +1813,12 @@ fn check_false_global_bounds(fcx: &FnCtxt<'_, '_>, mut span: Span, id: hir::HirI
// only use the span of the predicate clause (#90869)
if let Some(hir::Generics { where_clause, .. }) =
if let Some(hir::Generics { predicates, .. }) =
hir_node.and_then(|node| node.generics())
{
let obligation_span = obligation.cause.span(fcx.tcx);
span = where_clause
.predicates
span = predicates
.iter()
// There seems to be no better way to find out which predicate we are in
.find(|pred| pred.span().contains(obligation_span))

View File

@ -1,4 +1,3 @@
// ignore-tidy-filelength
//! "Collection" is the process of determining the type and other external
//! details of each item in Rust. Collection is specifically concerned
//! with *inter-procedural* things -- for example, for a function
@ -149,8 +148,7 @@ struct CollectItemTypesVisitor<'tcx> {
/// all already existing generic type parameters to avoid suggesting a name that is already in use.
crate fn placeholder_type_error<'tcx>(
tcx: TyCtxt<'tcx>,
span: Option<Span>,
generics: &[hir::GenericParam<'_>],
generics: Option<&hir::Generics<'_>>,
placeholder_types: Vec<Span>,
suggest: bool,
hir_ty: Option<&hir::Ty<'_>>,
@ -160,23 +158,13 @@ crate fn placeholder_type_error<'tcx>(
return;
}
placeholder_type_error_diag(
tcx,
span,
generics,
placeholder_types,
vec![],
suggest,
hir_ty,
kind,
)
.emit();
placeholder_type_error_diag(tcx, generics, placeholder_types, vec![], suggest, hir_ty, kind)
.emit();
}
crate fn placeholder_type_error_diag<'tcx>(
tcx: TyCtxt<'tcx>,
span: Option<Span>,
generics: &[hir::GenericParam<'_>],
generics: Option<&hir::Generics<'_>>,
placeholder_types: Vec<Span>,
additional_spans: Vec<Span>,
suggest: bool,
@ -187,26 +175,24 @@ crate fn placeholder_type_error_diag<'tcx>(
return bad_placeholder(tcx, additional_spans, kind);
}
let type_name = generics.next_type_param_name(None);
let params = generics.map(|g| g.params).unwrap_or_default();
let type_name = params.next_type_param_name(None);
let mut sugg: Vec<_> =
placeholder_types.iter().map(|sp| (*sp, (*type_name).to_string())).collect();
if generics.is_empty() {
if let Some(span) = span {
sugg.push((span, format!("<{}>", type_name)));
if let Some(generics) = generics {
if let Some(arg) = params.iter().find(|arg| {
matches!(arg.name, hir::ParamName::Plain(Ident { name: kw::Underscore, .. }))
}) {
// Account for `_` already present in cases like `struct S<_>(_);` and suggest
// `struct S<T>(T);` instead of `struct S<_, T>(T);`.
sugg.push((arg.span, (*type_name).to_string()));
} else if let Some(span) = generics.span_for_param_suggestion() {
// Account for bounds, we want `fn foo<T: E, K>(_: K)` not `fn foo<T, K: E>(_: K)`.
sugg.push((span, format!(", {}", type_name)));
} else {
sugg.push((generics.span, format!("<{}>", type_name)));
}
} else if let Some(arg) = generics
.iter()
.find(|arg| matches!(arg.name, hir::ParamName::Plain(Ident { name: kw::Underscore, .. })))
{
// Account for `_` already present in cases like `struct S<_>(_);` and suggest
// `struct S<T>(T);` instead of `struct S<_, T>(T);`.
sugg.push((arg.span, (*type_name).to_string()));
} else {
let last = generics.iter().last().unwrap();
// Account for bounds, we want `fn foo<T: E, K>(_: K)` not `fn foo<T, K: E>(_: K)`.
let span = last.bounds_span_for_suggestions().unwrap_or(last.span.shrink_to_hi());
sugg.push((span, format!(", {}", type_name)));
}
let mut err =
@ -270,15 +256,7 @@ fn reject_placeholder_type_signatures_in_item<'tcx>(
let mut visitor = HirPlaceholderCollector::default();
visitor.visit_item(item);
placeholder_type_error(
tcx,
Some(generics.span),
generics.params,
visitor.0,
suggest,
None,
item.kind.descr(),
);
placeholder_type_error(tcx, Some(generics), visitor.0, suggest, None, item.kind.descr());
}
impl<'tcx> Visitor<'tcx> for CollectItemTypesVisitor<'tcx> {
@ -680,27 +658,8 @@ impl<'tcx> ItemCtxt<'tcx> {
only_self_bounds: OnlySelfBounds,
assoc_name: Option<Ident>,
) -> Vec<(ty::Predicate<'tcx>, Span)> {
let from_ty_params = ast_generics
.params
.iter()
.filter_map(|param| match param.kind {
GenericParamKind::Type { .. } | GenericParamKind::Const { .. }
if param.hir_id == param_id =>
{
Some(&param.bounds)
}
_ => None,
})
.flat_map(|bounds| bounds.iter())
.filter(|b| match assoc_name {
Some(assoc_name) => self.bound_defines_assoc_item(b, assoc_name),
None => true,
})
.flat_map(|b| predicates_from_bound(self, ty, b, ty::List::empty()));
let param_def_id = self.tcx.hir().local_def_id(param_id).to_def_id();
let from_where_clauses = ast_generics
.where_clause
ast_generics
.predicates
.iter()
.filter_map(|wp| match *wp {
@ -725,9 +684,8 @@ impl<'tcx> ItemCtxt<'tcx> {
})
.filter_map(move |b| bt.map(|bt| (bt, b, bvars)))
})
.flat_map(|(bt, b, bvars)| predicates_from_bound(self, bt, b, bvars));
from_ty_params.chain(from_where_clauses).collect()
.flat_map(|(bt, b, bvars)| predicates_from_bound(self, bt, b, bvars))
.collect()
}
fn bound_defines_assoc_item(&self, b: &hir::GenericBound<'_>, assoc_name: Ident) -> bool {
@ -773,7 +731,6 @@ fn convert_item(tcx: TyCtxt<'_>, item_id: hir::ItemId) {
placeholder_type_error(
tcx,
None,
&[],
visitor.0,
false,
None,
@ -853,15 +810,7 @@ fn convert_item(tcx: TyCtxt<'_>, item_id: hir::ItemId) {
if let hir::TyKind::TraitObject(..) = ty.kind {
let mut visitor = HirPlaceholderCollector::default();
visitor.visit_item(it);
placeholder_type_error(
tcx,
None,
&[],
visitor.0,
false,
None,
it.kind.descr(),
);
placeholder_type_error(tcx, None, visitor.0, false, None, it.kind.descr());
}
}
_ => (),
@ -889,7 +838,7 @@ fn convert_trait_item(tcx: TyCtxt<'_>, trait_item_id: hir::TraitItemId) {
// Account for `const C: _;`.
let mut visitor = HirPlaceholderCollector::default();
visitor.visit_trait_item(trait_item);
placeholder_type_error(tcx, None, &[], visitor.0, false, None, "constant");
placeholder_type_error(tcx, None, visitor.0, false, None, "constant");
}
hir::TraitItemKind::Type(_, Some(_)) => {
@ -898,7 +847,7 @@ fn convert_trait_item(tcx: TyCtxt<'_>, trait_item_id: hir::TraitItemId) {
// Account for `type T = _;`.
let mut visitor = HirPlaceholderCollector::default();
visitor.visit_trait_item(trait_item);
placeholder_type_error(tcx, None, &[], visitor.0, false, None, "associated type");
placeholder_type_error(tcx, None, visitor.0, false, None, "associated type");
}
hir::TraitItemKind::Type(_, None) => {
@ -908,7 +857,7 @@ fn convert_trait_item(tcx: TyCtxt<'_>, trait_item_id: hir::TraitItemId) {
let mut visitor = HirPlaceholderCollector::default();
visitor.visit_trait_item(trait_item);
placeholder_type_error(tcx, None, &[], visitor.0, false, None, "associated type");
placeholder_type_error(tcx, None, visitor.0, false, None, "associated type");
}
};
@ -930,7 +879,7 @@ fn convert_impl_item(tcx: TyCtxt<'_>, impl_item_id: hir::ImplItemId) {
let mut visitor = HirPlaceholderCollector::default();
visitor.visit_impl_item(impl_item);
placeholder_type_error(tcx, None, &[], visitor.0, false, None, "associated type");
placeholder_type_error(tcx, None, visitor.0, false, None, "associated type");
}
hir::ImplItemKind::Const(..) => {}
}
@ -1893,15 +1842,14 @@ fn fn_sig(tcx: TyCtxt<'_>, def_id: DefId) -> ty::PolyFnSig<'_> {
match tcx.hir().get(hir_id) {
TraitItem(hir::TraitItem {
kind: TraitItemKind::Fn(sig, TraitFn::Provided(_)),
ident,
generics,
..
})
| Item(hir::Item { kind: ItemKind::Fn(sig, generics, _), ident, .. }) => {
infer_return_ty_for_fn_sig(tcx, sig, *ident, generics, def_id, &icx)
| Item(hir::Item { kind: ItemKind::Fn(sig, generics, _), .. }) => {
infer_return_ty_for_fn_sig(tcx, sig, generics, def_id, &icx)
}
ImplItem(hir::ImplItem { kind: ImplItemKind::Fn(sig, _), ident, generics, .. }) => {
ImplItem(hir::ImplItem { kind: ImplItemKind::Fn(sig, _), generics, .. }) => {
// Do not try to inference the return type for a impl method coming from a trait
if let Item(hir::Item { kind: ItemKind::Impl(i), .. }) =
tcx.hir().get(tcx.hir().get_parent_node(hir_id))
@ -1913,18 +1861,16 @@ fn fn_sig(tcx: TyCtxt<'_>, def_id: DefId) -> ty::PolyFnSig<'_> {
sig.header.unsafety,
sig.header.abi,
sig.decl,
generics,
Some(ident.span),
Some(generics),
None,
)
} else {
infer_return_ty_for_fn_sig(tcx, sig, *ident, generics, def_id, &icx)
infer_return_ty_for_fn_sig(tcx, sig, generics, def_id, &icx)
}
}
TraitItem(hir::TraitItem {
kind: TraitItemKind::Fn(FnSig { header, decl, span: _ }, _),
ident,
generics,
..
}) => <dyn AstConv<'_>>::ty_of_fn(
@ -1933,16 +1879,13 @@ fn fn_sig(tcx: TyCtxt<'_>, def_id: DefId) -> ty::PolyFnSig<'_> {
header.unsafety,
header.abi,
decl,
generics,
Some(ident.span),
Some(generics),
None,
),
ForeignItem(&hir::ForeignItem {
kind: ForeignItemKind::Fn(fn_decl, _, _), ident, ..
}) => {
ForeignItem(&hir::ForeignItem { kind: ForeignItemKind::Fn(fn_decl, _, _), .. }) => {
let abi = tcx.hir().get_foreign_abi(hir_id);
compute_sig_of_foreign_fn_decl(tcx, def_id.to_def_id(), fn_decl, abi, ident)
compute_sig_of_foreign_fn_decl(tcx, def_id.to_def_id(), fn_decl, abi)
}
Ctor(data) | Variant(hir::Variant { data, .. }) if data.ctor_hir_id().is_some() => {
@ -1983,7 +1926,6 @@ fn fn_sig(tcx: TyCtxt<'_>, def_id: DefId) -> ty::PolyFnSig<'_> {
fn infer_return_ty_for_fn_sig<'tcx>(
tcx: TyCtxt<'tcx>,
sig: &hir::FnSig<'_>,
ident: Ident,
generics: &hir::Generics<'_>,
def_id: LocalDefId,
icx: &ItemCtxt<'tcx>,
@ -2038,8 +1980,7 @@ fn infer_return_ty_for_fn_sig<'tcx>(
sig.header.unsafety,
sig.header.abi,
sig.decl,
generics,
Some(ident.span),
Some(generics),
None,
),
}
@ -2200,16 +2141,16 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericP
let icx = ItemCtxt::new(tcx, def_id);
const NO_GENERICS: &hir::Generics<'_> = &hir::Generics::empty();
const NO_GENERICS: &hir::Generics<'_> = hir::Generics::empty();
// We use an `IndexSet` to preserves order of insertion.
// Preserving the order of insertion is important here so as not to break UI tests.
let mut predicates: FxIndexSet<(ty::Predicate<'_>, Span)> = FxIndexSet::default();
let ast_generics = match node {
Node::TraitItem(item) => &item.generics,
Node::TraitItem(item) => item.generics,
Node::ImplItem(item) => &item.generics,
Node::ImplItem(item) => item.generics,
Node::Item(item) => {
match item.kind {
@ -2223,15 +2164,15 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericP
| ItemKind::TyAlias(_, ref generics)
| ItemKind::Enum(_, ref generics)
| ItemKind::Struct(_, ref generics)
| ItemKind::Union(_, ref generics) => generics,
| ItemKind::Union(_, ref generics) => *generics,
ItemKind::Trait(_, _, ref generics, ..) => {
is_trait = Some(ty::TraitRef::identity(tcx, def_id));
generics
*generics
}
ItemKind::TraitAlias(ref generics, _) => {
is_trait = Some(ty::TraitRef::identity(tcx, def_id));
generics
*generics
}
ItemKind::OpaqueTy(OpaqueTy {
origin: hir::OpaqueTyOrigin::AsyncFn(..) | hir::OpaqueTyOrigin::FnReturn(..),
@ -2268,7 +2209,7 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericP
Node::ForeignItem(item) => match item.kind {
ForeignItemKind::Static(..) => NO_GENERICS,
ForeignItemKind::Fn(_, _, ref generics) => generics,
ForeignItemKind::Fn(_, _, ref generics) => *generics,
ForeignItemKind::Type => NO_GENERICS,
},
@ -2302,29 +2243,9 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericP
// Collect the region predicates that were declared inline as
// well. In the case of parameters declared on a fn or method, we
// have to be careful to only iterate over early-bound regions.
let mut index = parent_count + has_own_self as u32;
for param in early_bound_lifetimes_from_generics(tcx, hir_id.owner, ast_generics) {
let region = tcx.mk_region(ty::ReEarlyBound(ty::EarlyBoundRegion {
def_id: tcx.hir().local_def_id(param.hir_id).to_def_id(),
index,
name: param.name.ident().name,
}));
index += 1;
match param.kind {
GenericParamKind::Lifetime { .. } => {
param.bounds.iter().for_each(|bound| match bound {
hir::GenericBound::Outlives(lt) => {
let bound = <dyn AstConv<'_>>::ast_region_to_region(&icx, lt, None);
let outlives = ty::Binder::dummy(ty::OutlivesPredicate(region, bound));
predicates.insert((outlives.to_predicate(tcx), lt.span));
}
_ => bug!(),
});
}
_ => bug!(),
}
}
let mut index = parent_count
+ has_own_self as u32
+ early_bound_lifetimes_from_generics(tcx, hir_id.owner, ast_generics).count() as u32;
// Collect the predicates that were written inline by the user on each
// type parameter (e.g., `<T: Foo>`).
@ -2337,28 +2258,26 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericP
let param_ty = ty::ParamTy::new(index, name).to_ty(tcx);
index += 1;
let mut bounds = <dyn AstConv<'_>>::compute_bounds(&icx, param_ty, param.bounds);
let mut bounds = Bounds::default();
// Params are implicitly sized unless a `?Sized` bound is found
<dyn AstConv<'_>>::add_implicitly_sized(
&icx,
&mut bounds,
param.bounds,
Some((param.hir_id, ast_generics.where_clause.predicates)),
&[],
Some((param.hir_id, ast_generics.predicates)),
param.span,
);
predicates.extend(bounds.predicates(tcx, param_ty));
}
GenericParamKind::Const { .. } => {
// Bounds on const parameters are currently not possible.
debug_assert!(param.bounds.is_empty());
index += 1;
}
}
}
// Add in the bounds that appear in the where-clause.
let where_clause = &ast_generics.where_clause;
for predicate in where_clause.predicates {
for predicate in ast_generics.predicates {
match predicate {
hir::WherePredicate::BoundPredicate(bound_pred) => {
let ty = icx.to_ty(bound_pred.bounded_ty);
@ -2616,7 +2535,6 @@ fn compute_sig_of_foreign_fn_decl<'tcx>(
def_id: DefId,
decl: &'tcx hir::FnDecl<'tcx>,
abi: abi::Abi,
ident: Ident,
) -> ty::PolyFnSig<'tcx> {
let unsafety = if abi == abi::Abi::RustIntrinsic {
intrinsic_operation_unsafety(tcx.item_name(def_id))
@ -2630,8 +2548,7 @@ fn compute_sig_of_foreign_fn_decl<'tcx>(
unsafety,
abi,
decl,
&hir::Generics::empty(),
Some(ident.span),
None,
None,
);

View File

@ -337,8 +337,8 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> {
icx.to_ty(ty)
}
}
ItemKind::TyAlias(self_ty, _)
| ItemKind::Impl(hir::Impl { self_ty, .. }) => icx.to_ty(self_ty),
ItemKind::TyAlias(self_ty, _) => icx.to_ty(self_ty),
ItemKind::Impl(hir::Impl { self_ty, .. }) => icx.to_ty(*self_ty),
ItemKind::Fn(..) => {
let substs = InternalSubsts::identity_for_item(tcx, def_id.to_def_id());
tcx.mk_fn_def(def_id.to_def_id(), substs)

View File

@ -213,7 +213,7 @@ fn check_main_fn_ty(tcx: TyCtxt<'_>, main_def_id: DefId) {
let hir_id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local());
match tcx.hir().find(hir_id) {
Some(Node::Item(hir::Item { kind: hir::ItemKind::Fn(_, ref generics, _), .. })) => {
generics.where_clause.span()
generics.where_clause_span()
}
_ => {
span_bug!(tcx.def_span(def_id), "main has a non-function type");
@ -408,7 +408,7 @@ fn check_start_fn_ty(tcx: TyCtxt<'_>, start_def_id: DefId) {
.emit();
error = true;
}
if let Some(sp) = generics.where_clause.span() {
if let Some(sp) = generics.where_clause_span() {
struct_span_err!(
tcx.sess,
sp,

View File

@ -49,8 +49,6 @@ def check_generic_param(param):
ty = param["kind"]["type"]
if ty["default"]:
check_type(ty["default"])
for bound in ty["bounds"]:
check_generic_bound(bound)
elif "const" in param["kind"]:
check_type(param["kind"]["const"])

View File

@ -238,9 +238,12 @@ impl Clean<Option<Lifetime>> for ty::Region<'_> {
}
}
impl Clean<WherePredicate> for hir::WherePredicate<'_> {
fn clean(&self, cx: &mut DocContext<'_>) -> WherePredicate {
match *self {
impl Clean<Option<WherePredicate>> for hir::WherePredicate<'_> {
fn clean(&self, cx: &mut DocContext<'_>) -> Option<WherePredicate> {
if !self.in_where_clause() {
return None;
}
Some(match *self {
hir::WherePredicate::BoundPredicate(ref wbp) => {
let bound_params = wbp
.bound_generic_params
@ -250,11 +253,7 @@ impl Clean<WherePredicate> for hir::WherePredicate<'_> {
// Higher-ranked lifetimes can't have bounds.
assert_matches!(
param,
hir::GenericParam {
kind: hir::GenericParamKind::Lifetime { .. },
bounds: [],
..
}
hir::GenericParam { kind: hir::GenericParamKind::Lifetime { .. }, .. }
);
Lifetime(param.name.ident().name)
})
@ -275,7 +274,7 @@ impl Clean<WherePredicate> for hir::WherePredicate<'_> {
lhs: wrp.lhs_ty.clean(cx),
rhs: wrp.rhs_ty.clean(cx).into(),
},
}
})
}
}
@ -456,44 +455,75 @@ impl Clean<GenericParamDef> for ty::GenericParamDef {
}
}
impl Clean<GenericParamDef> for hir::GenericParam<'_> {
fn clean(&self, cx: &mut DocContext<'_>) -> GenericParamDef {
let (name, kind) = match self.kind {
hir::GenericParamKind::Lifetime { .. } => {
let outlives = self
.bounds
fn clean_generic_param(
cx: &mut DocContext<'_>,
generics: Option<&hir::Generics<'_>>,
param: &hir::GenericParam<'_>,
) -> GenericParamDef {
let (name, kind) = match param.kind {
hir::GenericParamKind::Lifetime { .. } => {
let outlives = if let Some(generics) = generics {
generics
.predicates
.iter()
.flat_map(|pred| {
match pred {
hir::WherePredicate::RegionPredicate(rp)
if rp.lifetime.name == hir::LifetimeName::Param(param.name)
&& !rp.in_where_clause =>
{
rp.bounds
}
_ => &[],
}
.iter()
})
.map(|bound| match bound {
hir::GenericBound::Outlives(lt) => lt.clean(cx),
_ => panic!(),
})
.collect();
(self.name.ident().name, GenericParamDefKind::Lifetime { outlives })
}
hir::GenericParamKind::Type { ref default, synthetic } => (
self.name.ident().name,
.collect()
} else {
Vec::new()
};
(param.name.ident().name, GenericParamDefKind::Lifetime { outlives })
}
hir::GenericParamKind::Type { ref default, synthetic } => {
let did = cx.tcx.hir().local_def_id(param.hir_id);
let bounds = if let Some(generics) = generics {
generics
.bounds_for_param(did)
.filter(|bp| !bp.in_where_clause)
.flat_map(|bp| bp.bounds)
.filter_map(|x| x.clean(cx))
.collect()
} else {
Vec::new()
};
(
param.name.ident().name,
GenericParamDefKind::Type {
did: cx.tcx.hir().local_def_id(self.hir_id).to_def_id(),
bounds: self.bounds.iter().filter_map(|x| x.clean(cx)).collect(),
did: did.to_def_id(),
bounds,
default: default.map(|t| t.clean(cx)).map(Box::new),
synthetic,
},
),
hir::GenericParamKind::Const { ref ty, default } => (
self.name.ident().name,
GenericParamDefKind::Const {
did: cx.tcx.hir().local_def_id(self.hir_id).to_def_id(),
ty: Box::new(ty.clean(cx)),
default: default.map(|ct| {
let def_id = cx.tcx.hir().local_def_id(ct.hir_id);
Box::new(ty::Const::from_anon_const(cx.tcx, def_id).to_string())
}),
},
),
};
)
}
hir::GenericParamKind::Const { ref ty, default } => (
param.name.ident().name,
GenericParamDefKind::Const {
did: cx.tcx.hir().local_def_id(param.hir_id).to_def_id(),
ty: Box::new(ty.clean(cx)),
default: default.map(|ct| {
let def_id = cx.tcx.hir().local_def_id(ct.hir_id);
Box::new(ty::Const::from_anon_const(cx.tcx, def_id).to_string())
}),
},
),
};
GenericParamDef { name, kind }
}
GenericParamDef { name, kind }
}
impl Clean<Generics> for hir::Generics<'_> {
@ -524,7 +554,7 @@ impl Clean<Generics> for hir::Generics<'_> {
.iter()
.filter(|param| is_impl_trait(param))
.map(|param| {
let param: GenericParamDef = param.clean(cx);
let param = clean_generic_param(cx, Some(self), param);
match param.kind {
GenericParamDefKind::Lifetime { .. } => unreachable!(),
GenericParamDefKind::Type { did, ref bounds, .. } => {
@ -538,14 +568,14 @@ impl Clean<Generics> for hir::Generics<'_> {
let mut params = Vec::with_capacity(self.params.len());
for p in self.params.iter().filter(|p| !is_impl_trait(p) && !is_elided_lifetime(p)) {
let p = p.clean(cx);
let p = clean_generic_param(cx, Some(self), p);
params.push(p);
}
params.extend(impl_trait_params);
let mut generics = Generics {
params,
where_predicates: self.where_clause.predicates.iter().map(|x| x.clean(cx)).collect(),
where_predicates: self.predicates.iter().filter_map(|x| x.clean(cx)).collect(),
};
// Some duplicates are generated for ?Sized bounds between type params and where
@ -954,7 +984,11 @@ impl Clean<PolyTrait> for hir::PolyTraitRef<'_> {
fn clean(&self, cx: &mut DocContext<'_>) -> PolyTrait {
PolyTrait {
trait_: self.trait_ref.clean(cx),
generic_params: self.bound_generic_params.iter().map(|x| x.clean(cx)).collect(),
generic_params: self
.bound_generic_params
.iter()
.map(|x| clean_generic_param(cx, None, x))
.collect(),
}
}
}
@ -1823,7 +1857,8 @@ impl Clean<BareFunctionDecl> for hir::BareFnTy<'_> {
fn clean(&self, cx: &mut DocContext<'_>) -> BareFunctionDecl {
let (generic_params, decl) = enter_impl_trait(cx, |cx| {
// NOTE: generics must be cleaned before args
let generic_params = self.generic_params.iter().map(|x| x.clean(cx)).collect();
let generic_params =
self.generic_params.iter().map(|x| clean_generic_param(cx, None, x)).collect();
let args = clean_args_from_types_and_names(cx, self.decl.inputs, self.param_names);
let decl = clean_fn_decl_with_args(cx, self.decl, args);
(generic_params, decl)

View File

@ -5,7 +5,7 @@ use rustc_data_structures::fx::FxHashMap;
use rustc_hir::def::{DefKind, Res};
use rustc_hir::def_id::DefId;
use rustc_hir::intravisit::{self, Visitor};
use rustc_hir::{ExprKind, GenericParam, GenericParamKind, HirId, Mod, Node};
use rustc_hir::{ExprKind, GenericParam, HirId, Mod, Node};
use rustc_middle::hir::nested_filter;
use rustc_middle::ty::TyCtxt;
use rustc_span::Span;
@ -100,16 +100,7 @@ impl<'tcx> Visitor<'tcx> for SpanMapVisitor<'tcx> {
self.tcx.hir()
}
fn visit_generic_param(&mut self, p: &'tcx GenericParam<'tcx>) {
if !matches!(p.kind, GenericParamKind::Type { .. }) {
return;
}
for bound in p.bounds {
if let Some(trait_ref) = bound.trait_ref() {
self.handle_path(trait_ref.path, None);
}
}
}
fn visit_generic_param(&mut self, _: &'tcx GenericParam<'tcx>) {}
fn visit_path(&mut self, path: &'tcx rustc_hir::Path<'tcx>, _id: HirId) {
self.handle_path(path, None);

View File

@ -14,10 +14,10 @@ note: captured value is not `Send` because `&` references cannot be sent unless
LL | let x = x;
| ^ has type `&T` which is not `Send`, because `T` is not `Sync`
= note: required for the cast to the object type `dyn Future<Output = ()> + Send`
help: consider further restricting type parameter `T`
help: consider further restricting this bound
|
LL | where 'me:'async_trait, T: std::marker::Sync {
| ++++++++++++++++++++++
LL | fn bar<'me, 'async_trait, T: Send + std::marker::Sync>(x: &'me T)
| +++++++++++++++++++
error: aborting due to previous error

View File

@ -2,9 +2,12 @@ error[E0310]: the parameter type `T` may not live long enough
--> $DIR/builtin-superkinds-self-type.rs:10:16
|
LL | impl <T: Sync> Foo for T { }
| -- ^^^ ...so that the type `T` will meet its required lifetime bounds
| |
| help: consider adding an explicit lifetime bound...: `T: 'static +`
| ^^^ ...so that the type `T` will meet its required lifetime bounds
|
help: consider adding an explicit lifetime bound...
|
LL | impl <T: Sync + 'static> Foo for T { }
| +++++++++
error: aborting due to previous error

View File

@ -1,8 +1,6 @@
error[E0310]: the parameter type `U` may not live long enough
--> $DIR/feature-gate-infer_static_outlives_requirements.rs:5:10
|
LL | struct Foo<U> {
| - help: consider adding an explicit lifetime bound...: `U: 'static`
LL | bar: Bar<U>
| ^^^^^^ ...so that the type `U` will meet its required lifetime bounds...
|
@ -11,6 +9,10 @@ note: ...that is required by this bound
|
LL | struct Bar<T: 'static> {
| ^^^^^^^
help: consider adding an explicit lifetime bound...
|
LL | struct Foo<U: 'static> {
| +++++++++
error: aborting due to previous error

View File

@ -1,10 +1,7 @@
error[E0311]: the parameter type `T` may not live long enough
--> $DIR/issue-86483.rs:5:1
|
LL | pub trait IceIce<T>
| ^ - help: consider adding an explicit lifetime bound...: `T: 'a`
| _|
| |
LL | / pub trait IceIce<T>
LL | | where
LL | | for<'a> T: 'a,
LL | | {
@ -19,13 +16,14 @@ note: ...that is required by this bound
|
LL | for<'a> T: 'a,
| ^^
help: consider adding an explicit lifetime bound...
|
LL | for<'a> T: 'a + 'a,
| ++++
error[E0311]: the parameter type `T` may not live long enough
--> $DIR/issue-86483.rs:9:5
|
LL | pub trait IceIce<T>
| - help: consider adding an explicit lifetime bound...: `T: 'a`
...
LL | type Ice<'v>: IntoIterator<Item = &'v T>;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds...
|
@ -34,6 +32,10 @@ note: ...that is required by this bound
|
LL | for<'a> T: 'a,
| ^^
help: consider adding an explicit lifetime bound...
|
LL | for<'a> T: 'a + 'a,
| ++++
error[E0309]: the parameter type `T` may not live long enough
--> $DIR/issue-86483.rs:9:32

View File

@ -1,10 +1,13 @@
error[E0311]: the parameter type `T` may not live long enough
--> $DIR/issue-91139.rs:27:12
|
LL | fn foo<T>() {
| - help: consider adding an explicit lifetime bound...: `T: 'a`
LL | let _: for<'a> fn(<() as Foo<T>>::Type<'a>, &'a T) = |_, _| ();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds
|
help: consider adding an explicit lifetime bound...
|
LL | fn foo<T: 'a>() {
| ++++
error: aborting due to previous error

View File

@ -2,17 +2,23 @@ error[E0311]: the parameter type `C` may not live long enough
--> $DIR/issue-92096.rs:20:33
|
LL | fn call_connect<C>(c: &'_ C) -> impl '_ + Future + Send
| - ^^^^^^^^^^^^^^^^^^^^^^^ ...so that the type `C` will meet its required lifetime bounds
| |
| help: consider adding an explicit lifetime bound...: `C: 'a`
| ^^^^^^^^^^^^^^^^^^^^^^^ ...so that the type `C` will meet its required lifetime bounds
|
help: consider adding an explicit lifetime bound...
|
LL | C: Client + Send + Sync + 'a,
| ++++
error[E0311]: the parameter type `C` may not live long enough
--> $DIR/issue-92096.rs:20:33
|
LL | fn call_connect<C>(c: &'_ C) -> impl '_ + Future + Send
| - ^^^^^^^^^^^^^^^^^^^^^^^ ...so that the type `C` will meet its required lifetime bounds
| |
| help: consider adding an explicit lifetime bound...: `C: 'a`
| ^^^^^^^^^^^^^^^^^^^^^^^ ...so that the type `C` will meet its required lifetime bounds
|
help: consider adding an explicit lifetime bound...
|
LL | C: Client + Send + Sync + 'a,
| ++++
error: aborting due to 2 previous errors

View File

@ -87,10 +87,10 @@ note: tuple struct defined here
|
LL | struct E<B>(B);
| ^
help: consider further restricting type parameter `B`
help: consider further restricting this bound
|
LL | impl<B: Add> Add for E<B> where <B as Add>::Output = B, B: Add<Output = B> {
| ++++++++++++++++++++
LL | impl<B: Add + Add<Output = B>> Add for E<B> where <B as Add>::Output = B {
| +++++++++++++++++
error: aborting due to 5 previous errors

View File

@ -2,7 +2,7 @@ warning: unnecessary lifetime parameter `'a`
--> $DIR/unsatified-item-lifetime-bound.rs:4:12
|
LL | type Y<'a: 'static>;
| ^^^^^^^^^^^
| ^^
|
= help: you can use the `'static` lifetime directly, in place of `'a`

View File

@ -2,7 +2,7 @@ warning: unnecessary lifetime parameter `'a`
--> $DIR/equal-hidden-lifetimes.rs:7:25
|
LL | fn equal_regions_static<'a: 'static>(x: &'a i32) -> impl Sized {
| ^^^^^^^^^^^
| ^^
|
= help: you can use the `'static` lifetime directly, in place of `'a`

View File

@ -112,11 +112,13 @@ LL | fn move_lifetime_into_fn<'a, 'b>(x: &'a u32, y: &'b u32) -> impl Fn(&'a u32
error[E0310]: the parameter type `T` may not live long enough
--> $DIR/must_outlive_least_region_or_bound.rs:40:5
|
LL | fn ty_param_wont_outlive_static<T:Debug>(x: T) -> impl Debug + 'static {
| -- help: consider adding an explicit lifetime bound...: `T: 'static +`
LL |
LL | x
| ^ ...so that the type `T` will meet its required lifetime bounds
|
help: consider adding an explicit lifetime bound...
|
LL | fn ty_param_wont_outlive_static<T:Debug + 'static>(x: T) -> impl Debug + 'static {
| +++++++++
error: aborting due to 9 previous errors

View File

@ -128,9 +128,12 @@ error[E0310]: the parameter type `T` may not live long enough
--> $DIR/must_outlive_least_region_or_bound.rs:38:51
|
LL | fn ty_param_wont_outlive_static<T:Debug>(x: T) -> impl Debug + 'static {
| -- ^^^^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds
| |
| help: consider adding an explicit lifetime bound...: `T: 'static +`
| ^^^^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds
|
help: consider adding an explicit lifetime bound...
|
LL | fn ty_param_wont_outlive_static<T:Debug + 'static>(x: T) -> impl Debug + 'static {
| +++++++++
error[E0759]: `x` has an anonymous lifetime `'_` but it needs to satisfy a `'static` lifetime requirement
--> $DIR/must_outlive_least_region_or_bound.rs:16:50

View File

@ -1,11 +1,13 @@
error[E0310]: the parameter type `T` may not live long enough
--> $DIR/type_parameters_captured.rs:9:5
|
LL | fn foo<T>(x: T) -> impl Any + 'static {
| - help: consider adding an explicit lifetime bound...: `T: 'static`
LL |
LL | x
| ^ ...so that the type `T` will meet its required lifetime bounds
|
help: consider adding an explicit lifetime bound...
|
LL | fn foo<T: 'static>(x: T) -> impl Any + 'static {
| +++++++++
error: aborting due to previous error

View File

@ -2,9 +2,12 @@ error[E0310]: the parameter type `T` may not live long enough
--> $DIR/type_parameters_captured.rs:7:20
|
LL | fn foo<T>(x: T) -> impl Any + 'static {
| - ^^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds
| |
| help: consider adding an explicit lifetime bound...: `T: 'static`
| ^^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds
|
help: consider adding an explicit lifetime bound...
|
LL | fn foo<T: 'static>(x: T) -> impl Any + 'static {
| +++++++++
error: aborting due to previous error

View File

@ -5,6 +5,7 @@ trait Trait { type Out; }
struct Test<'a> { s: &'a str }
fn silly<'y, 'z>(_s: &'y Test<'z>) -> &'y <Test<'z> as Trait>::Out where 'z: 'static {
//~^ WARN unnecessary lifetime parameter `'z`
let x = Test { s: "this cannot last" };
&x
//~^ ERROR: cannot return reference to local variable `x`

View File

@ -1,9 +1,17 @@
warning: unnecessary lifetime parameter `'z`
--> $DIR/issue-30438-c.rs:7:74
|
LL | fn silly<'y, 'z>(_s: &'y Test<'z>) -> &'y <Test<'z> as Trait>::Out where 'z: 'static {
| ^^
|
= help: you can use the `'static` lifetime directly, in place of `'z`
error[E0515]: cannot return reference to local variable `x`
--> $DIR/issue-30438-c.rs:9:5
--> $DIR/issue-30438-c.rs:10:5
|
LL | &x
| ^^ returns a reference to data owned by the current function
error: aborting due to previous error
error: aborting due to previous error; 1 warning emitted
For more information about this error, try `rustc --explain E0515`.

View File

@ -1,18 +1,24 @@
error[E0310]: the parameter type `T` may not live long enough
--> $DIR/lifetime-doesnt-live-long-enough.rs:19:10
|
LL | struct Foo<T> {
| - help: consider adding an explicit lifetime bound...: `T: 'static`
LL | foo: &'static T
| ^^^^^^^^^^ ...so that the reference type `&'static T` does not outlive the data it points at
|
help: consider adding an explicit lifetime bound...
|
LL | struct Foo<T: 'static> {
| +++++++++
error[E0309]: the parameter type `K` may not live long enough
--> $DIR/lifetime-doesnt-live-long-enough.rs:24:19
|
LL | trait X<K>: Sized {
| - help: consider adding an explicit lifetime bound...: `K: 'a`
LL | fn foo<'a, L: X<&'a Nested<K>>>();
| ^^^^^^^^^^^^^^^^ ...so that the reference type `&'a Nested<K>` does not outlive the data it points at
|
help: consider adding an explicit lifetime bound...
|
LL | trait X<K: 'a>: Sized {
| ++++
error[E0309]: the parameter type `Self` may not live long enough
--> $DIR/lifetime-doesnt-live-long-enough.rs:28:19
@ -27,25 +33,34 @@ error[E0309]: the parameter type `L` may not live long enough
--> $DIR/lifetime-doesnt-live-long-enough.rs:32:22
|
LL | fn baz<'a, L, M: X<&'a Nested<L>>>() {
| - ^^^^^^^^^^^^^^^^ ...so that the reference type `&'a Nested<L>` does not outlive the data it points at
| |
| help: consider adding an explicit lifetime bound...: `L: 'a`
| ^^^^^^^^^^^^^^^^ ...so that the reference type `&'a Nested<L>` does not outlive the data it points at
|
help: consider adding an explicit lifetime bound...
|
LL | fn baz<'a, L: 'a, M: X<&'a Nested<L>>>() {
| ++++
error[E0309]: the parameter type `K` may not live long enough
--> $DIR/lifetime-doesnt-live-long-enough.rs:41:33
|
LL | impl<K> Nested<K> {
| - help: consider adding an explicit lifetime bound...: `K: 'a`
LL | fn generic_in_parent<'a, L: X<&'a Nested<K>>>() {
| ^^^^^^^^^^^^^^^^ ...so that the reference type `&'a Nested<K>` does not outlive the data it points at
|
help: consider adding an explicit lifetime bound...
|
LL | impl<K: 'a> Nested<K> {
| ++++
error[E0309]: the parameter type `M` may not live long enough
--> $DIR/lifetime-doesnt-live-long-enough.rs:44:36
|
LL | fn generic_in_child<'a, 'b, L: X<&'a Nested<M>>, M: 'b>() {
| ^^^^^^^^^^^^^^^^ -- help: consider adding an explicit lifetime bound...: `M: 'a +`
| |
| ...so that the reference type `&'a Nested<M>` does not outlive the data it points at
| ^^^^^^^^^^^^^^^^ ...so that the reference type `&'a Nested<M>` does not outlive the data it points at
|
help: consider adding an explicit lifetime bound...
|
LL | fn generic_in_child<'a, 'b, L: X<&'a Nested<M>>, M: 'b + 'a>() {
| ++++
error: aborting due to 6 previous errors

View File

@ -1,10 +1,13 @@
error[E0310]: the parameter type `T` may not live long enough
--> $DIR/issue_74400.rs:12:5
|
LL | fn g<T>(data: &[T]) {
| - help: consider adding an explicit lifetime bound...: `T: 'static`
LL | f(data, identity)
| ^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds
|
help: consider adding an explicit lifetime bound...
|
LL | fn g<T: 'static>(data: &[T]) {
| +++++++++
error[E0308]: mismatched types
--> $DIR/issue_74400.rs:12:5

View File

@ -54,17 +54,17 @@ where
fn duplicate_custom_3<T>(t: S<T>) -> (S<T>, S<T>)
where
T: A,
T: B, T: Trait, T: Copy
//~^ HELP consider further restricting type parameter `T`
T: A + Trait + Copy,
//~^ HELP consider further restricting this bound
T: B,
{
(t, t) //~ use of moved value: `t`
}
fn duplicate_custom_4<T: A>(t: S<T>) -> (S<T>, S<T>)
fn duplicate_custom_4<T: A + Trait + Copy>(t: S<T>) -> (S<T>, S<T>)
//~^ HELP consider further restricting this bound
where
T: B + Trait + Copy,
//~^ HELP consider further restricting this bound
T: B,
{
(t, t) //~ use of moved value: `t`
}
@ -77,8 +77,8 @@ fn existing_colon<T: Copy>(t: T) {
fn existing_colon_in_where<T>(t: T)
where
T: Copy,
//~^ HELP consider further restricting this bound
T:, T: Copy
//~^ HELP consider further restricting type parameter `T`
{
[t, t]; //~ use of moved value: `t`
}

View File

@ -55,16 +55,16 @@ where
fn duplicate_custom_3<T>(t: S<T>) -> (S<T>, S<T>)
where
T: A,
//~^ HELP consider further restricting this bound
T: B,
//~^ HELP consider further restricting type parameter `T`
{
(t, t) //~ use of moved value: `t`
}
fn duplicate_custom_4<T: A>(t: S<T>) -> (S<T>, S<T>)
//~^ HELP consider further restricting this bound
where
T: B,
//~^ HELP consider further restricting this bound
{
(t, t) //~ use of moved value: `t`
}
@ -78,7 +78,7 @@ fn existing_colon<T:>(t: T) {
fn existing_colon_in_where<T>(t: T)
where
T:,
//~^ HELP consider further restricting this bound
//~^ HELP consider further restricting type parameter `T`
{
[t, t]; //~ use of moved value: `t`
}

View File

@ -121,10 +121,10 @@ LL | (t, t)
| |
| value moved here
|
help: consider further restricting type parameter `T`
help: consider further restricting this bound
|
LL | T: B, T: Trait, T: Copy
| ~~~~~~~~~~~~~~~~~~~
LL | T: A + Trait + Copy,
| ++++++++++++++
error[E0382]: use of moved value: `t`
--> $DIR/use_of_moved_value_copy_suggestions.rs:69:9
@ -139,8 +139,8 @@ LL | (t, t)
|
help: consider further restricting this bound
|
LL | T: B + Trait + Copy,
| ++++++++++++++
LL | fn duplicate_custom_4<T: A + Trait + Copy>(t: S<T>) -> (S<T>, S<T>)
| ++++++++++++++
error[E0382]: use of moved value: `t`
--> $DIR/use_of_moved_value_copy_suggestions.rs:83:9
@ -153,10 +153,10 @@ LL | [t, t];
| |
| value moved here
|
help: consider further restricting this bound
help: consider further restricting type parameter `T`
|
LL | T: Copy,
| ++++
LL | T:, T: Copy
| ~~~~~~~~~
error[E0382]: use of moved value: `t`
--> $DIR/use_of_moved_value_copy_suggestions.rs:75:9

View File

@ -36,9 +36,6 @@ LL | | }
error[E0309]: the parameter type `T` may not live long enough
--> $DIR/propagate-from-trait-match.rs:32:36
|
LL | fn supply<'a, T>(value: T)
| - help: consider adding an explicit lifetime bound...: `T: 'a`
...
LL | establish_relationships(value, |value| {
| ____________________________________^
LL | |
@ -48,6 +45,11 @@ LL | | // This function call requires that
LL | | require(value);
LL | | });
| |_____^ ...so that the type `T` will meet its required lifetime bounds
|
help: consider adding an explicit lifetime bound...
|
LL | T: Trait<'a> + 'a,
| ++++
error: aborting due to previous error

View File

@ -1,20 +1,24 @@
error[E0309]: the parameter type `T` may not live long enough
--> $DIR/impl-trait-outlives.rs:11:5
|
LL | fn no_region<'a, T>(x: Box<T>) -> impl Debug + 'a
| - help: consider adding an explicit lifetime bound...: `T: 'a`
...
LL | x
| ^ ...so that the type `T` will meet its required lifetime bounds
|
help: consider adding an explicit lifetime bound...
|
LL | T: Debug + 'a,
| ++++
error[E0309]: the parameter type `T` may not live long enough
--> $DIR/impl-trait-outlives.rs:26:5
|
LL | fn wrong_region<'a, 'b, T>(x: Box<T>) -> impl Debug + 'a
| - help: consider adding an explicit lifetime bound...: `T: 'a`
...
LL | x
| ^ ...so that the type `T` will meet its required lifetime bounds
|
help: consider adding an explicit lifetime bound...
|
LL | T: 'b + Debug + 'a,
| ++++
error: aborting due to 2 previous errors

View File

@ -1,10 +1,13 @@
error[E0310]: the parameter type `T` may not live long enough
--> $DIR/projection-implied-bounds.rs:30:18
|
LL | fn generic2<T: Iterator>(value: T) {
| -- help: consider adding an explicit lifetime bound...: `T: 'static +`
LL | twice(value, |value_ref, item| invoke2(value_ref, item));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds
|
help: consider adding an explicit lifetime bound...
|
LL | fn generic2<T: Iterator + 'static>(value: T) {
| +++++++++
error: aborting due to previous error

View File

@ -31,11 +31,13 @@ LL | | }
error[E0309]: the parameter type `T` may not live long enough
--> $DIR/projection-one-region-closure.rs:45:29
|
LL | fn no_relationships_late<'a, 'b, T>(cell: Cell<&'a ()>, t: T)
| - help: consider adding an explicit lifetime bound...: `T: 'a`
...
LL | with_signature(cell, t, |cell, t| require(cell, t));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds
|
help: consider adding an explicit lifetime bound...
|
LL | T: Anything<'b> + 'a,
| ++++
error: lifetime may not live long enough
--> $DIR/projection-one-region-closure.rs:45:39
@ -82,11 +84,13 @@ LL | | }
error[E0309]: the parameter type `T` may not live long enough
--> $DIR/projection-one-region-closure.rs:56:29
|
LL | fn no_relationships_early<'a, 'b, T>(cell: Cell<&'a ()>, t: T)
| - help: consider adding an explicit lifetime bound...: `T: 'a`
...
LL | with_signature(cell, t, |cell, t| require(cell, t));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds
|
help: consider adding an explicit lifetime bound...
|
LL | T: Anything<'b> + 'a,
| ++++
error: lifetime may not live long enough
--> $DIR/projection-one-region-closure.rs:56:39

View File

@ -1,11 +1,13 @@
error[E0309]: the parameter type `T` may not live long enough
--> $DIR/projection-where-clause-none.rs:16:5
|
LL | fn foo<'a, T>() -> &'a ()
| - help: consider adding an explicit lifetime bound...: `T: 'a`
...
LL | bar::<T::Output>()
| ^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds
|
help: consider adding an explicit lifetime bound...
|
LL | T: MyTrait<'a> + 'a,
| ++++
error: aborting due to previous error

View File

@ -52,10 +52,13 @@ LL | | }
error[E0309]: the parameter type `T` may not live long enough
--> $DIR/ty-param-closure-approximate-lower-bound.rs:29:24
|
LL | fn generic_fail<'a, T>(cell: Cell<&'a ()>, value: T) {
| - help: consider adding an explicit lifetime bound...: `T: 'a`
LL | twice(cell, value, |a, b| invoke(a, b));
| ^^^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds
|
help: consider adding an explicit lifetime bound...
|
LL | fn generic_fail<'a, T: 'a>(cell: Cell<&'a ()>, value: T) {
| ++++
error: aborting due to previous error

View File

@ -29,20 +29,24 @@ LL | | }
error[E0309]: the parameter type `T` may not live long enough
--> $DIR/ty-param-closure-outlives-from-return-type.rs:26:23
|
LL | fn no_region<'a, T>(x: Box<T>) -> Box<dyn Debug + 'a>
| - help: consider adding an explicit lifetime bound...: `T: 'a`
...
LL | with_signature(x, |y| y)
| ^^^^^ ...so that the type `T` will meet its required lifetime bounds
|
help: consider adding an explicit lifetime bound...
|
LL | T: Debug + 'a,
| ++++
error[E0309]: the parameter type `T` may not live long enough
--> $DIR/ty-param-closure-outlives-from-return-type.rs:41:5
|
LL | fn wrong_region<'a, 'b, T>(x: Box<T>) -> Box<Debug + 'a>
| - help: consider adding an explicit lifetime bound...: `T: 'a`
...
LL | x
| ^ ...so that the type `T` will meet its required lifetime bounds
|
help: consider adding an explicit lifetime bound...
|
LL | T: 'b + Debug + 'a,
| ++++
error: aborting due to 2 previous errors

View File

@ -37,8 +37,6 @@ LL | | }
error[E0309]: the parameter type `T` may not live long enough
--> $DIR/ty-param-closure-outlives-from-where-clause.rs:27:26
|
LL | fn no_region<'a, T>(a: Cell<&'a ()>, b: T) {
| - help: consider adding an explicit lifetime bound...: `T: 'a`
LL | with_signature(a, b, |x, y| {
| __________________________^
LL | |
@ -48,6 +46,11 @@ LL | | // See `correct_region`, which explains the point of this
LL | | require(&x, &y)
LL | | })
| |_____^ ...so that the type `T` will meet its required lifetime bounds
|
help: consider adding an explicit lifetime bound...
|
LL | fn no_region<'a, T: 'a>(a: Cell<&'a ()>, b: T) {
| ++++
note: external requirements
--> $DIR/ty-param-closure-outlives-from-where-clause.rs:43:26
@ -121,9 +124,6 @@ LL | | }
error[E0309]: the parameter type `T` may not live long enough
--> $DIR/ty-param-closure-outlives-from-where-clause.rs:64:26
|
LL | fn wrong_region<'a, 'b, T>(a: Cell<&'a ()>, b: T)
| - help: consider adding an explicit lifetime bound...: `T: 'a`
...
LL | with_signature(a, b, |x, y| {
| __________________________^
LL | |
@ -131,6 +131,11 @@ LL | | // See `correct_region`
LL | | require(&x, &y)
LL | | })
| |_____^ ...so that the type `T` will meet its required lifetime bounds
|
help: consider adding an explicit lifetime bound...
|
LL | T: 'b + 'a,
| ++++
note: external requirements
--> $DIR/ty-param-closure-outlives-from-where-clause.rs:77:26

View File

@ -1,10 +1,13 @@
error[E0309]: the parameter type `T` may not live long enough
--> $DIR/ty-param-fn-body.rs:19:5
|
LL | fn region_static<'a, T>(cell: Cell<&'a usize>, t: T) {
| - help: consider adding an explicit lifetime bound...: `T: 'a`
LL | outlives(cell, t)
| ^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds
|
help: consider adding an explicit lifetime bound...
|
LL | fn region_static<'a, T: 'a>(cell: Cell<&'a usize>, t: T) {
| ++++
error: aborting due to previous error

View File

@ -1,20 +1,24 @@
error[E0309]: the parameter type `T` may not live long enough
--> $DIR/ty-param-fn.rs:11:5
|
LL | fn no_region<'a, T>(x: Box<T>) -> Box<Debug + 'a>
| - help: consider adding an explicit lifetime bound...: `T: 'a`
...
LL | x
| ^ ...so that the type `T` will meet its required lifetime bounds
|
help: consider adding an explicit lifetime bound...
|
LL | T: Debug + 'a,
| ++++
error[E0309]: the parameter type `T` may not live long enough
--> $DIR/ty-param-fn.rs:26:5
|
LL | fn wrong_region<'a, 'b, T>(x: Box<T>) -> Box<Debug + 'a>
| - help: consider adding an explicit lifetime bound...: `T: 'a`
...
LL | x
| ^ ...so that the type `T` will meet its required lifetime bounds
|
help: consider adding an explicit lifetime bound...
|
LL | T: 'b + Debug + 'a,
| ++++
error: aborting due to 2 previous errors

View File

@ -1,26 +1,35 @@
error[E0310]: the parameter type `U` may not live long enough
--> $DIR/regions-close-object-into-object-4.rs:13:5
|
LL | fn i<'a, T, U>(v: Box<dyn A<U>+'a>) -> Box<dyn X + 'static> {
| - help: consider adding an explicit lifetime bound...: `U: 'static`
LL | Box::new(B(&*v)) as Box<dyn X>
| ^^^^^^^^ ...so that the type `U` will meet its required lifetime bounds
|
help: consider adding an explicit lifetime bound...
|
LL | fn i<'a, T, U: 'static>(v: Box<dyn A<U>+'a>) -> Box<dyn X + 'static> {
| +++++++++
error[E0310]: the parameter type `U` may not live long enough
--> $DIR/regions-close-object-into-object-4.rs:13:5
|
LL | fn i<'a, T, U>(v: Box<dyn A<U>+'a>) -> Box<dyn X + 'static> {
| - help: consider adding an explicit lifetime bound...: `U: 'static`
LL | Box::new(B(&*v)) as Box<dyn X>
| ^^^^^^^^^^^^^^^^ ...so that the type `U` will meet its required lifetime bounds
|
help: consider adding an explicit lifetime bound...
|
LL | fn i<'a, T, U: 'static>(v: Box<dyn A<U>+'a>) -> Box<dyn X + 'static> {
| +++++++++
error[E0310]: the parameter type `U` may not live long enough
--> $DIR/regions-close-object-into-object-4.rs:13:5
|
LL | fn i<'a, T, U>(v: Box<dyn A<U>+'a>) -> Box<dyn X + 'static> {
| - help: consider adding an explicit lifetime bound...: `U: 'static`
LL | Box::new(B(&*v)) as Box<dyn X>
| ^^^^^^^^^^^^^^^^ ...so that the type `U` will meet its required lifetime bounds
|
help: consider adding an explicit lifetime bound...
|
LL | fn i<'a, T, U: 'static>(v: Box<dyn A<U>+'a>) -> Box<dyn X + 'static> {
| +++++++++
error: lifetime may not live long enough
--> $DIR/regions-close-object-into-object-4.rs:13:5
@ -51,10 +60,13 @@ LL | Box::new(B(&*v)) as Box<dyn X>
error[E0310]: the parameter type `U` may not live long enough
--> $DIR/regions-close-object-into-object-4.rs:13:14
|
LL | fn i<'a, T, U>(v: Box<dyn A<U>+'a>) -> Box<dyn X + 'static> {
| - help: consider adding an explicit lifetime bound...: `U: 'static`
LL | Box::new(B(&*v)) as Box<dyn X>
| ^^^^^^ ...so that the type `U` will meet its required lifetime bounds
|
help: consider adding an explicit lifetime bound...
|
LL | fn i<'a, T, U: 'static>(v: Box<dyn A<U>+'a>) -> Box<dyn X + 'static> {
| +++++++++
error: aborting due to 6 previous errors

View File

@ -1,9 +1,6 @@
error[E0310]: the parameter type `T` may not live long enough
--> $DIR/regions-close-object-into-object-5.rs:21:5
|
LL | fn f<'a, T, U>(v: Box<A<T> + 'static>) -> Box<X + 'static> {
| - help: consider adding an explicit lifetime bound...: `T: 'static`
LL | // oh dear!
LL | Box::new(B(&*v)) as Box<dyn X>
| ^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds...
|
@ -12,22 +9,25 @@ note: ...that is required by this bound
|
LL | struct B<'a, T: 'a>(&'a (A<T> + 'a));
| ^^
help: consider adding an explicit lifetime bound...
|
LL | fn f<'a, T: 'static, U>(v: Box<A<T> + 'static>) -> Box<X + 'static> {
| +++++++++
error[E0310]: the parameter type `T` may not live long enough
--> $DIR/regions-close-object-into-object-5.rs:21:5
|
LL | fn f<'a, T, U>(v: Box<A<T> + 'static>) -> Box<X + 'static> {
| - help: consider adding an explicit lifetime bound...: `T: 'static`
LL | // oh dear!
LL | Box::new(B(&*v)) as Box<dyn X>
| ^^^^^^^^^^^^^^^^ ...so that the type `B<'_, T>` will meet its required lifetime bounds
|
help: consider adding an explicit lifetime bound...
|
LL | fn f<'a, T: 'static, U>(v: Box<A<T> + 'static>) -> Box<X + 'static> {
| +++++++++
error[E0310]: the parameter type `T` may not live long enough
--> $DIR/regions-close-object-into-object-5.rs:21:14
|
LL | fn f<'a, T, U>(v: Box<A<T> + 'static>) -> Box<X + 'static> {
| - help: consider adding an explicit lifetime bound...: `T: 'static`
LL | // oh dear!
LL | Box::new(B(&*v)) as Box<dyn X>
| ^ ...so that the type `T` will meet its required lifetime bounds...
|
@ -36,13 +36,14 @@ note: ...that is required by this bound
|
LL | struct B<'a, T: 'a>(&'a (A<T> + 'a));
| ^^
help: consider adding an explicit lifetime bound...
|
LL | fn f<'a, T: 'static, U>(v: Box<A<T> + 'static>) -> Box<X + 'static> {
| +++++++++
error[E0310]: the parameter type `T` may not live long enough
--> $DIR/regions-close-object-into-object-5.rs:21:14
|
LL | fn f<'a, T, U>(v: Box<A<T> + 'static>) -> Box<X + 'static> {
| - help: consider adding an explicit lifetime bound...: `T: 'static`
LL | // oh dear!
LL | Box::new(B(&*v)) as Box<dyn X>
| ^^^^^^ ...so that the type `T` will meet its required lifetime bounds...
|
@ -51,33 +52,43 @@ note: ...that is required by this bound
|
LL | struct B<'a, T: 'a>(&'a (A<T> + 'a));
| ^^
help: consider adding an explicit lifetime bound...
|
LL | fn f<'a, T: 'static, U>(v: Box<A<T> + 'static>) -> Box<X + 'static> {
| +++++++++
error[E0310]: the parameter type `T` may not live long enough
--> $DIR/regions-close-object-into-object-5.rs:21:16
|
LL | fn f<'a, T, U>(v: Box<A<T> + 'static>) -> Box<X + 'static> {
| - help: consider adding an explicit lifetime bound...: `T: 'static`
LL | // oh dear!
LL | Box::new(B(&*v)) as Box<dyn X>
| ^^^ ...so that the reference type `&dyn A<T>` does not outlive the data it points at
|
help: consider adding an explicit lifetime bound...
|
LL | fn f<'a, T: 'static, U>(v: Box<A<T> + 'static>) -> Box<X + 'static> {
| +++++++++
error[E0310]: the parameter type `T` may not live long enough
--> $DIR/regions-close-object-into-object-5.rs:21:16
|
LL | fn f<'a, T, U>(v: Box<A<T> + 'static>) -> Box<X + 'static> {
| - help: consider adding an explicit lifetime bound...: `T: 'static`
LL | // oh dear!
LL | Box::new(B(&*v)) as Box<dyn X>
| ^^^ ...so that the type `(dyn A<T> + 'static)` is not borrowed for too long
|
help: consider adding an explicit lifetime bound...
|
LL | fn f<'a, T: 'static, U>(v: Box<A<T> + 'static>) -> Box<X + 'static> {
| +++++++++
error[E0310]: the parameter type `T` may not live long enough
--> $DIR/regions-close-object-into-object-5.rs:21:16
|
LL | fn f<'a, T, U>(v: Box<A<T> + 'static>) -> Box<X + 'static> {
| - help: consider adding an explicit lifetime bound...: `T: 'static`
LL | // oh dear!
LL | Box::new(B(&*v)) as Box<dyn X>
| ^^^ ...so that the type `(dyn A<T> + 'static)` is not borrowed for too long
|
help: consider adding an explicit lifetime bound...
|
LL | fn f<'a, T: 'static, U>(v: Box<A<T> + 'static>) -> Box<X + 'static> {
| +++++++++
error: aborting due to 7 previous errors

View File

@ -1,29 +1,35 @@
error[E0310]: the parameter type `T` may not live long enough
--> $DIR/regions-close-object-into-object-5.rs:21:5
|
LL | fn f<'a, T, U>(v: Box<A<T> + 'static>) -> Box<X + 'static> {
| - help: consider adding an explicit lifetime bound...: `T: 'static`
LL | // oh dear!
LL | Box::new(B(&*v)) as Box<dyn X>
| ^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds
|
help: consider adding an explicit lifetime bound...
|
LL | fn f<'a, T: 'static, U>(v: Box<A<T> + 'static>) -> Box<X + 'static> {
| +++++++++
error[E0310]: the parameter type `T` may not live long enough
--> $DIR/regions-close-object-into-object-5.rs:21:5
|
LL | fn f<'a, T, U>(v: Box<A<T> + 'static>) -> Box<X + 'static> {
| - help: consider adding an explicit lifetime bound...: `T: 'static`
LL | // oh dear!
LL | Box::new(B(&*v)) as Box<dyn X>
| ^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds
|
help: consider adding an explicit lifetime bound...
|
LL | fn f<'a, T: 'static, U>(v: Box<A<T> + 'static>) -> Box<X + 'static> {
| +++++++++
error[E0310]: the parameter type `T` may not live long enough
--> $DIR/regions-close-object-into-object-5.rs:21:5
|
LL | fn f<'a, T, U>(v: Box<A<T> + 'static>) -> Box<X + 'static> {
| - help: consider adding an explicit lifetime bound...: `T: 'static`
LL | // oh dear!
LL | Box::new(B(&*v)) as Box<dyn X>
| ^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds
|
help: consider adding an explicit lifetime bound...
|
LL | fn f<'a, T: 'static, U>(v: Box<A<T> + 'static>) -> Box<X + 'static> {
| +++++++++
error[E0515]: cannot return value referencing local data `*v`
--> $DIR/regions-close-object-into-object-5.rs:21:5
@ -37,11 +43,13 @@ LL | Box::new(B(&*v)) as Box<dyn X>
error[E0310]: the parameter type `T` may not live long enough
--> $DIR/regions-close-object-into-object-5.rs:21:14
|
LL | fn f<'a, T, U>(v: Box<A<T> + 'static>) -> Box<X + 'static> {
| - help: consider adding an explicit lifetime bound...: `T: 'static`
LL | // oh dear!
LL | Box::new(B(&*v)) as Box<dyn X>
| ^^^^^^ ...so that the type `T` will meet its required lifetime bounds
|
help: consider adding an explicit lifetime bound...
|
LL | fn f<'a, T: 'static, U>(v: Box<A<T> + 'static>) -> Box<X + 'static> {
| +++++++++
error: aborting due to 5 previous errors

View File

@ -1,18 +1,24 @@
error[E0310]: the parameter type `A` may not live long enough
--> $DIR/regions-close-over-type-parameter-1.rs:15:5
|
LL | fn make_object1<A: SomeTrait>(v: A) -> Box<dyn SomeTrait + 'static> {
| -- help: consider adding an explicit lifetime bound...: `A: 'static +`
LL | Box::new(v) as Box<dyn SomeTrait + 'static>
| ^^^^^^^^^^^ ...so that the type `A` will meet its required lifetime bounds
|
help: consider adding an explicit lifetime bound...
|
LL | fn make_object1<A: SomeTrait + 'static>(v: A) -> Box<dyn SomeTrait + 'static> {
| +++++++++
error[E0309]: the parameter type `A` may not live long enough
--> $DIR/regions-close-over-type-parameter-1.rs:24:5
|
LL | fn make_object3<'a, 'b, A: SomeTrait + 'a>(v: A) -> Box<dyn SomeTrait + 'b> {
| -- help: consider adding an explicit lifetime bound...: `A: 'b +`
LL | Box::new(v) as Box<dyn SomeTrait + 'b>
| ^^^^^^^^^^^ ...so that the type `A` will meet its required lifetime bounds
|
help: consider adding an explicit lifetime bound...
|
LL | fn make_object3<'a, 'b, A: SomeTrait + 'a + 'b>(v: A) -> Box<dyn SomeTrait + 'b> {
| ++++
error: aborting due to 2 previous errors

View File

@ -1,18 +1,24 @@
error[E0310]: the parameter type `A` may not live long enough
--> $DIR/regions-close-over-type-parameter-1.rs:15:5
|
LL | fn make_object1<A: SomeTrait>(v: A) -> Box<dyn SomeTrait + 'static> {
| -- help: consider adding an explicit lifetime bound...: `A: 'static +`
LL | Box::new(v) as Box<dyn SomeTrait + 'static>
| ^^^^^^^^^^^ ...so that the type `A` will meet its required lifetime bounds
|
help: consider adding an explicit lifetime bound...
|
LL | fn make_object1<A: SomeTrait + 'static>(v: A) -> Box<dyn SomeTrait + 'static> {
| +++++++++
error[E0309]: the parameter type `A` may not live long enough
--> $DIR/regions-close-over-type-parameter-1.rs:24:5
|
LL | fn make_object3<'a, 'b, A: SomeTrait + 'a>(v: A) -> Box<dyn SomeTrait + 'b> {
| -- help: consider adding an explicit lifetime bound...: `A: 'b +`
LL | Box::new(v) as Box<dyn SomeTrait + 'b>
| ^^^^^^^^^^^ ...so that the type `A` will meet its required lifetime bounds
|
help: consider adding an explicit lifetime bound...
|
LL | fn make_object3<'a, 'b, A: SomeTrait + 'a + 'b>(v: A) -> Box<dyn SomeTrait + 'b> {
| ++++
error: aborting due to 2 previous errors

View File

@ -1,38 +1,46 @@
error[E0310]: the parameter type `T` may not live long enough
--> $DIR/regions-close-param-into-object.rs:10:5
|
LL | fn p1<T>(v: T) -> Box<dyn X + 'static>
| - help: consider adding an explicit lifetime bound...: `T: 'static`
...
LL | Box::new(v)
| ^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds
|
help: consider adding an explicit lifetime bound...
|
LL | where T : X + 'static
| +++++++++
error[E0310]: the parameter type `T` may not live long enough
--> $DIR/regions-close-param-into-object.rs:16:5
|
LL | fn p2<T>(v: Box<T>) -> Box<dyn X + 'static>
| - help: consider adding an explicit lifetime bound...: `T: 'static`
...
LL | Box::new(v)
| ^^^^^^^^^^^ ...so that the type `Box<T>` will meet its required lifetime bounds
|
help: consider adding an explicit lifetime bound...
|
LL | fn p2<T: 'static>(v: Box<T>) -> Box<dyn X + 'static>
| +++++++++
error[E0309]: the parameter type `T` may not live long enough
--> $DIR/regions-close-param-into-object.rs:22:5
|
LL | fn p3<'a,T>(v: T) -> Box<dyn X + 'a>
| - help: consider adding an explicit lifetime bound...: `T: 'a`
...
LL | Box::new(v)
| ^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds
|
help: consider adding an explicit lifetime bound...
|
LL | where T : X + 'a
| ++++
error[E0309]: the parameter type `T` may not live long enough
--> $DIR/regions-close-param-into-object.rs:28:5
|
LL | fn p4<'a,T>(v: Box<T>) -> Box<dyn X + 'a>
| - help: consider adding an explicit lifetime bound...: `T: 'a`
...
LL | Box::new(v)
| ^^^^^^^^^^^ ...so that the type `Box<T>` will meet its required lifetime bounds
|
help: consider adding an explicit lifetime bound...
|
LL | fn p4<'a,T: 'a>(v: Box<T>) -> Box<dyn X + 'a>
| ++++
error: aborting due to 4 previous errors

View File

@ -1,38 +1,46 @@
error[E0310]: the parameter type `T` may not live long enough
--> $DIR/regions-close-param-into-object.rs:10:5
|
LL | fn p1<T>(v: T) -> Box<dyn X + 'static>
| - help: consider adding an explicit lifetime bound...: `T: 'static`
...
LL | Box::new(v)
| ^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds
|
help: consider adding an explicit lifetime bound...
|
LL | where T : X + 'static
| +++++++++
error[E0310]: the parameter type `T` may not live long enough
--> $DIR/regions-close-param-into-object.rs:16:5
|
LL | fn p2<T>(v: Box<T>) -> Box<dyn X + 'static>
| - help: consider adding an explicit lifetime bound...: `T: 'static`
...
LL | Box::new(v)
| ^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds
|
help: consider adding an explicit lifetime bound...
|
LL | fn p2<T: 'static>(v: Box<T>) -> Box<dyn X + 'static>
| +++++++++
error[E0309]: the parameter type `T` may not live long enough
--> $DIR/regions-close-param-into-object.rs:22:5
|
LL | fn p3<'a,T>(v: T) -> Box<dyn X + 'a>
| - help: consider adding an explicit lifetime bound...: `T: 'a`
...
LL | Box::new(v)
| ^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds
|
help: consider adding an explicit lifetime bound...
|
LL | where T : X + 'a
| ++++
error[E0309]: the parameter type `T` may not live long enough
--> $DIR/regions-close-param-into-object.rs:28:5
|
LL | fn p4<'a,T>(v: Box<T>) -> Box<dyn X + 'a>
| - help: consider adding an explicit lifetime bound...: `T: 'a`
...
LL | Box::new(v)
| ^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds
|
help: consider adding an explicit lifetime bound...
|
LL | fn p4<'a,T: 'a>(v: Box<T>) -> Box<dyn X + 'a>
| ++++
error: aborting due to 4 previous errors

View File

@ -9,7 +9,7 @@
// 'a : 'b
fn test<'a,'b>(x: &'a i32) -> &'b i32
where 'a: 'static
where 'a: 'static //~ WARN unnecessary lifetime parameter `'a`
{
x
}

View File

@ -0,0 +1,10 @@
warning: unnecessary lifetime parameter `'a`
--> $DIR/regions-free-region-outlives-static-outlives-free-region.rs:12:11
|
LL | where 'a: 'static
| ^^
|
= help: you can use the `'static` lifetime directly, in place of `'a`
warning: 1 warning emitted

View File

@ -1,11 +1,13 @@
error[E0309]: the parameter type `T` may not live long enough
--> $DIR/regions-implied-bounds-projection-gap-1.rs:20:10
|
LL | fn func<'x, T:Trait1<'x>>(t: &'x T::Foo)
| -- help: consider adding an explicit lifetime bound...: `T: 'x +`
LL | {
LL | wf::<&'x T>();
| ^^^^^ ...so that the reference type `&'x T` does not outlive the data it points at
|
help: consider adding an explicit lifetime bound...
|
LL | fn func<'x, T:Trait1<'x> + 'x>(t: &'x T::Foo)
| ++++
error: aborting due to previous error

View File

@ -1,11 +1,13 @@
error[E0309]: the parameter type `T` may not live long enough
--> $DIR/regions-implied-bounds-projection-gap-1.rs:20:5
|
LL | fn func<'x, T:Trait1<'x>>(t: &'x T::Foo)
| -- help: consider adding an explicit lifetime bound...: `T: 'x +`
LL | {
LL | wf::<&'x T>();
| ^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds
|
help: consider adding an explicit lifetime bound...
|
LL | fn func<'x, T:Trait1<'x> + 'x>(t: &'x T::Foo)
| ++++
error: aborting due to previous error

View File

@ -1,8 +1,6 @@
error[E0309]: the parameter type `A` may not live long enough
--> $DIR/regions-infer-bound-from-trait.rs:37:5
|
LL | fn bar1<'a,A>(x: Inv<'a>, a: A) {
| - help: consider adding an explicit lifetime bound...: `A: 'a`
LL | check_bound(x, a)
| ^^^^^^^^^^^ ...so that the type `A` will meet its required lifetime bounds...
|
@ -11,12 +9,14 @@ note: ...that is required by this bound
|
LL | fn check_bound<'a,A:'a>(x: Inv<'a>, a: A) { }
| ^^
help: consider adding an explicit lifetime bound...
|
LL | fn bar1<'a,A: 'a>(x: Inv<'a>, a: A) {
| ++++
error[E0309]: the parameter type `A` may not live long enough
--> $DIR/regions-infer-bound-from-trait.rs:41:5
|
LL | fn bar2<'a,'b,A:Is<'b>>(x: Inv<'a>, y: Inv<'b>, a: A) {
| -- help: consider adding an explicit lifetime bound...: `A: 'a +`
LL | check_bound(x, a)
| ^^^^^^^^^^^ ...so that the type `A` will meet its required lifetime bounds...
|
@ -25,6 +25,10 @@ note: ...that is required by this bound
|
LL | fn check_bound<'a,A:'a>(x: Inv<'a>, a: A) { }
| ^^
help: consider adding an explicit lifetime bound...
|
LL | fn bar2<'a,'b,A:Is<'b> + 'a>(x: Inv<'a>, y: Inv<'b>, a: A) {
| ++++
error: aborting due to 2 previous errors

View File

@ -1,18 +1,24 @@
error[E0309]: the parameter type `A` may not live long enough
--> $DIR/regions-infer-bound-from-trait.rs:37:5
|
LL | fn bar1<'a,A>(x: Inv<'a>, a: A) {
| - help: consider adding an explicit lifetime bound...: `A: 'a`
LL | check_bound(x, a)
| ^^^^^^^^^^^^^^^^^ ...so that the type `A` will meet its required lifetime bounds
|
help: consider adding an explicit lifetime bound...
|
LL | fn bar1<'a,A: 'a>(x: Inv<'a>, a: A) {
| ++++
error[E0309]: the parameter type `A` may not live long enough
--> $DIR/regions-infer-bound-from-trait.rs:41:5
|
LL | fn bar2<'a,'b,A:Is<'b>>(x: Inv<'a>, y: Inv<'b>, a: A) {
| -- help: consider adding an explicit lifetime bound...: `A: 'a +`
LL | check_bound(x, a)
| ^^^^^^^^^^^^^^^^^ ...so that the type `A` will meet its required lifetime bounds
|
help: consider adding an explicit lifetime bound...
|
LL | fn bar2<'a,'b,A:Is<'b> + 'a>(x: Inv<'a>, y: Inv<'b>, a: A) {
| ++++
error: aborting due to 2 previous errors

View File

@ -1,10 +1,17 @@
// run-pass
fn invariant_id<'a,'b>(t: &'b mut &'static ()) -> &'b mut &'a ()
where 'a: 'static { t }
//~^ WARN unnecessary lifetime parameter `'a`
fn static_id<'a>(t: &'a ()) -> &'static ()
where 'a: 'static { t }
//~^ WARN unnecessary lifetime parameter `'a`
fn static_id_indirect<'a,'b>(t: &'a ()) -> &'static ()
where 'a: 'b, 'b: 'static { t }
//~^ WARN unnecessary lifetime parameter `'b`
fn ref_id<'a>(t: &'a ()) -> &'a () where 'static: 'a { t }
static UNIT: () = ();

View File

@ -0,0 +1,26 @@
warning: unnecessary lifetime parameter `'a`
--> $DIR/regions-static-bound-rpass.rs:4:11
|
LL | where 'a: 'static { t }
| ^^
|
= help: you can use the `'static` lifetime directly, in place of `'a`
warning: unnecessary lifetime parameter `'a`
--> $DIR/regions-static-bound-rpass.rs:8:11
|
LL | where 'a: 'static { t }
| ^^
|
= help: you can use the `'static` lifetime directly, in place of `'a`
warning: unnecessary lifetime parameter `'b`
--> $DIR/regions-static-bound-rpass.rs:12:19
|
LL | where 'a: 'b, 'b: 'static { t }
| ^^
|
= help: you can use the `'static` lifetime directly, in place of `'b`
warning: 3 warnings emitted

View File

@ -1,18 +1,34 @@
warning: unnecessary lifetime parameter `'a`
--> $DIR/regions-static-bound.rs:6:11
|
LL | where 'a: 'static { t }
| ^^
|
= help: you can use the `'static` lifetime directly, in place of `'a`
warning: unnecessary lifetime parameter `'b`
--> $DIR/regions-static-bound.rs:10:19
|
LL | where 'a: 'b, 'b: 'static { t }
| ^^
|
= help: you can use the `'static` lifetime directly, in place of `'b`
error[E0312]: lifetime of reference outlives lifetime of borrowed content...
--> $DIR/regions-static-bound.rs:10:5
--> $DIR/regions-static-bound.rs:14:5
|
LL | t
| ^
|
= note: ...the reference is valid for the static lifetime...
note: ...but the borrowed content is only valid for the lifetime `'a` as defined here
--> $DIR/regions-static-bound.rs:9:24
--> $DIR/regions-static-bound.rs:13:24
|
LL | fn static_id_wrong_way<'a>(t: &'a ()) -> &'static () where 'static: 'a {
| ^^
error[E0759]: `u` has an anonymous lifetime `'_` but it needs to satisfy a `'static` lifetime requirement
--> $DIR/regions-static-bound.rs:16:5
--> $DIR/regions-static-bound.rs:20:5
|
LL | fn error(u: &(), v: &()) {
| --- this data with an anonymous lifetime `'_`...
@ -20,13 +36,13 @@ LL | static_id(&u);
| ^^^^^^^^^ -- ...is used here...
|
note: ...and is required to live as long as `'static` here
--> $DIR/regions-static-bound.rs:16:5
--> $DIR/regions-static-bound.rs:20:5
|
LL | static_id(&u);
| ^^^^^^^^^
error[E0759]: `v` has an anonymous lifetime `'_` but it needs to satisfy a `'static` lifetime requirement
--> $DIR/regions-static-bound.rs:19:5
--> $DIR/regions-static-bound.rs:23:5
|
LL | fn error(u: &(), v: &()) {
| --- this data with an anonymous lifetime `'_`...
@ -35,12 +51,12 @@ LL | static_id_indirect(&v);
| ^^^^^^^^^^^^^^^^^^ -- ...is used here...
|
note: ...and is required to live as long as `'static` here
--> $DIR/regions-static-bound.rs:19:5
--> $DIR/regions-static-bound.rs:23:5
|
LL | static_id_indirect(&v);
| ^^^^^^^^^^^^^^^^^^
error: aborting due to 3 previous errors
error: aborting due to 3 previous errors; 2 warnings emitted
Some errors have detailed explanations: E0312, E0759.
For more information about an error, try `rustc --explain E0312`.

View File

@ -1,5 +1,21 @@
warning: unnecessary lifetime parameter `'a`
--> $DIR/regions-static-bound.rs:6:11
|
LL | where 'a: 'static { t }
| ^^
|
= help: you can use the `'static` lifetime directly, in place of `'a`
warning: unnecessary lifetime parameter `'b`
--> $DIR/regions-static-bound.rs:10:19
|
LL | where 'a: 'b, 'b: 'static { t }
| ^^
|
= help: you can use the `'static` lifetime directly, in place of `'b`
error: lifetime may not live long enough
--> $DIR/regions-static-bound.rs:10:5
--> $DIR/regions-static-bound.rs:14:5
|
LL | fn static_id_wrong_way<'a>(t: &'a ()) -> &'static () where 'static: 'a {
| -- lifetime `'a` defined here
@ -7,7 +23,7 @@ LL | t
| ^ returning this value requires that `'a` must outlive `'static`
error[E0521]: borrowed data escapes outside of function
--> $DIR/regions-static-bound.rs:16:5
--> $DIR/regions-static-bound.rs:20:5
|
LL | fn error(u: &(), v: &()) {
| - - let's call the lifetime of this reference `'1`
@ -20,7 +36,7 @@ LL | static_id(&u);
| argument requires that `'1` must outlive `'static`
error[E0521]: borrowed data escapes outside of function
--> $DIR/regions-static-bound.rs:19:5
--> $DIR/regions-static-bound.rs:23:5
|
LL | fn error(u: &(), v: &()) {
| - - let's call the lifetime of this reference `'2`
@ -33,6 +49,6 @@ LL | static_id_indirect(&v);
| `v` escapes the function body here
| argument requires that `'2` must outlive `'static`
error: aborting due to 3 previous errors
error: aborting due to 3 previous errors; 2 warnings emitted
For more information about this error, try `rustc --explain E0521`.

View File

@ -4,8 +4,12 @@
fn static_id<'a,'b>(t: &'a ()) -> &'static ()
where 'a: 'static { t }
//~^ WARN unnecessary lifetime parameter `'a`
fn static_id_indirect<'a,'b>(t: &'a ()) -> &'static ()
where 'a: 'b, 'b: 'static { t }
//~^ WARN unnecessary lifetime parameter `'b`
fn static_id_wrong_way<'a>(t: &'a ()) -> &'static () where 'static: 'a {
t
//[base]~^ ERROR E0312

View File

@ -1,8 +1,6 @@
error[E0310]: the parameter type `U` may not live long enough
--> $DIR/dont-infer-static.rs:8:10
|
LL | struct Foo<U> {
| - help: consider adding an explicit lifetime bound...: `U: 'static`
LL | bar: Bar<U>
| ^^^^^^ ...so that the type `U` will meet its required lifetime bounds...
|
@ -11,6 +9,10 @@ note: ...that is required by this bound
|
LL | struct Bar<T: 'static> {
| ^^^^^^^
help: consider adding an explicit lifetime bound...
|
LL | struct Foo<U: 'static> {
| +++++++++
error: aborting due to previous error

View File

@ -1,27 +1,35 @@
error[E0309]: the parameter type `T` may not live long enough
--> $DIR/regions-enum-not-wf.rs:17:18
|
LL | enum Ref1<'a, T> {
| - help: consider adding an explicit lifetime bound...: `T: 'a`
LL | Ref1Variant1(RequireOutlives<'a, T>),
| ^^^^^^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds
|
help: consider adding an explicit lifetime bound...
|
LL | enum Ref1<'a, T: 'a> {
| ++++
error[E0309]: the parameter type `T` may not live long enough
--> $DIR/regions-enum-not-wf.rs:22:25
|
LL | enum Ref2<'a, T> {
| - help: consider adding an explicit lifetime bound...: `T: 'a`
LL | Ref2Variant1,
LL | Ref2Variant2(isize, RequireOutlives<'a, T>),
| ^^^^^^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds
|
help: consider adding an explicit lifetime bound...
|
LL | enum Ref2<'a, T: 'a> {
| ++++
error[E0309]: the parameter type `T` may not live long enough
--> $DIR/regions-enum-not-wf.rs:35:23
|
LL | enum RefDouble<'a, 'b, T> {
| - help: consider adding an explicit lifetime bound...: `T: 'b`
LL | RefDoubleVariant1(&'a RequireOutlives<'b, T>),
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds
|
help: consider adding an explicit lifetime bound...
|
LL | enum RefDouble<'a, 'b, T: 'b> {
| ++++
error: aborting due to 3 previous errors

View File

@ -1,16 +1,17 @@
error[E0309]: the parameter type `T` may not live long enough
--> $DIR/regions-struct-not-wf.rs:13:16
|
LL | impl<'a, T> Trait<'a, T> for usize {
| - help: consider adding an explicit lifetime bound...: `T: 'a`
LL | type Out = &'a T;
| ^^^^^ ...so that the reference type `&'a T` does not outlive the data it points at
|
help: consider adding an explicit lifetime bound...
|
LL | impl<'a, T: 'a> Trait<'a, T> for usize {
| ++++
error[E0309]: the parameter type `T` may not live long enough
--> $DIR/regions-struct-not-wf.rs:21:16
|
LL | impl<'a, T> Trait<'a, T> for u32 {
| - help: consider adding an explicit lifetime bound...: `T: 'a`
LL | type Out = RefOk<'a, T>;
| ^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds...
|
@ -19,6 +20,10 @@ note: ...that is required by this bound
|
LL | struct RefOk<'a, T:'a> {
| ^^
help: consider adding an explicit lifetime bound...
|
LL | impl<'a, T: 'a> Trait<'a, T> for u32 {
| ++++
error[E0491]: in type `&'a &'b T`, reference has a longer lifetime than the data it references
--> $DIR/regions-struct-not-wf.rs:25:16

View File

@ -2,7 +2,7 @@ warning: unnecessary lifetime parameter `'a`
--> $DIR/static-lifetime-bound.rs:1:6
|
LL | fn f<'a: 'static>(_: &'a i32) {}
| ^^^^^^^^^^^
| ^^
|
= help: you can use the `'static` lifetime directly, in place of `'a`

View File

@ -35,7 +35,7 @@ fn test_one_bound_where<X>(x: X) where X: Sized + std::fmt::Debug {
}
#[allow(dead_code)]
fn test_many_bounds_where<X>(x: X) where X: Sized, X: Sized, X: std::fmt::Debug {
fn test_many_bounds_where<X>(x: X) where X: Sized + std::fmt::Debug, X: Sized {
println!("{:?}", x);
//~^ ERROR doesn't implement
}

View File

@ -65,10 +65,10 @@ LL | println!("{:?}", x);
| ^ `X` cannot be formatted using `{:?}` because it doesn't implement `Debug`
|
= note: this error originates in the macro `$crate::format_args_nl` (in Nightly builds, run with -Z macro-backtrace for more info)
help: consider further restricting type parameter `X`
help: consider further restricting this bound
|
LL | fn test_many_bounds_where<X>(x: X) where X: Sized, X: Sized, X: std::fmt::Debug {
| ++++++++++++++++++++
LL | fn test_many_bounds_where<X>(x: X) where X: Sized + std::fmt::Debug, X: Sized {
| +++++++++++++++++
error[E0277]: the size for values of type `Self` cannot be known at compilation time
--> $DIR/bound-suggestions.rs:44:46

View File

@ -8,7 +8,7 @@ LL | foo.hello();
help: the following trait defines an item `hello`, perhaps you need to restrict type parameter `impl Foo` with it:
|
LL | fn test(foo: impl Foo + Bar) {
| ~~~~~~~~~~~~~~
| +++++
error: aborting due to previous error

View File

@ -7,8 +7,8 @@ LL | x.method()
= help: items from traits can only be used if the type parameter is bounded by the trait
help: the following trait defines an item `method`, perhaps you need to restrict type parameter `T` with it:
|
LL | fn call_method<T: Foo + std::fmt::Debug>(x: &T) {
| ~~~~~~~~
LL | fn call_method<T: std::fmt::Debug + Foo>(x: &T) {
| +++++
error[E0599]: no method named `method` found for type parameter `T` in the current scope
--> $DIR/issue-21673.rs:10:7
@ -20,7 +20,7 @@ LL | x.method()
help: the following trait defines an item `method`, perhaps you need to restrict type parameter `T` with it:
|
LL | fn call_method_2<T: Foo>(x: T) {
| ~~~~~~
| +++++
error: aborting due to 2 previous errors

View File

@ -1,8 +1,6 @@
error[E0311]: the parameter type `T` may not live long enough
--> $DIR/missing-lifetimes-in-signature-2.rs:20:5
|
LL | fn func<T: Test>(foo: &Foo, t: T) {
| -- help: consider adding an explicit lifetime bound...: `T: 'a +`
LL | / foo.bar(move |_| {
LL | |
LL | | t.test();
@ -22,6 +20,10 @@ LL | |
LL | | t.test();
LL | | });
| |______^
help: consider adding an explicit lifetime bound...
|
LL | fn func<T: Test + 'a>(foo: &Foo, t: T) {
| ++++
error: aborting due to previous error

View File

@ -1,8 +1,6 @@
error[E0311]: the parameter type `T` may not live long enough
--> $DIR/missing-lifetimes-in-signature-2.rs:20:9
|
LL | fn func<T: Test>(foo: &Foo, t: T) {
| -- help: consider adding an explicit lifetime bound...: `T: 'a +`
LL | foo.bar(move |_| {
| ^^^
|
@ -21,6 +19,10 @@ note: ...that is required by this bound
|
LL | F: 'a,
| ^^
help: consider adding an explicit lifetime bound...
|
LL | fn func<T: Test + 'a>(foo: &Foo, t: T) {
| ++++
error: aborting due to previous error

View File

@ -26,9 +26,6 @@ LL | fn foo<G, T>(g: G, dest: &mut T) -> impl FnOnce() + '_
error[E0311]: the parameter type `G` may not live long enough
--> $DIR/missing-lifetimes-in-signature.rs:31:5
|
LL | fn bar<G, T>(g: G, dest: &mut T) -> impl FnOnce() + '_
| - help: consider adding an explicit lifetime bound...: `G: 'a`
...
LL | / move || {
LL | | *dest = g.get();
LL | | }
@ -46,13 +43,14 @@ LL | / move || {
LL | | *dest = g.get();
LL | | }
| |_____^
help: consider adding an explicit lifetime bound...
|
LL | G: Get<T> + 'a,
| ++++
error[E0311]: the parameter type `G` may not live long enough
--> $DIR/missing-lifetimes-in-signature.rs:53:5
|
LL | fn qux<'a, G: 'a, T>(g: G, dest: &mut T) -> impl FnOnce() + '_
| -- help: consider adding an explicit lifetime bound...: `G: 'b +`
...
LL | / move || {
LL | | *dest = g.get();
LL | | }
@ -70,13 +68,14 @@ LL | / move || {
LL | | *dest = g.get();
LL | | }
| |_____^
help: consider adding an explicit lifetime bound...
|
LL | fn qux<'a, G: 'a + 'b, T>(g: G, dest: &mut T) -> impl FnOnce() + '_
| ++++
error[E0311]: the parameter type `G` may not live long enough
--> $DIR/missing-lifetimes-in-signature.rs:62:9
|
LL | fn qux<'b, G: Get<T> + 'b, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ {
| -- help: consider adding an explicit lifetime bound...: `G: 'c +`
LL |
LL | / move || {
LL | | *dest = g.get();
LL | | }
@ -94,13 +93,14 @@ LL | / move || {
LL | | *dest = g.get();
LL | | }
| |_________^
help: consider adding an explicit lifetime bound...
|
LL | fn qux<'b, G: Get<T> + 'b + 'c, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ {
| ++++
error[E0311]: the parameter type `G` may not live long enough
--> $DIR/missing-lifetimes-in-signature.rs:74:5
|
LL | fn bat<'a, G: 'a, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ + 'a
| -- help: consider adding an explicit lifetime bound...: `G: 'b +`
...
LL | / move || {
LL | | *dest = g.get();
LL | | }
@ -118,6 +118,10 @@ LL | / move || {
LL | | *dest = g.get();
LL | | }
| |_____^
help: consider adding an explicit lifetime bound...
|
LL | fn bat<'a, G: 'a + 'b, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ + 'a
| ++++
error[E0621]: explicit lifetime required in the type of `dest`
--> $DIR/missing-lifetimes-in-signature.rs:74:5
@ -133,13 +137,15 @@ LL | | }
error[E0309]: the parameter type `G` may not live long enough
--> $DIR/missing-lifetimes-in-signature.rs:85:5
|
LL | fn bak<'a, G, T>(g: G, dest: &'a mut T) -> impl FnOnce() + 'a
| - help: consider adding an explicit lifetime bound...: `G: 'a`
...
LL | / move || {
LL | | *dest = g.get();
LL | | }
| |_____^ ...so that the type `G` will meet its required lifetime bounds
|
help: consider adding an explicit lifetime bound...
|
LL | G: Get<T> + 'a,
| ++++
error: aborting due to 8 previous errors

View File

@ -41,8 +41,11 @@ LL | fn bar<G, T>(g: G, dest: &mut T) -> impl FnOnce() + '_
| ^^^^^^^^^^^^^^^^^^
help: consider introducing an explicit lifetime bound
|
LL | fn bar<'a, G: 'a, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ + 'a
| ~~~~~ ++++
LL ~ fn bar<'a, G, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ + 'a
LL |
LL | where
LL ~ G: Get<T> + 'a,
|
error[E0311]: the parameter type `G` may not live long enough
--> $DIR/missing-lifetimes-in-signature.rs:48:45
@ -62,8 +65,8 @@ LL | fn qux<'a, G: 'a, T>(g: G, dest: &mut T) -> impl FnOnce() + '_
| ^^^^^^^^^^^^^^^^^^
help: consider introducing an explicit lifetime bound
|
LL | fn qux<'b, 'a, G: 'b + 'a, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ + 'b
| +++ ~~~~~~~ ++++
LL | fn qux<'b, 'a, G: 'a + 'b, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ + 'b
| +++ ++++ ++++
error[E0311]: the parameter type `G` may not live long enough
--> $DIR/missing-lifetimes-in-signature.rs:60:58
@ -83,8 +86,8 @@ LL | fn qux<'b, G: Get<T> + 'b, T>(g: G, dest: &mut T) -> impl FnOnce() + '_
| ^^^^^^^^^^^^^^^^^^
help: consider introducing an explicit lifetime bound
|
LL | fn qux<'c, 'b, G: 'c + Get<T> + 'b, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ + 'c {
| +++ ~~~~~~~ ++++
LL | fn qux<'c, 'b, G: Get<T> + 'b + 'c, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ + 'c {
| +++ ++++ ++++
error[E0621]: explicit lifetime required in the type of `dest`
--> $DIR/missing-lifetimes-in-signature.rs:69:45
@ -98,9 +101,12 @@ error[E0309]: the parameter type `G` may not live long enough
--> $DIR/missing-lifetimes-in-signature.rs:80:44
|
LL | fn bak<'a, G, T>(g: G, dest: &'a mut T) -> impl FnOnce() + 'a
| - ^^^^^^^^^^^^^^^^^^ ...so that the type `[closure@$DIR/missing-lifetimes-in-signature.rs:85:5: 87:6]` will meet its required lifetime bounds
| |
| help: consider adding an explicit lifetime bound...: `G: 'a`
| ^^^^^^^^^^^^^^^^^^ ...so that the type `[closure@$DIR/missing-lifetimes-in-signature.rs:85:5: 87:6]` will meet its required lifetime bounds
|
help: consider adding an explicit lifetime bound...
|
LL | G: Get<T> + 'a,
| ++++
error: aborting due to 7 previous errors

Some files were not shown because too many files have changed in this diff Show More