1
Fork 0

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, span: Span,
trait_def_id: DefId, trait_def_id: DefId,
trait_segment: &'_ hir::PathSegment<'_>, 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 let trait_def = self.tcx().trait_def(trait_def_id);
&& trait_segment.args().parenthesized != trait_def.paren_sugar if !trait_def.paren_sugar {
{ if trait_segment.args().parenthesized {
let sess = &self.tcx().sess.parse_sess; // 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. // For now, require that parenthetical notation be used only with `Fn()` etc.
let (msg, sugg) = if trait_def.paren_sugar { let mut err = feature_err(
( &sess.parse_sess,
"the precise format of `Fn`-family traits' type parameters is subject to \ sym::unboxed_closures,
change", span,
Some(format!( "the precise format of `Fn`-family traits' type parameters is subject to change",
"{}{} -> {}", );
trait_segment.ident, // Do not suggest the other syntax if we are in trait impl:
trait_segment // the desugaring would contain an associated type constrait.
.args if !is_impl {
.as_ref() let args = trait_segment
.and_then(|args| args.args.get(0)) .args
.and_then(|arg| match arg { .as_ref()
hir::GenericArg::Type(ty) => match ty.kind { .and_then(|args| args.args.get(0))
hir::TyKind::Tup(t) => t .and_then(|arg| match arg {
.iter() hir::GenericArg::Type(ty) => match ty.kind {
.map(|e| sess.source_map().span_to_snippet(e.span)) hir::TyKind::Tup(t) => t
.collect::<Result<Vec<_>, _>>() .iter()
.map(|a| a.join(", ")), .map(|e| sess.source_map().span_to_snippet(e.span))
_ => sess.source_map().span_to_snippet(ty.span), .collect::<Result<Vec<_>, _>>()
} .map(|a| a.join(", ")),
.map(|s| format!("({})", s)) _ => sess.source_map().span_to_snippet(ty.span),
.ok(), }
_ => None, .map(|s| format!("({})", s))
}) .ok(),
.unwrap_or_else(|| "()".to_string()), _ => None,
trait_segment })
.args() .unwrap_or_else(|| "()".to_string());
.bindings let ret = trait_segment
.iter() .args()
.find_map(|b| match (b.ident.name == sym::Output, &b.kind) { .bindings
(true, hir::TypeBindingKind::Equality { ty }) => { .iter()
sess.source_map().span_to_snippet(ty.span).ok() .find_map(|b| match (b.ident.name == sym::Output, &b.kind) {
} (true, hir::TypeBindingKind::Equality { ty }) => {
_ => None, sess.source_map().span_to_snippet(ty.span).ok()
}) }
.unwrap_or_else(|| "()".to_string()), _ => None,
)), })
) .unwrap_or_else(|| "()".to_string());
} else { err.span_suggestion(
("parenthetical notation is only stable when used with `Fn`-family traits", None) span,
}; "use parenthetical notation instead",
let mut err = feature_err(sess, sym::unboxed_closures, span, msg); format!("{}{} -> {}", trait_segment.ident, args, ret),
if let Some(sugg) = sugg { Applicability::MaybeIncorrect,
let msg = "use parenthetical notation instead"; );
err.span_suggestion(span, msg, sugg, Applicability::MaybeIncorrect);
} }
err.emit(); 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>( 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()), trait_ref.trait_def_id().unwrap_or_else(|| FatalError.raise()),
self_ty, self_ty,
trait_ref.path.segments.last().unwrap(), 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; let infer_args = trait_segment.infer_args;
self.prohibit_generics(trait_ref.path.segments.split_last().unwrap().1); 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( self.instantiate_poly_trait_ref_inner(
hir_id, hir_id,
@ -822,9 +823,15 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
trait_def_id: DefId, trait_def_id: DefId,
self_ty: Ty<'tcx>, self_ty: Ty<'tcx>,
trait_segment: &hir::PathSegment<'_>, trait_segment: &hir::PathSegment<'_>,
is_impl: bool,
) -> ty::TraitRef<'tcx> { ) -> ty::TraitRef<'tcx> {
let (substs, _) = let (substs, _) = self.create_substs_for_ast_trait_ref(
self.create_substs_for_ast_trait_ref(span, trait_def_id, self_ty, trait_segment); span,
trait_def_id,
self_ty,
trait_segment,
is_impl,
);
let assoc_bindings = self.create_assoc_bindings_for_generic_args(trait_segment.args()); let assoc_bindings = self.create_assoc_bindings_for_generic_args(trait_segment.args());
if let Some(b) = assoc_bindings.first() { if let Some(b) = assoc_bindings.first() {
Self::prohibit_assoc_ty_binding(self.tcx(), b.span); Self::prohibit_assoc_ty_binding(self.tcx(), b.span);
@ -839,8 +846,9 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
trait_def_id: DefId, trait_def_id: DefId,
self_ty: Ty<'tcx>, self_ty: Ty<'tcx>,
trait_segment: &'a hir::PathSegment<'a>, trait_segment: &'a hir::PathSegment<'a>,
is_impl: bool,
) -> (SubstsRef<'tcx>, GenericArgCountResult) { ) -> (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( self.create_substs_for_ast_path(
span, span,
@ -1932,7 +1940,8 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
debug!("qpath_to_ty: self_type={:?}", self_ty); 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( let item_substs = self.create_substs_for_associated_item(
tcx, tcx,

View file

@ -121,28 +121,6 @@ fn enforce_trait_manually_implementable(
return; 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 /// 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 --> $DIR/feature-gate-unboxed-closures-manual-impls.rs:9:6
| |
LL | impl Fn<()> for Foo { 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 = 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 = 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 error[E0229]: associated type bindings are not allowed here
--> $DIR/feature-gate-unboxed-closures-manual-impls.rs:16:6 --> $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 --> $DIR/feature-gate-unboxed-closures-manual-impls.rs:23:6
| |
LL | impl FnMut<()> for Bar { 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 = 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 = 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 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 --> $DIR/feature-gate-unboxed-closures-manual-impls.rs:30:6
| |
LL | impl FnOnce<()> for Baz { 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 = 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 = 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 error[E0183]: manual implementations of `FnOnce` are experimental
--> $DIR/feature-gate-unboxed-closures-manual-impls.rs:16:1 --> $DIR/feature-gate-unboxed-closures-manual-impls.rs:30:6
|
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
| |
LL | impl FnOnce<()> for Baz { 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 = 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 --> $DIR/feature-gate-unboxed-closures.rs:5:6
| |
LL | impl FnOnce<(u32, u32)> for Test { 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 = 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 = help: add `#![feature(unboxed_closures)]` to the crate attributes to enable
error[E0183]: manual implementations of `FnOnce` are experimental 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 { 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 = help: add `#![feature(unboxed_closures)]` to the crate attributes to enable