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,
|
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>(
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue