Err about fn traits in a single place.

This commit is contained in:
Camille GILLOT 2022-01-12 23:13:52 +01:00
parent 7b285925c8
commit 2e0a80c8c0
5 changed files with 130 additions and 109 deletions

View file

@ -93,62 +93,96 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
span: Span,
trait_def_id: DefId,
trait_segment: &'_ hir::PathSegment<'_>,
is_impl: bool,
) {
let trait_def = self.tcx().trait_def(trait_def_id);
if self.tcx().features().unboxed_closures {
return;
}
if !self.tcx().features().unboxed_closures
&& trait_segment.args().parenthesized != trait_def.paren_sugar
{
let sess = &self.tcx().sess.parse_sess;
let trait_def = self.tcx().trait_def(trait_def_id);
if !trait_def.paren_sugar {
if trait_segment.args().parenthesized {
// For now, require that parenthetical notation be used only with `Fn()` etc.
let mut err = feature_err(
&self.tcx().sess.parse_sess,
sym::unboxed_closures,
span,
"parenthetical notation is only stable when used with `Fn`-family traits",
);
err.emit();
}
return;
}
let sess = self.tcx().sess;
if !trait_segment.args().parenthesized {
// For now, require that parenthetical notation be used only with `Fn()` etc.
let (msg, sugg) = if trait_def.paren_sugar {
(
"the precise format of `Fn`-family traits' type parameters is subject to \
change",
Some(format!(
"{}{} -> {}",
trait_segment.ident,
trait_segment
.args
.as_ref()
.and_then(|args| args.args.get(0))
.and_then(|arg| match arg {
hir::GenericArg::Type(ty) => match ty.kind {
hir::TyKind::Tup(t) => t
.iter()
.map(|e| sess.source_map().span_to_snippet(e.span))
.collect::<Result<Vec<_>, _>>()
.map(|a| a.join(", ")),
_ => sess.source_map().span_to_snippet(ty.span),
}
.map(|s| format!("({})", s))
.ok(),
_ => None,
})
.unwrap_or_else(|| "()".to_string()),
trait_segment
.args()
.bindings
.iter()
.find_map(|b| match (b.ident.name == sym::Output, &b.kind) {
(true, hir::TypeBindingKind::Equality { ty }) => {
sess.source_map().span_to_snippet(ty.span).ok()
}
_ => None,
})
.unwrap_or_else(|| "()".to_string()),
)),
)
} else {
("parenthetical notation is only stable when used with `Fn`-family traits", None)
};
let mut err = feature_err(sess, sym::unboxed_closures, span, msg);
if let Some(sugg) = sugg {
let msg = "use parenthetical notation instead";
err.span_suggestion(span, msg, sugg, Applicability::MaybeIncorrect);
let mut err = feature_err(
&sess.parse_sess,
sym::unboxed_closures,
span,
"the precise format of `Fn`-family traits' type parameters is subject to change",
);
// Do not suggest the other syntax if we are in trait impl:
// the desugaring would contain an associated type constrait.
if !is_impl {
let args = trait_segment
.args
.as_ref()
.and_then(|args| args.args.get(0))
.and_then(|arg| match arg {
hir::GenericArg::Type(ty) => match ty.kind {
hir::TyKind::Tup(t) => t
.iter()
.map(|e| sess.source_map().span_to_snippet(e.span))
.collect::<Result<Vec<_>, _>>()
.map(|a| a.join(", ")),
_ => sess.source_map().span_to_snippet(ty.span),
}
.map(|s| format!("({})", s))
.ok(),
_ => None,
})
.unwrap_or_else(|| "()".to_string());
let ret = trait_segment
.args()
.bindings
.iter()
.find_map(|b| match (b.ident.name == sym::Output, &b.kind) {
(true, hir::TypeBindingKind::Equality { ty }) => {
sess.source_map().span_to_snippet(ty.span).ok()
}
_ => None,
})
.unwrap_or_else(|| "()".to_string());
err.span_suggestion(
span,
"use parenthetical notation instead",
format!("{}{} -> {}", trait_segment.ident, args, ret),
Applicability::MaybeIncorrect,
);
}
err.emit();
}
if is_impl {
let trait_name = self.tcx().def_path_str(trait_def_id);
struct_span_err!(
self.tcx().sess,
span,
E0183,
"manual implementations of `{}` are experimental",
trait_name,
)
.span_label(
span,
format!("manual implementations of `{}` are experimental", trait_name),
)
.help("add `#![feature(unboxed_closures)]` to the crate attributes to enable")
.emit();
}
}
pub(crate) fn complain_about_assoc_type_not_found<I>(

View file

@ -669,6 +669,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
trait_ref.trait_def_id().unwrap_or_else(|| FatalError.raise()),
self_ty,
trait_ref.path.segments.last().unwrap(),
true,
)
}
@ -765,7 +766,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
let infer_args = trait_segment.infer_args;
self.prohibit_generics(trait_ref.path.segments.split_last().unwrap().1);
self.complain_about_internal_fn_trait(span, trait_def_id, trait_segment);
self.complain_about_internal_fn_trait(span, trait_def_id, trait_segment, false);
self.instantiate_poly_trait_ref_inner(
hir_id,
@ -822,9 +823,15 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
trait_def_id: DefId,
self_ty: Ty<'tcx>,
trait_segment: &hir::PathSegment<'_>,
is_impl: bool,
) -> ty::TraitRef<'tcx> {
let (substs, _) =
self.create_substs_for_ast_trait_ref(span, trait_def_id, self_ty, trait_segment);
let (substs, _) = self.create_substs_for_ast_trait_ref(
span,
trait_def_id,
self_ty,
trait_segment,
is_impl,
);
let assoc_bindings = self.create_assoc_bindings_for_generic_args(trait_segment.args());
if let Some(b) = assoc_bindings.first() {
Self::prohibit_assoc_ty_binding(self.tcx(), b.span);
@ -839,8 +846,9 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
trait_def_id: DefId,
self_ty: Ty<'tcx>,
trait_segment: &'a hir::PathSegment<'a>,
is_impl: bool,
) -> (SubstsRef<'tcx>, GenericArgCountResult) {
self.complain_about_internal_fn_trait(span, trait_def_id, trait_segment);
self.complain_about_internal_fn_trait(span, trait_def_id, trait_segment, is_impl);
self.create_substs_for_ast_path(
span,
@ -1932,7 +1940,8 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
debug!("qpath_to_ty: self_type={:?}", self_ty);
let trait_ref = self.ast_path_to_mono_trait_ref(span, trait_def_id, self_ty, trait_segment);
let trait_ref =
self.ast_path_to_mono_trait_ref(span, trait_def_id, self_ty, trait_segment, false);
let item_substs = self.create_substs_for_associated_item(
tcx,

View file

@ -121,28 +121,6 @@ fn enforce_trait_manually_implementable(
return;
}
}
let trait_name = if did == li.fn_trait() {
"Fn"
} else if did == li.fn_mut_trait() {
"FnMut"
} else if did == li.fn_once_trait() {
"FnOnce"
} else {
return; // everything OK
};
let span = impl_header_span(tcx, impl_def_id);
struct_span_err!(
tcx.sess,
span,
E0183,
"manual implementations of `{}` are experimental",
trait_name
)
.span_label(span, format!("manual implementations of `{}` are experimental", trait_name))
.help("add `#![feature(unboxed_closures)]` to the crate attributes to enable")
.emit();
}
/// We allow impls of marker traits to overlap, so they can't override impls

View file

@ -38,11 +38,27 @@ error[E0658]: the precise format of `Fn`-family traits' type parameters is subje
--> $DIR/feature-gate-unboxed-closures-manual-impls.rs:9:6
|
LL | impl Fn<()> for Foo {
| ^^^^^^ help: use parenthetical notation instead: `Fn() -> ()`
| ^^^^^^
|
= note: see issue #29625 <https://github.com/rust-lang/rust/issues/29625> for more information
= help: add `#![feature(unboxed_closures)]` to the crate attributes to enable
error[E0183]: manual implementations of `Fn` are experimental
--> $DIR/feature-gate-unboxed-closures-manual-impls.rs:9:6
|
LL | impl Fn<()> for Foo {
| ^^^^^^ manual implementations of `Fn` are experimental
|
= help: add `#![feature(unboxed_closures)]` to the crate attributes to enable
error[E0183]: manual implementations of `FnOnce` are experimental
--> $DIR/feature-gate-unboxed-closures-manual-impls.rs:16:6
|
LL | impl FnOnce() for Foo1 {
| ^^^^^^^^ manual implementations of `FnOnce` are experimental
|
= help: add `#![feature(unboxed_closures)]` to the crate attributes to enable
error[E0229]: associated type bindings are not allowed here
--> $DIR/feature-gate-unboxed-closures-manual-impls.rs:16:6
|
@ -53,49 +69,33 @@ error[E0658]: the precise format of `Fn`-family traits' type parameters is subje
--> $DIR/feature-gate-unboxed-closures-manual-impls.rs:23:6
|
LL | impl FnMut<()> for Bar {
| ^^^^^^^^^ help: use parenthetical notation instead: `FnMut() -> ()`
| ^^^^^^^^^
|
= note: see issue #29625 <https://github.com/rust-lang/rust/issues/29625> for more information
= help: add `#![feature(unboxed_closures)]` to the crate attributes to enable
error[E0183]: manual implementations of `FnMut` are experimental
--> $DIR/feature-gate-unboxed-closures-manual-impls.rs:23:6
|
LL | impl FnMut<()> for Bar {
| ^^^^^^^^^ manual implementations of `FnMut` are experimental
|
= help: add `#![feature(unboxed_closures)]` to the crate attributes to enable
error[E0658]: the precise format of `Fn`-family traits' type parameters is subject to change
--> $DIR/feature-gate-unboxed-closures-manual-impls.rs:30:6
|
LL | impl FnOnce<()> for Baz {
| ^^^^^^^^^^ help: use parenthetical notation instead: `FnOnce() -> ()`
| ^^^^^^^^^^
|
= note: see issue #29625 <https://github.com/rust-lang/rust/issues/29625> for more information
= help: add `#![feature(unboxed_closures)]` to the crate attributes to enable
error[E0183]: manual implementations of `Fn` are experimental
--> $DIR/feature-gate-unboxed-closures-manual-impls.rs:9:1
|
LL | impl Fn<()> for Foo {
| ^^^^^^^^^^^^^^^^^^^ manual implementations of `Fn` are experimental
|
= help: add `#![feature(unboxed_closures)]` to the crate attributes to enable
error[E0183]: manual implementations of `FnMut` are experimental
--> $DIR/feature-gate-unboxed-closures-manual-impls.rs:23:1
|
LL | impl FnMut<()> for Bar {
| ^^^^^^^^^^^^^^^^^^^^^^ manual implementations of `FnMut` are experimental
|
= help: add `#![feature(unboxed_closures)]` to the crate attributes to enable
error[E0183]: manual implementations of `FnOnce` are experimental
--> $DIR/feature-gate-unboxed-closures-manual-impls.rs:16:1
|
LL | impl FnOnce() for Foo1 {
| ^^^^^^^^^^^^^^^^^^^^^^ manual implementations of `FnOnce` are experimental
|
= help: add `#![feature(unboxed_closures)]` to the crate attributes to enable
error[E0183]: manual implementations of `FnOnce` are experimental
--> $DIR/feature-gate-unboxed-closures-manual-impls.rs:30:1
--> $DIR/feature-gate-unboxed-closures-manual-impls.rs:30:6
|
LL | impl FnOnce<()> for Baz {
| ^^^^^^^^^^^^^^^^^^^^^^^ manual implementations of `FnOnce` are experimental
| ^^^^^^^^^^ manual implementations of `FnOnce` are experimental
|
= help: add `#![feature(unboxed_closures)]` to the crate attributes to enable

View file

@ -11,16 +11,16 @@ error[E0658]: the precise format of `Fn`-family traits' type parameters is subje
--> $DIR/feature-gate-unboxed-closures.rs:5:6
|
LL | impl FnOnce<(u32, u32)> for Test {
| ^^^^^^^^^^^^^^^^^^ help: use parenthetical notation instead: `FnOnce(u32, u32) -> ()`
| ^^^^^^^^^^^^^^^^^^
|
= note: see issue #29625 <https://github.com/rust-lang/rust/issues/29625> for more information
= help: add `#![feature(unboxed_closures)]` to the crate attributes to enable
error[E0183]: manual implementations of `FnOnce` are experimental
--> $DIR/feature-gate-unboxed-closures.rs:5:1
--> $DIR/feature-gate-unboxed-closures.rs:5:6
|
LL | impl FnOnce<(u32, u32)> for Test {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ manual implementations of `FnOnce` are experimental
| ^^^^^^^^^^^^^^^^^^ manual implementations of `FnOnce` are experimental
|
= help: add `#![feature(unboxed_closures)]` to the crate attributes to enable