Err about fn traits in a single place.
This commit is contained in:
parent
7b285925c8
commit
2e0a80c8c0
5 changed files with 130 additions and 109 deletions
|
@ -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>(
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue