Auto merge of #109284 - matthiaskrgr:rollup-aaublsx, r=matthiaskrgr
Rollup of 9 pull requests Successful merges: - #109102 (Erase escaping late-bound regions when probing for ambiguous associated types) - #109200 (Fix index out of bounds in `suggest_trait_fn_ty_for_impl_fn_infer`) - #109211 (E0206 - update description ) - #109222 (Do not ICE for unexpected lifetime with ConstGeneric rib) - #109235 (fallback to lstat when stat fails on Windows) - #109248 (Pass the right HIR back from `get_fn_decl`) - #109251 (Suggest surrounding the macro with `{}` to interpret as a statement) - #109256 (Check for llvm-tools before install) - #109257 (resolve: Improve debug impls for `NameBinding`) Failed merges: r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
85123d2504
@ -1,5 +1,5 @@
|
||||
The `Copy` trait was implemented on a type which is neither a struct nor an
|
||||
enum.
|
||||
The `Copy` trait was implemented on a type which is neither a struct, an
|
||||
enum, nor a union.
|
||||
|
||||
Erroneous code example:
|
||||
|
||||
@ -10,6 +10,6 @@ struct Bar;
|
||||
impl Copy for &'static mut Bar { } // error!
|
||||
```
|
||||
|
||||
You can only implement `Copy` for a struct or an enum.
|
||||
You can only implement `Copy` for a struct, an enum, or a union.
|
||||
The previous example will fail because `&'static mut Bar`
|
||||
is not a struct or enum.
|
||||
is not a struct, an enum, or a union.
|
||||
|
@ -245,12 +245,24 @@ pub(super) fn emit_frag_parse_err(
|
||||
e.note(
|
||||
"the macro call doesn't expand to an expression, but it can expand to a statement",
|
||||
);
|
||||
e.span_suggestion_verbose(
|
||||
site_span.shrink_to_hi(),
|
||||
"add `;` to interpret the expansion as a statement",
|
||||
";",
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
|
||||
if parser.token == token::Semi {
|
||||
if let Ok(snippet) = parser.sess.source_map().span_to_snippet(site_span) {
|
||||
e.span_suggestion_verbose(
|
||||
site_span,
|
||||
"surround the macro invocation with `{}` to interpret the expansion as a statement",
|
||||
format!("{{ {}; }}", snippet),
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
}
|
||||
} else {
|
||||
e.span_suggestion_verbose(
|
||||
site_span.shrink_to_hi(),
|
||||
"add `;` to interpret the expansion as a statement",
|
||||
";",
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
}
|
||||
}
|
||||
},
|
||||
_ => annotate_err_with_kind(&mut e, kind, site_span),
|
||||
|
@ -2396,13 +2396,24 @@ fn probe_traits_that_match_assoc_ty(
|
||||
tcx,
|
||||
infcx.fresh_substs_for_item(DUMMY_SP, impl_def_id),
|
||||
);
|
||||
// I guess we don't need to make a universe unless we need it,
|
||||
// but also we're on the error path, so it doesn't matter here.
|
||||
let universe = infcx.create_next_universe();
|
||||
infcx
|
||||
.can_eq(
|
||||
ty::ParamEnv::empty(),
|
||||
impl_.self_ty(),
|
||||
// Must fold past escaping bound vars too,
|
||||
// since we have those at this point in astconv.
|
||||
tcx.fold_regions(qself_ty, |_, _| tcx.lifetimes.re_erased),
|
||||
tcx.replace_escaping_bound_vars_uncached(qself_ty, ty::fold::FnMutDelegate {
|
||||
regions: &mut |_| tcx.lifetimes.re_erased,
|
||||
types: &mut |bv| tcx.mk_placeholder(ty::PlaceholderType {
|
||||
universe,
|
||||
name: bv.kind,
|
||||
}),
|
||||
consts: &mut |bv, ty| tcx.mk_const(ty::PlaceholderConst {
|
||||
universe,
|
||||
name: bv
|
||||
}, ty),
|
||||
})
|
||||
)
|
||||
})
|
||||
&& tcx.impl_polarity(impl_def_id) != ty::ImplPolarity::Negative
|
||||
@ -3317,10 +3328,13 @@ fn suggest_trait_fn_ty_for_impl_fn_infer(
|
||||
tcx,
|
||||
trait_ref.substs.extend_to(tcx, assoc.def_id, |param, _| tcx.mk_param_from_def(param)),
|
||||
);
|
||||
let fn_sig = tcx.liberate_late_bound_regions(fn_hir_id.expect_owner().to_def_id(), fn_sig);
|
||||
|
||||
let ty = if let Some(arg_idx) = arg_idx { fn_sig.input(arg_idx) } else { fn_sig.output() };
|
||||
|
||||
Some(tcx.liberate_late_bound_regions(fn_hir_id.expect_owner().to_def_id(), ty))
|
||||
Some(if let Some(arg_idx) = arg_idx {
|
||||
*fn_sig.inputs().get(arg_idx)?
|
||||
} else {
|
||||
fn_sig.output()
|
||||
})
|
||||
}
|
||||
|
||||
#[instrument(level = "trace", skip(self, generate_err))]
|
||||
|
@ -299,7 +299,7 @@ fn maybe_get_coercion_reason(&self, hir_id: hir::HirId, sp: Span) -> Option<(Spa
|
||||
{
|
||||
// check that the `if` expr without `else` is the fn body's expr
|
||||
if expr.span == sp {
|
||||
return self.get_fn_decl(hir_id).and_then(|(fn_decl, _)| {
|
||||
return self.get_fn_decl(hir_id).and_then(|(_, fn_decl, _)| {
|
||||
let span = fn_decl.output.span();
|
||||
let snippet = self.tcx.sess.source_map().span_to_snippet(span).ok()?;
|
||||
Some((span, format!("expected `{snippet}` because of this return type")))
|
||||
|
@ -1722,12 +1722,13 @@ fn report_return_mismatched_types<'a>(
|
||||
fcx.suggest_semicolon_at_end(cond_expr.span, &mut err);
|
||||
}
|
||||
}
|
||||
fcx.get_node_fn_decl(parent).map(|(fn_decl, _, is_main)| (fn_decl, is_main))
|
||||
fcx.get_node_fn_decl(parent)
|
||||
.map(|(fn_id, fn_decl, _, is_main)| (fn_id, fn_decl, is_main))
|
||||
} else {
|
||||
fcx.get_fn_decl(parent_id)
|
||||
};
|
||||
|
||||
if let Some((fn_decl, can_suggest)) = fn_decl {
|
||||
if let Some((fn_id, fn_decl, can_suggest)) = fn_decl {
|
||||
if blk_id.is_none() {
|
||||
pointing_at_return_type |= fcx.suggest_missing_return_type(
|
||||
&mut err,
|
||||
@ -1735,7 +1736,7 @@ fn report_return_mismatched_types<'a>(
|
||||
expected,
|
||||
found,
|
||||
can_suggest,
|
||||
fcx.tcx.hir().get_parent_item(id).into(),
|
||||
fn_id,
|
||||
);
|
||||
}
|
||||
if !pointing_at_return_type {
|
||||
@ -1746,17 +1747,11 @@ fn report_return_mismatched_types<'a>(
|
||||
let parent_id = fcx.tcx.hir().get_parent_item(id);
|
||||
let parent_item = fcx.tcx.hir().get_by_def_id(parent_id.def_id);
|
||||
|
||||
if let (Some(expr), Some(_), Some((fn_decl, _, _))) =
|
||||
if let (Some(expr), Some(_), Some((fn_id, fn_decl, _, _))) =
|
||||
(expression, blk_id, fcx.get_node_fn_decl(parent_item))
|
||||
{
|
||||
fcx.suggest_missing_break_or_return_expr(
|
||||
&mut err,
|
||||
expr,
|
||||
fn_decl,
|
||||
expected,
|
||||
found,
|
||||
id,
|
||||
parent_id.into(),
|
||||
&mut err, expr, fn_decl, expected, found, id, fn_id,
|
||||
);
|
||||
}
|
||||
|
||||
@ -1882,7 +1877,7 @@ fn add_impl_trait_explanation<'a>(
|
||||
}
|
||||
|
||||
fn is_return_ty_unsized<'a>(&self, fcx: &FnCtxt<'a, 'tcx>, blk_id: hir::HirId) -> bool {
|
||||
if let Some((fn_decl, _)) = fcx.get_fn_decl(blk_id)
|
||||
if let Some((_, fn_decl, _)) = fcx.get_fn_decl(blk_id)
|
||||
&& let hir::FnRetTy::Return(ty) = fn_decl.output
|
||||
&& let ty = fcx.astconv().ast_ty_to_ty( ty)
|
||||
&& let ty::Dynamic(..) = ty.kind()
|
||||
|
@ -788,7 +788,7 @@ fn check_expr_return(
|
||||
self.ret_coercion_span.set(Some(expr.span));
|
||||
}
|
||||
let cause = self.cause(expr.span, ObligationCauseCode::ReturnNoExpression);
|
||||
if let Some((fn_decl, _)) = self.get_fn_decl(expr.hir_id) {
|
||||
if let Some((_, fn_decl, _)) = self.get_fn_decl(expr.hir_id) {
|
||||
coercion.coerce_forced_unit(
|
||||
self,
|
||||
&cause,
|
||||
|
@ -898,51 +898,74 @@ pub fn resolve_ty_and_res_fully_qualified_call(
|
||||
)
|
||||
}
|
||||
|
||||
/// Given a function `Node`, return its `FnDecl` if it exists, or `None` otherwise.
|
||||
/// Given a function `Node`, return its `HirId` and `FnDecl` if it exists. Given a closure
|
||||
/// that is the child of a function, return that function's `HirId` and `FnDecl` instead.
|
||||
/// This may seem confusing at first, but this is used in diagnostics for `async fn`,
|
||||
/// for example, where most of the type checking actually happens within a nested closure,
|
||||
/// but we often want access to the parent function's signature.
|
||||
///
|
||||
/// Otherwise, return false.
|
||||
pub(in super::super) fn get_node_fn_decl(
|
||||
&self,
|
||||
node: Node<'tcx>,
|
||||
) -> Option<(&'tcx hir::FnDecl<'tcx>, Ident, bool)> {
|
||||
) -> Option<(hir::HirId, &'tcx hir::FnDecl<'tcx>, Ident, bool)> {
|
||||
match node {
|
||||
Node::Item(&hir::Item { ident, kind: hir::ItemKind::Fn(ref sig, ..), .. }) => {
|
||||
Node::Item(&hir::Item {
|
||||
ident,
|
||||
kind: hir::ItemKind::Fn(ref sig, ..),
|
||||
owner_id,
|
||||
..
|
||||
}) => {
|
||||
// This is less than ideal, it will not suggest a return type span on any
|
||||
// method called `main`, regardless of whether it is actually the entry point,
|
||||
// but it will still present it as the reason for the expected type.
|
||||
Some((&sig.decl, ident, ident.name != sym::main))
|
||||
Some((
|
||||
hir::HirId::make_owner(owner_id.def_id),
|
||||
&sig.decl,
|
||||
ident,
|
||||
ident.name != sym::main,
|
||||
))
|
||||
}
|
||||
Node::TraitItem(&hir::TraitItem {
|
||||
ident,
|
||||
kind: hir::TraitItemKind::Fn(ref sig, ..),
|
||||
owner_id,
|
||||
..
|
||||
}) => Some((&sig.decl, ident, true)),
|
||||
}) => Some((hir::HirId::make_owner(owner_id.def_id), &sig.decl, ident, true)),
|
||||
Node::ImplItem(&hir::ImplItem {
|
||||
ident,
|
||||
kind: hir::ImplItemKind::Fn(ref sig, ..),
|
||||
owner_id,
|
||||
..
|
||||
}) => Some((&sig.decl, ident, false)),
|
||||
Node::Expr(&hir::Expr {
|
||||
hir_id,
|
||||
kind: hir::ExprKind::Closure(..),
|
||||
..
|
||||
}) if let Some(Node::Item(&hir::Item {
|
||||
}) => Some((hir::HirId::make_owner(owner_id.def_id), &sig.decl, ident, false)),
|
||||
Node::Expr(&hir::Expr { hir_id, kind: hir::ExprKind::Closure(..), .. })
|
||||
if let Some(Node::Item(&hir::Item {
|
||||
ident,
|
||||
kind: hir::ItemKind::Fn(ref sig, ..),
|
||||
owner_id,
|
||||
..
|
||||
})) = self.tcx.hir().find_parent(hir_id) => Some((
|
||||
hir::HirId::make_owner(owner_id.def_id),
|
||||
&sig.decl,
|
||||
ident,
|
||||
kind: hir::ItemKind::Fn(ref sig, ..),
|
||||
..
|
||||
})) = self.tcx.hir().find_parent(hir_id) => {
|
||||
Some((&sig.decl, ident, ident.name != sym::main))
|
||||
},
|
||||
ident.name != sym::main,
|
||||
)),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
/// Given a `HirId`, return the `FnDecl` of the method it is enclosed by and whether a
|
||||
/// Given a `HirId`, return the `HirId` of the enclosing function, its `FnDecl`, and whether a
|
||||
/// suggestion can be made, `None` otherwise.
|
||||
pub fn get_fn_decl(&self, blk_id: hir::HirId) -> Option<(&'tcx hir::FnDecl<'tcx>, bool)> {
|
||||
pub fn get_fn_decl(
|
||||
&self,
|
||||
blk_id: hir::HirId,
|
||||
) -> Option<(hir::HirId, &'tcx hir::FnDecl<'tcx>, bool)> {
|
||||
// Get enclosing Fn, if it is a function or a trait method, unless there's a `loop` or
|
||||
// `while` before reaching it, as block tail returns are not available in them.
|
||||
self.tcx.hir().get_return_block(blk_id).and_then(|blk_id| {
|
||||
let parent = self.tcx.hir().get(blk_id);
|
||||
self.get_node_fn_decl(parent).map(|(fn_decl, _, is_main)| (fn_decl, is_main))
|
||||
self.get_node_fn_decl(parent)
|
||||
.map(|(fn_id, fn_decl, _, is_main)| (fn_id, fn_decl, is_main))
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -1669,7 +1669,7 @@ fn parent_item_span(&self, id: hir::HirId) -> Option<Span> {
|
||||
/// Given a function block's `HirId`, returns its `FnDecl` if it exists, or `None` otherwise.
|
||||
fn get_parent_fn_decl(&self, blk_id: hir::HirId) -> Option<(&'tcx hir::FnDecl<'tcx>, Ident)> {
|
||||
let parent = self.tcx.hir().get_by_def_id(self.tcx.hir().get_parent_item(blk_id).def_id);
|
||||
self.get_node_fn_decl(parent).map(|(fn_decl, ident, _)| (fn_decl, ident))
|
||||
self.get_node_fn_decl(parent).map(|(_, fn_decl, ident, _)| (fn_decl, ident))
|
||||
}
|
||||
|
||||
/// If `expr` is a `match` expression that has only one non-`!` arm, use that arm's tail
|
||||
|
@ -64,8 +64,7 @@ pub fn suggest_mismatched_types_on_tail(
|
||||
let expr = expr.peel_drop_temps();
|
||||
self.suggest_missing_semicolon(err, expr, expected, false);
|
||||
let mut pointing_at_return_type = false;
|
||||
if let Some((fn_decl, can_suggest)) = self.get_fn_decl(blk_id) {
|
||||
let fn_id = self.tcx.hir().get_return_block(blk_id).unwrap();
|
||||
if let Some((fn_id, fn_decl, can_suggest)) = self.get_fn_decl(blk_id) {
|
||||
pointing_at_return_type = self.suggest_missing_return_type(
|
||||
err,
|
||||
&fn_decl,
|
||||
|
@ -85,20 +85,28 @@ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
Single {
|
||||
ref source,
|
||||
ref target,
|
||||
ref source_bindings,
|
||||
ref target_bindings,
|
||||
ref type_ns_only,
|
||||
ref nested,
|
||||
ref id,
|
||||
// Ignore the following to avoid an infinite loop while printing.
|
||||
source_bindings: _,
|
||||
target_bindings: _,
|
||||
} => f
|
||||
.debug_struct("Single")
|
||||
.field("source", source)
|
||||
.field("target", target)
|
||||
// Ignore the nested bindings to avoid an infinite loop while printing.
|
||||
.field(
|
||||
"source_bindings",
|
||||
&source_bindings.clone().map(|b| b.into_inner().map(|_| format_args!(".."))),
|
||||
)
|
||||
.field(
|
||||
"target_bindings",
|
||||
&target_bindings.clone().map(|b| b.into_inner().map(|_| format_args!(".."))),
|
||||
)
|
||||
.field("type_ns_only", type_ns_only)
|
||||
.field("nested", nested)
|
||||
.field("id", id)
|
||||
.finish_non_exhaustive(),
|
||||
.finish(),
|
||||
Glob { ref is_prelude, ref max_vis, ref id } => f
|
||||
.debug_struct("Glob")
|
||||
.field("is_prelude", is_prelude)
|
||||
|
@ -1478,8 +1478,9 @@ fn resolve_lifetime(&mut self, lifetime: &'ast Lifetime, use_ctxt: visit::Lifeti
|
||||
} else {
|
||||
LifetimeUseSet::Many
|
||||
}),
|
||||
LifetimeRibKind::Generics { .. } => None,
|
||||
LifetimeRibKind::ConstGeneric | LifetimeRibKind::AnonConst => {
|
||||
LifetimeRibKind::Generics { .. }
|
||||
| LifetimeRibKind::ConstGeneric => None,
|
||||
LifetimeRibKind::AnonConst => {
|
||||
span_bug!(ident.span, "unexpected rib kind: {:?}", rib.kind)
|
||||
}
|
||||
})
|
||||
|
@ -1236,7 +1236,17 @@ pub fn link(_original: &Path, _link: &Path) -> io::Result<()> {
|
||||
}
|
||||
|
||||
pub fn stat(path: &Path) -> io::Result<FileAttr> {
|
||||
metadata(path, ReparsePoint::Follow)
|
||||
match metadata(path, ReparsePoint::Follow) {
|
||||
Err(err) if err.raw_os_error() == Some(c::ERROR_CANT_ACCESS_FILE as i32) => {
|
||||
if let Ok(attrs) = lstat(path) {
|
||||
if !attrs.file_type().is_symlink() {
|
||||
return Ok(attrs);
|
||||
}
|
||||
}
|
||||
Err(err)
|
||||
}
|
||||
result => result,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn lstat(path: &Path) -> io::Result<FileAttr> {
|
||||
|
@ -210,10 +210,13 @@ fn run($sel, $builder: &Builder<'_>) {
|
||||
}
|
||||
};
|
||||
LlvmTools, alias = "llvm-tools", Self::should_build(_config), only_hosts: true, {
|
||||
let tarball = builder
|
||||
.ensure(dist::LlvmTools { target: self.target })
|
||||
.expect("missing llvm-tools");
|
||||
install_sh(builder, "llvm-tools", self.compiler.stage, Some(self.target), &tarball);
|
||||
if let Some(tarball) = builder.ensure(dist::LlvmTools { target: self.target }) {
|
||||
install_sh(builder, "llvm-tools", self.compiler.stage, Some(self.target), &tarball);
|
||||
} else {
|
||||
builder.info(
|
||||
&format!("skipping llvm-tools stage{} ({}): external LLVM", self.compiler.stage, self.target),
|
||||
);
|
||||
}
|
||||
};
|
||||
Rustfmt, alias = "rustfmt", Self::should_build(_config), only_hosts: true, {
|
||||
if let Some(tarball) = builder.ensure(dist::Rustfmt {
|
||||
|
@ -25,4 +25,9 @@ fn d<const C: S>() {}
|
||||
//~^ ERROR missing lifetime specifier
|
||||
//~| ERROR `S<'_>` is forbidden as the type of a const generic parameter
|
||||
|
||||
trait Foo<'a> {}
|
||||
struct Bar<const N: &'a (dyn for<'a> Foo<'a>)>;
|
||||
//~^ ERROR use of non-static lifetime `'a` in const generic
|
||||
//~| ERROR `&dyn for<'a> Foo<'a>` is forbidden as the type of a const generic parameter
|
||||
|
||||
fn main() {}
|
||||
|
@ -9,6 +9,14 @@ help: consider introducing a named lifetime parameter
|
||||
LL | fn d<'a, const C: S<'a>>() {}
|
||||
| +++ ++++
|
||||
|
||||
error[E0771]: use of non-static lifetime `'a` in const generic
|
||||
--> $DIR/unusual-rib-combinations.rs:29:22
|
||||
|
|
||||
LL | struct Bar<const N: &'a (dyn for<'a> Foo<'a>)>;
|
||||
| ^^
|
||||
|
|
||||
= note: for more information, see issue #74052 <https://github.com/rust-lang/rust/issues/74052>
|
||||
|
||||
error[E0214]: parenthesized type parameters may only be used with a `Fn` trait
|
||||
--> $DIR/unusual-rib-combinations.rs:7:16
|
||||
|
|
||||
@ -55,7 +63,16 @@ LL | fn d<const C: S>() {}
|
||||
= note: the only supported types are integers, `bool` and `char`
|
||||
= help: more complex types are supported with `#![feature(adt_const_params)]`
|
||||
|
||||
error: aborting due to 7 previous errors
|
||||
error: `&dyn for<'a> Foo<'a>` is forbidden as the type of a const generic parameter
|
||||
--> $DIR/unusual-rib-combinations.rs:29:21
|
||||
|
|
||||
LL | struct Bar<const N: &'a (dyn for<'a> Foo<'a>)>;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: the only supported types are integers, `bool` and `char`
|
||||
= help: more complex types are supported with `#![feature(adt_const_params)]`
|
||||
|
||||
Some errors have detailed explanations: E0106, E0214, E0308.
|
||||
error: aborting due to 9 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0106, E0214, E0308, E0771.
|
||||
For more information about an error, try `rustc --explain E0106`.
|
||||
|
7
tests/ui/macros/issue-109237.rs
Normal file
7
tests/ui/macros/issue-109237.rs
Normal file
@ -0,0 +1,7 @@
|
||||
macro_rules! statement {
|
||||
() => {;}; //~ ERROR expected expression
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let _ = statement!();
|
||||
}
|
18
tests/ui/macros/issue-109237.stderr
Normal file
18
tests/ui/macros/issue-109237.stderr
Normal file
@ -0,0 +1,18 @@
|
||||
error: expected expression, found `;`
|
||||
--> $DIR/issue-109237.rs:2:12
|
||||
|
|
||||
LL | () => {;};
|
||||
| ^ expected expression
|
||||
...
|
||||
LL | let _ = statement!();
|
||||
| ------------ in this macro invocation
|
||||
|
|
||||
= note: the macro call doesn't expand to an expression, but it can expand to a statement
|
||||
= note: this error originates in the macro `statement` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
help: surround the macro invocation with `{}` to interpret the expansion as a statement
|
||||
|
|
||||
LL | let _ = { statement!(); };
|
||||
| ~~~~~~~~~~~~~~~~~
|
||||
|
||||
error: aborting due to previous error
|
||||
|
10
tests/ui/suggestions/bad-infer-in-trait-impl.rs
Normal file
10
tests/ui/suggestions/bad-infer-in-trait-impl.rs
Normal file
@ -0,0 +1,10 @@
|
||||
trait Foo {
|
||||
fn bar();
|
||||
}
|
||||
|
||||
impl Foo for () {
|
||||
fn bar(s: _) {}
|
||||
//~^ ERROR the placeholder `_` is not allowed within types on item signatures for functions
|
||||
}
|
||||
|
||||
fn main() {}
|
14
tests/ui/suggestions/bad-infer-in-trait-impl.stderr
Normal file
14
tests/ui/suggestions/bad-infer-in-trait-impl.stderr
Normal file
@ -0,0 +1,14 @@
|
||||
error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions
|
||||
--> $DIR/bad-infer-in-trait-impl.rs:6:15
|
||||
|
|
||||
LL | fn bar(s: _) {}
|
||||
| ^ not allowed in type signatures
|
||||
|
|
||||
help: use type parameters instead
|
||||
|
|
||||
LL | fn bar<T>(s: T) {}
|
||||
| +++ ~
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0121`.
|
11
tests/ui/suggestions/suggest-ret-on-async-w-late.rs
Normal file
11
tests/ui/suggestions/suggest-ret-on-async-w-late.rs
Normal file
@ -0,0 +1,11 @@
|
||||
// edition: 2021
|
||||
|
||||
// Make sure we don't ICE when suggesting a return type
|
||||
// for an async fn that has late-bound vars...
|
||||
|
||||
async fn ice(_: &i32) {
|
||||
true
|
||||
//~^ ERROR mismatched types
|
||||
}
|
||||
|
||||
fn main() {}
|
11
tests/ui/suggestions/suggest-ret-on-async-w-late.stderr
Normal file
11
tests/ui/suggestions/suggest-ret-on-async-w-late.stderr
Normal file
@ -0,0 +1,11 @@
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/suggest-ret-on-async-w-late.rs:7:5
|
||||
|
|
||||
LL | async fn ice(_: &i32) {
|
||||
| - help: try adding a return type: `-> bool`
|
||||
LL | true
|
||||
| ^^^^ expected `()`, found `bool`
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0308`.
|
11
tests/ui/traits/non_lifetime_binders/missing-assoc-item.rs
Normal file
11
tests/ui/traits/non_lifetime_binders/missing-assoc-item.rs
Normal file
@ -0,0 +1,11 @@
|
||||
#![feature(non_lifetime_binders)]
|
||||
//~^ WARN the feature `non_lifetime_binders` is incomplete
|
||||
|
||||
fn f()
|
||||
where
|
||||
for<B> B::Item: Send,
|
||||
//~^ ERROR ambiguous associated type
|
||||
{
|
||||
}
|
||||
|
||||
fn main() {}
|
@ -0,0 +1,18 @@
|
||||
warning: the feature `non_lifetime_binders` is incomplete and may not be safe to use and/or cause compiler crashes
|
||||
--> $DIR/missing-assoc-item.rs:1:12
|
||||
|
|
||||
LL | #![feature(non_lifetime_binders)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: see issue #108185 <https://github.com/rust-lang/rust/issues/108185> for more information
|
||||
= note: `#[warn(incomplete_features)]` on by default
|
||||
|
||||
error[E0223]: ambiguous associated type
|
||||
--> $DIR/missing-assoc-item.rs:6:12
|
||||
|
|
||||
LL | for<B> B::Item: Send,
|
||||
| ^^^^^^^ help: use the fully-qualified path: `<B as IntoIterator>::Item`
|
||||
|
||||
error: aborting due to previous error; 1 warning emitted
|
||||
|
||||
For more information about this error, try `rustc --explain E0223`.
|
Loading…
Reference in New Issue
Block a user