Auto merge of #93119 - matthiaskrgr:rollup-ku3cn5j, r=matthiaskrgr
Rollup of 13 pull requests Successful merges: - #89747 (Add MaybeUninit::(slice_)as_bytes(_mut)) - #89764 (Fix variant index / discriminant confusion in uninhabited enum branching) - #91606 (Stabilize `-Z print-link-args` as `--print link-args`) - #91694 (rustdoc: decouple stability and const-stability) - #92183 (Point at correct argument when async fn output type lifetime disagrees with signature) - #92582 (improve `_` constants in item signature handling) - #92680 (intra-doc: Use the impl's assoc item where possible) - #92704 (Change lint message to be stronger for &T -> &mut T transmute) - #92861 (Rustdoc mobile: put out-of-band info on its own line) - #92992 (Help optimize out backtraces when disabled) - #93038 (Fix star handling in block doc comments) - #93108 (⬆️ rust-analyzer) - #93112 (Fix CVE-2022-21658) Failed merges: r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
777bb86bcd
99 changed files with 1916 additions and 805 deletions
|
|
@ -242,6 +242,17 @@ impl Attribute {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn doc_str_and_comment_kind(&self) -> Option<(Symbol, CommentKind)> {
|
||||
match self.kind {
|
||||
AttrKind::DocComment(kind, data) => Some((data, kind)),
|
||||
AttrKind::Normal(ref item, _) if item.path == sym::doc => item
|
||||
.meta_kind()
|
||||
.and_then(|kind| kind.value_str())
|
||||
.map(|data| (data, CommentKind::Line)),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn doc_str(&self) -> Option<Symbol> {
|
||||
match self.kind {
|
||||
AttrKind::DocComment(.., data) => Some(data),
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
use crate::token::CommentKind;
|
||||
use rustc_span::source_map::SourceMap;
|
||||
use rustc_span::{BytePos, CharPos, FileName, Pos, Symbol};
|
||||
|
||||
|
|
@ -25,7 +26,7 @@ pub struct Comment {
|
|||
|
||||
/// Makes a doc string more presentable to users.
|
||||
/// Used by rustdoc and perhaps other tools, but not by rustc.
|
||||
pub fn beautify_doc_string(data: Symbol) -> Symbol {
|
||||
pub fn beautify_doc_string(data: Symbol, kind: CommentKind) -> Symbol {
|
||||
fn get_vertical_trim(lines: &[&str]) -> Option<(usize, usize)> {
|
||||
let mut i = 0;
|
||||
let mut j = lines.len();
|
||||
|
|
@ -42,10 +43,28 @@ pub fn beautify_doc_string(data: Symbol) -> Symbol {
|
|||
if i != 0 || j != lines.len() { Some((i, j)) } else { None }
|
||||
}
|
||||
|
||||
fn get_horizontal_trim(lines: &[&str]) -> Option<usize> {
|
||||
fn get_horizontal_trim(lines: &[&str], kind: CommentKind) -> Option<usize> {
|
||||
let mut i = usize::MAX;
|
||||
let mut first = true;
|
||||
|
||||
// In case we have doc comments like `/**` or `/*!`, we want to remove stars if they are
|
||||
// present. However, we first need to strip the empty lines so they don't get in the middle
|
||||
// when we try to compute the "horizontal trim".
|
||||
let lines = if kind == CommentKind::Block {
|
||||
let mut i = 0;
|
||||
let mut j = lines.len();
|
||||
|
||||
while i < j && lines[i].trim().is_empty() {
|
||||
i += 1;
|
||||
}
|
||||
while j > i && lines[j - 1].trim().is_empty() {
|
||||
j -= 1;
|
||||
}
|
||||
&lines[i..j]
|
||||
} else {
|
||||
lines
|
||||
};
|
||||
|
||||
for line in lines {
|
||||
for (j, c) in line.chars().enumerate() {
|
||||
if j > i || !"* \t".contains(c) {
|
||||
|
|
@ -79,11 +98,13 @@ pub fn beautify_doc_string(data: Symbol) -> Symbol {
|
|||
} else {
|
||||
&mut lines
|
||||
};
|
||||
if let Some(horizontal) = get_horizontal_trim(&lines) {
|
||||
if let Some(horizontal) = get_horizontal_trim(&lines, kind) {
|
||||
changes = true;
|
||||
// remove a "[ \t]*\*" block from each line, if possible
|
||||
for line in lines.iter_mut() {
|
||||
*line = &line[horizontal + 1..];
|
||||
if horizontal + 1 < line.len() {
|
||||
*line = &line[horizontal + 1..];
|
||||
}
|
||||
}
|
||||
}
|
||||
if changes {
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ use rustc_span::create_default_session_globals_then;
|
|||
fn test_block_doc_comment_1() {
|
||||
create_default_session_globals_then(|| {
|
||||
let comment = "\n * Test \n ** Test\n * Test\n";
|
||||
let stripped = beautify_doc_string(Symbol::intern(comment));
|
||||
let stripped = beautify_doc_string(Symbol::intern(comment), CommentKind::Block);
|
||||
assert_eq!(stripped.as_str(), " Test \n* Test\n Test");
|
||||
})
|
||||
}
|
||||
|
|
@ -14,7 +14,7 @@ fn test_block_doc_comment_1() {
|
|||
fn test_block_doc_comment_2() {
|
||||
create_default_session_globals_then(|| {
|
||||
let comment = "\n * Test\n * Test\n";
|
||||
let stripped = beautify_doc_string(Symbol::intern(comment));
|
||||
let stripped = beautify_doc_string(Symbol::intern(comment), CommentKind::Block);
|
||||
assert_eq!(stripped.as_str(), " Test\n Test");
|
||||
})
|
||||
}
|
||||
|
|
@ -23,7 +23,7 @@ fn test_block_doc_comment_2() {
|
|||
fn test_block_doc_comment_3() {
|
||||
create_default_session_globals_then(|| {
|
||||
let comment = "\n let a: *i32;\n *a = 5;\n";
|
||||
let stripped = beautify_doc_string(Symbol::intern(comment));
|
||||
let stripped = beautify_doc_string(Symbol::intern(comment), CommentKind::Block);
|
||||
assert_eq!(stripped.as_str(), " let a: *i32;\n *a = 5;");
|
||||
})
|
||||
}
|
||||
|
|
@ -31,13 +31,13 @@ fn test_block_doc_comment_3() {
|
|||
#[test]
|
||||
fn test_line_doc_comment() {
|
||||
create_default_session_globals_then(|| {
|
||||
let stripped = beautify_doc_string(Symbol::intern(" test"));
|
||||
let stripped = beautify_doc_string(Symbol::intern(" test"), CommentKind::Line);
|
||||
assert_eq!(stripped.as_str(), " test");
|
||||
let stripped = beautify_doc_string(Symbol::intern("! test"));
|
||||
let stripped = beautify_doc_string(Symbol::intern("! test"), CommentKind::Line);
|
||||
assert_eq!(stripped.as_str(), "! test");
|
||||
let stripped = beautify_doc_string(Symbol::intern("test"));
|
||||
let stripped = beautify_doc_string(Symbol::intern("test"), CommentKind::Line);
|
||||
assert_eq!(stripped.as_str(), "test");
|
||||
let stripped = beautify_doc_string(Symbol::intern("!test"));
|
||||
let stripped = beautify_doc_string(Symbol::intern("!test"), CommentKind::Line);
|
||||
assert_eq!(stripped.as_str(), "!test");
|
||||
})
|
||||
}
|
||||
|
|
|
|||
|
|
@ -667,7 +667,7 @@ fn link_natively<'a, B: ArchiveBuilder<'a>>(
|
|||
cmd.env_remove(k);
|
||||
}
|
||||
|
||||
if sess.opts.debugging_opts.print_link_args {
|
||||
if sess.opts.prints.contains(&PrintRequest::LinkArgs) {
|
||||
println!("{:?}", &cmd);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -645,9 +645,9 @@ impl RustcDefaultCalls {
|
|||
temps_dir: &Option<PathBuf>,
|
||||
) -> Compilation {
|
||||
use rustc_session::config::PrintRequest::*;
|
||||
// PrintRequest::NativeStaticLibs is special - printed during linking
|
||||
// NativeStaticLibs and LinkArgs are special - printed during linking
|
||||
// (empty iterator returns true)
|
||||
if sess.opts.prints.iter().all(|&p| p == PrintRequest::NativeStaticLibs) {
|
||||
if sess.opts.prints.iter().all(|&p| p == NativeStaticLibs || p == LinkArgs) {
|
||||
return Compilation::Continue;
|
||||
}
|
||||
|
||||
|
|
@ -738,7 +738,8 @@ impl RustcDefaultCalls {
|
|||
codegen_backend.print(*req, sess);
|
||||
}
|
||||
// Any output here interferes with Cargo's parsing of other printed output
|
||||
PrintRequest::NativeStaticLibs => {}
|
||||
NativeStaticLibs => {}
|
||||
LinkArgs => {}
|
||||
}
|
||||
}
|
||||
Compilation::Stop
|
||||
|
|
|
|||
|
|
@ -2726,6 +2726,10 @@ pub struct FnHeader {
|
|||
}
|
||||
|
||||
impl FnHeader {
|
||||
pub fn is_async(&self) -> bool {
|
||||
matches!(&self.asyncness, IsAsync::Async)
|
||||
}
|
||||
|
||||
pub fn is_const(&self) -> bool {
|
||||
matches!(&self.constness, Constness::Const)
|
||||
}
|
||||
|
|
@ -3169,7 +3173,7 @@ impl<'hir> Node<'hir> {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn fn_decl(&self) -> Option<&FnDecl<'hir>> {
|
||||
pub fn fn_decl(&self) -> Option<&'hir FnDecl<'hir>> {
|
||||
match self {
|
||||
Node::TraitItem(TraitItem { kind: TraitItemKind::Fn(fn_sig, _), .. })
|
||||
| Node::ImplItem(ImplItem { kind: ImplItemKind::Fn(fn_sig, _), .. })
|
||||
|
|
@ -3181,6 +3185,15 @@ impl<'hir> Node<'hir> {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn fn_sig(&self) -> Option<&'hir FnSig<'hir>> {
|
||||
match self {
|
||||
Node::TraitItem(TraitItem { kind: TraitItemKind::Fn(fn_sig, _), .. })
|
||||
| Node::ImplItem(ImplItem { kind: ImplItemKind::Fn(fn_sig, _), .. })
|
||||
| Node::Item(Item { kind: ItemKind::Fn(fn_sig, _, _), .. }) => Some(fn_sig),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn body_id(&self) -> Option<BodyId> {
|
||||
match self {
|
||||
Node::TraitItem(TraitItem {
|
||||
|
|
|
|||
|
|
@ -65,11 +65,11 @@ use rustc_hir::def_id::DefId;
|
|||
use rustc_hir::lang_items::LangItem;
|
||||
use rustc_hir::{Item, ItemKind, Node};
|
||||
use rustc_middle::dep_graph::DepContext;
|
||||
use rustc_middle::ty::error::TypeError;
|
||||
use rustc_middle::ty::{
|
||||
self,
|
||||
error::TypeError,
|
||||
subst::{GenericArgKind, Subst, SubstsRef},
|
||||
Region, Ty, TyCtxt, TypeFoldable,
|
||||
Binder, Region, Ty, TyCtxt, TypeFoldable,
|
||||
};
|
||||
use rustc_span::{sym, BytePos, DesugaringKind, MultiSpan, Pos, Span};
|
||||
use rustc_target::spec::abi;
|
||||
|
|
@ -1765,7 +1765,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
|||
self.note_error_origin(diag, cause, exp_found, terr);
|
||||
}
|
||||
|
||||
pub fn get_impl_future_output_ty(&self, ty: Ty<'tcx>) -> Option<Ty<'tcx>> {
|
||||
pub fn get_impl_future_output_ty(&self, ty: Ty<'tcx>) -> Option<Binder<'tcx, Ty<'tcx>>> {
|
||||
if let ty::Opaque(def_id, substs) = ty.kind() {
|
||||
let future_trait = self.tcx.require_lang_item(LangItem::Future, None);
|
||||
// Future::Output
|
||||
|
|
@ -1775,13 +1775,20 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
|||
|
||||
for (predicate, _) in bounds {
|
||||
let predicate = predicate.subst(self.tcx, substs);
|
||||
if let ty::PredicateKind::Projection(projection_predicate) =
|
||||
predicate.kind().skip_binder()
|
||||
{
|
||||
if projection_predicate.projection_ty.item_def_id == item_def_id {
|
||||
// We don't account for multiple `Future::Output = Ty` contraints.
|
||||
return projection_predicate.term.ty();
|
||||
}
|
||||
let output = predicate
|
||||
.kind()
|
||||
.map_bound(|kind| match kind {
|
||||
ty::PredicateKind::Projection(projection_predicate)
|
||||
if projection_predicate.projection_ty.item_def_id == item_def_id =>
|
||||
{
|
||||
projection_predicate.term.ty()
|
||||
}
|
||||
_ => None,
|
||||
})
|
||||
.transpose();
|
||||
if output.is_some() {
|
||||
// We don't account for multiple `Future::Output = Ty` contraints.
|
||||
return output;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1823,8 +1830,8 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
|||
}
|
||||
|
||||
match (
|
||||
self.get_impl_future_output_ty(exp_found.expected),
|
||||
self.get_impl_future_output_ty(exp_found.found),
|
||||
self.get_impl_future_output_ty(exp_found.expected).map(Binder::skip_binder),
|
||||
self.get_impl_future_output_ty(exp_found.found).map(Binder::skip_binder),
|
||||
) {
|
||||
(Some(exp), Some(found)) if same_type_modulo_infer(exp, found) => match cause.code() {
|
||||
ObligationCauseCode::IfExpression(box IfExpressionCause { then, .. }) => {
|
||||
|
|
|
|||
|
|
@ -106,90 +106,47 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
|
|||
None => String::new(),
|
||||
};
|
||||
|
||||
let (span_1, span_2, main_label, span_label, future_return_type) =
|
||||
match (sup_is_ret_type, sub_is_ret_type) {
|
||||
(None, None) => {
|
||||
let (main_label_1, span_label_1) = if ty_sup.hir_id == ty_sub.hir_id {
|
||||
(
|
||||
"this type is declared with multiple lifetimes...".to_owned(),
|
||||
"...but data with one lifetime flows into the other here".to_owned(),
|
||||
)
|
||||
} else {
|
||||
(
|
||||
"these two types are declared with different lifetimes...".to_owned(),
|
||||
format!("...but data{} flows{} here", span_label_var1, span_label_var2),
|
||||
)
|
||||
};
|
||||
(ty_sup.span, ty_sub.span, main_label_1, span_label_1, None)
|
||||
}
|
||||
|
||||
(Some(ret_span), _) => {
|
||||
let sup_future = self.future_return_type(scope_def_id_sup);
|
||||
let (return_type, action) = if sup_future.is_some() {
|
||||
("returned future", "held across an await point")
|
||||
} else {
|
||||
("return type", "returned")
|
||||
};
|
||||
|
||||
(
|
||||
ty_sub.span,
|
||||
ret_span,
|
||||
format!(
|
||||
"this parameter and the {} are declared with different lifetimes...",
|
||||
return_type
|
||||
),
|
||||
format!("...but data{} is {} here", span_label_var1, action),
|
||||
sup_future,
|
||||
)
|
||||
}
|
||||
(_, Some(ret_span)) => {
|
||||
let sub_future = self.future_return_type(scope_def_id_sub);
|
||||
let (return_type, action) = if sub_future.is_some() {
|
||||
("returned future", "held across an await point")
|
||||
} else {
|
||||
("return type", "returned")
|
||||
};
|
||||
|
||||
(
|
||||
ty_sup.span,
|
||||
ret_span,
|
||||
format!(
|
||||
"this parameter and the {} are declared with different lifetimes...",
|
||||
return_type
|
||||
),
|
||||
format!("...but data{} is {} here", span_label_var1, action),
|
||||
sub_future,
|
||||
)
|
||||
}
|
||||
};
|
||||
debug!(
|
||||
"try_report_anon_anon_conflict: sub_is_ret_type={:?} sup_is_ret_type={:?}",
|
||||
sub_is_ret_type, sup_is_ret_type
|
||||
);
|
||||
|
||||
let mut err = struct_span_err!(self.tcx().sess, span, E0623, "lifetime mismatch");
|
||||
|
||||
err.span_label(span_1, main_label);
|
||||
err.span_label(span_2, String::new());
|
||||
err.span_label(span, span_label);
|
||||
match (sup_is_ret_type, sub_is_ret_type) {
|
||||
(ret_capture @ Some(ret_span), _) | (_, ret_capture @ Some(ret_span)) => {
|
||||
let param_span =
|
||||
if sup_is_ret_type == ret_capture { ty_sub.span } else { ty_sup.span };
|
||||
|
||||
err.span_label(
|
||||
param_span,
|
||||
"this parameter and the return type are declared with different lifetimes...",
|
||||
);
|
||||
err.span_label(ret_span, "");
|
||||
err.span_label(span, format!("...but data{} is returned here", span_label_var1));
|
||||
}
|
||||
|
||||
(None, None) => {
|
||||
if ty_sup.hir_id == ty_sub.hir_id {
|
||||
err.span_label(ty_sup.span, "this type is declared with multiple lifetimes...");
|
||||
err.span_label(ty_sub.span, "");
|
||||
err.span_label(span, "...but data with one lifetime flows into the other here");
|
||||
} else {
|
||||
err.span_label(
|
||||
ty_sup.span,
|
||||
"these two types are declared with different lifetimes...",
|
||||
);
|
||||
err.span_label(ty_sub.span, "");
|
||||
err.span_label(
|
||||
span,
|
||||
format!("...but data{} flows{} here", span_label_var1, span_label_var2),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
self.suggest_adding_lifetime_params(sub, ty_sup, ty_sub, &mut err);
|
||||
|
||||
if let Some(t) = future_return_type {
|
||||
let snip = self
|
||||
.tcx()
|
||||
.sess
|
||||
.source_map()
|
||||
.span_to_snippet(t.span)
|
||||
.ok()
|
||||
.and_then(|s| match (&t.kind, s.as_str()) {
|
||||
(rustc_hir::TyKind::Tup(&[]), "") => Some("()".to_string()),
|
||||
(_, "") => None,
|
||||
_ => Some(s),
|
||||
})
|
||||
.unwrap_or_else(|| "{unnamed_type}".to_string());
|
||||
|
||||
err.span_label(
|
||||
t.span,
|
||||
&format!("this `async fn` implicitly returns an `impl Future<Output = {}>`", snip),
|
||||
);
|
||||
}
|
||||
err.emit();
|
||||
Some(ErrorReported)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
use rustc_hir as hir;
|
||||
use rustc_hir::intravisit::{self, Visitor};
|
||||
use rustc_hir::Node;
|
||||
use rustc_middle::hir::map::Map;
|
||||
use rustc_middle::hir::nested_filter;
|
||||
use rustc_middle::middle::resolve_lifetime as rl;
|
||||
|
|
@ -25,25 +24,19 @@ pub(crate) fn find_anon_type<'tcx>(
|
|||
tcx: TyCtxt<'tcx>,
|
||||
region: Region<'tcx>,
|
||||
br: &ty::BoundRegionKind,
|
||||
) -> Option<(&'tcx hir::Ty<'tcx>, &'tcx hir::FnDecl<'tcx>)> {
|
||||
) -> Option<(&'tcx hir::Ty<'tcx>, &'tcx hir::FnSig<'tcx>)> {
|
||||
if let Some(anon_reg) = tcx.is_suitable_region(region) {
|
||||
let hir_id = tcx.hir().local_def_id_to_hir_id(anon_reg.def_id);
|
||||
let fndecl = match tcx.hir().get(hir_id) {
|
||||
Node::Item(&hir::Item { kind: hir::ItemKind::Fn(ref m, ..), .. })
|
||||
| Node::TraitItem(&hir::TraitItem {
|
||||
kind: hir::TraitItemKind::Fn(ref m, ..), ..
|
||||
})
|
||||
| Node::ImplItem(&hir::ImplItem { kind: hir::ImplItemKind::Fn(ref m, ..), .. }) => {
|
||||
&m.decl
|
||||
}
|
||||
_ => return None,
|
||||
let Some(fn_sig) = tcx.hir().get(hir_id).fn_sig() else {
|
||||
return None
|
||||
};
|
||||
|
||||
fndecl
|
||||
fn_sig
|
||||
.decl
|
||||
.inputs
|
||||
.iter()
|
||||
.find_map(|arg| find_component_for_bound_region(tcx, arg, br))
|
||||
.map(|ty| (ty, &**fndecl))
|
||||
.map(|ty| (ty, fn_sig))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
use crate::infer::error_reporting::nice_region_error::NiceRegionError;
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::def_id::LocalDefId;
|
||||
use rustc_middle::ty::{self, DefIdTree, Region, Ty};
|
||||
use rustc_middle::ty::{self, Binder, DefIdTree, Region, Ty, TypeFoldable};
|
||||
use rustc_span::Span;
|
||||
|
||||
/// Information about the anonymous region we are searching for.
|
||||
|
|
@ -94,81 +94,42 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
|
|||
})
|
||||
}
|
||||
|
||||
pub(super) fn future_return_type(
|
||||
&self,
|
||||
local_def_id: LocalDefId,
|
||||
) -> Option<&rustc_hir::Ty<'_>> {
|
||||
if let Some(hir::IsAsync::Async) = self.asyncness(local_def_id) {
|
||||
if let rustc_middle::ty::Opaque(def_id, _) =
|
||||
self.tcx().type_of(local_def_id).fn_sig(self.tcx()).output().skip_binder().kind()
|
||||
{
|
||||
match self.tcx().hir().get_if_local(*def_id) {
|
||||
Some(hir::Node::Item(hir::Item {
|
||||
kind:
|
||||
hir::ItemKind::OpaqueTy(hir::OpaqueTy {
|
||||
bounds,
|
||||
origin: hir::OpaqueTyOrigin::AsyncFn(..),
|
||||
..
|
||||
}),
|
||||
..
|
||||
})) => {
|
||||
for b in bounds.iter() {
|
||||
if let hir::GenericBound::LangItemTrait(
|
||||
hir::LangItem::Future,
|
||||
_span,
|
||||
_hir_id,
|
||||
generic_args,
|
||||
) = b
|
||||
{
|
||||
for type_binding in generic_args.bindings.iter() {
|
||||
if type_binding.ident.name == rustc_span::sym::Output {
|
||||
if let hir::TypeBindingKind::Equality {
|
||||
term: hir::Term::Ty(ty),
|
||||
} = type_binding.kind
|
||||
{
|
||||
return Some(ty);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
pub(super) fn asyncness(&self, local_def_id: LocalDefId) -> Option<hir::IsAsync> {
|
||||
// similar to the asyncness fn in rustc_ty_utils::ty
|
||||
let hir_id = self.tcx().hir().local_def_id_to_hir_id(local_def_id);
|
||||
let node = self.tcx().hir().get(hir_id);
|
||||
let fn_kind = node.fn_kind()?;
|
||||
Some(fn_kind.asyncness())
|
||||
}
|
||||
|
||||
// Here, we check for the case where the anonymous region
|
||||
// is in the return type.
|
||||
// is in the return type as written by the user.
|
||||
// FIXME(#42703) - Need to handle certain cases here.
|
||||
pub(super) fn is_return_type_anon(
|
||||
&self,
|
||||
scope_def_id: LocalDefId,
|
||||
br: ty::BoundRegionKind,
|
||||
decl: &hir::FnDecl<'_>,
|
||||
hir_sig: &hir::FnSig<'_>,
|
||||
) -> Option<Span> {
|
||||
let ret_ty = self.tcx().type_of(scope_def_id);
|
||||
if let ty::FnDef(_, _) = ret_ty.kind() {
|
||||
let sig = ret_ty.fn_sig(self.tcx());
|
||||
let late_bound_regions =
|
||||
self.tcx().collect_referenced_late_bound_regions(&sig.output());
|
||||
if late_bound_regions.iter().any(|r| *r == br) {
|
||||
return Some(decl.output.span());
|
||||
}
|
||||
let fn_ty = self.tcx().type_of(scope_def_id);
|
||||
if let ty::FnDef(_, _) = fn_ty.kind() {
|
||||
let ret_ty = fn_ty.fn_sig(self.tcx()).output();
|
||||
let span = hir_sig.decl.output.span();
|
||||
let future_output = if hir_sig.header.is_async() {
|
||||
ret_ty.map_bound(|ty| self.infcx.get_impl_future_output_ty(ty)).transpose()
|
||||
} else {
|
||||
None
|
||||
};
|
||||
return match future_output {
|
||||
Some(output) if self.includes_region(output, br) => Some(span),
|
||||
None if self.includes_region(ret_ty, br) => Some(span),
|
||||
_ => None,
|
||||
};
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
fn includes_region(
|
||||
&self,
|
||||
ty: Binder<'tcx, impl TypeFoldable<'tcx>>,
|
||||
region: ty::BoundRegionKind,
|
||||
) -> bool {
|
||||
let late_bound_regions = self.tcx().collect_referenced_late_bound_regions(&ty);
|
||||
late_bound_regions.iter().any(|r| *r == region)
|
||||
}
|
||||
|
||||
// Here we check for the case where anonymous region
|
||||
// corresponds to self and if yes, we display E0312.
|
||||
// FIXME(#42700) - Need to format self properly to
|
||||
|
|
|
|||
|
|
@ -678,7 +678,6 @@ fn test_debugging_options_tracking_hash() {
|
|||
// `pre_link_arg` is omitted because it just forwards to `pre_link_args`.
|
||||
untracked!(pre_link_args, vec![String::from("abc"), String::from("def")]);
|
||||
untracked!(profile_closures, true);
|
||||
untracked!(print_link_args, true);
|
||||
untracked!(print_llvm_passes, true);
|
||||
untracked!(print_mono_items, Some(String::from("abc")));
|
||||
untracked!(print_type_sizes, true);
|
||||
|
|
|
|||
|
|
@ -1247,7 +1247,7 @@ declare_lint! {
|
|||
/// [`UnsafeCell`]: https://doc.rust-lang.org/std/cell/struct.UnsafeCell.html
|
||||
MUTABLE_TRANSMUTES,
|
||||
Deny,
|
||||
"mutating transmuted &mut T from &T may cause undefined behavior"
|
||||
"transmuting &T to &mut T is undefined behavior, even if the reference is unused"
|
||||
}
|
||||
|
||||
declare_lint_pass!(MutableTransmutes => [MUTABLE_TRANSMUTES]);
|
||||
|
|
@ -1259,8 +1259,8 @@ impl<'tcx> LateLintPass<'tcx> for MutableTransmutes {
|
|||
get_transmute_from_to(cx, expr).map(|(ty1, ty2)| (ty1.kind(), ty2.kind()))
|
||||
{
|
||||
if to_mt == hir::Mutability::Mut && from_mt == hir::Mutability::Not {
|
||||
let msg = "mutating transmuted &mut T from &T may cause undefined behavior, \
|
||||
consider instead using an UnsafeCell";
|
||||
let msg = "transmuting &T to &mut T is undefined behavior, \
|
||||
even if the reference is unused, consider instead using an UnsafeCell";
|
||||
cx.struct_span_lint(MUTABLE_TRANSMUTES, expr.span, |lint| lint.build(msg).emit());
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1210,11 +1210,25 @@ impl<'tcx> TyCtxt<'tcx> {
|
|||
self.mk_ty(Error(DelaySpanBugEmitted(())))
|
||||
}
|
||||
|
||||
/// Like `err` but for constants.
|
||||
/// Like [TyCtxt::ty_error] but for constants.
|
||||
#[track_caller]
|
||||
pub fn const_error(self, ty: Ty<'tcx>) -> &'tcx Const<'tcx> {
|
||||
self.sess
|
||||
.delay_span_bug(DUMMY_SP, "ty::ConstKind::Error constructed but no error reported.");
|
||||
self.const_error_with_message(
|
||||
ty,
|
||||
DUMMY_SP,
|
||||
"ty::ConstKind::Error constructed but no error reported",
|
||||
)
|
||||
}
|
||||
|
||||
/// Like [TyCtxt::ty_error_with_message] but for constants.
|
||||
#[track_caller]
|
||||
pub fn const_error_with_message<S: Into<MultiSpan>>(
|
||||
self,
|
||||
ty: Ty<'tcx>,
|
||||
span: S,
|
||||
msg: &str,
|
||||
) -> &'tcx Const<'tcx> {
|
||||
self.sess.delay_span_bug(span, msg);
|
||||
self.mk_const(ty::Const { val: ty::ConstKind::Error(DelaySpanBugEmitted(())), ty })
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -3,8 +3,7 @@
|
|||
use crate::MirPass;
|
||||
use rustc_data_structures::stable_set::FxHashSet;
|
||||
use rustc_middle::mir::{
|
||||
BasicBlock, BasicBlockData, Body, Local, Operand, Rvalue, StatementKind, SwitchTargets,
|
||||
TerminatorKind,
|
||||
BasicBlockData, Body, Local, Operand, Rvalue, StatementKind, SwitchTargets, TerminatorKind,
|
||||
};
|
||||
use rustc_middle::ty::layout::TyAndLayout;
|
||||
use rustc_middle::ty::{Ty, TyCtxt};
|
||||
|
|
@ -56,7 +55,10 @@ fn variant_discriminants<'tcx>(
|
|||
match &layout.variants {
|
||||
Variants::Single { index } => {
|
||||
let mut res = FxHashSet::default();
|
||||
res.insert(index.as_u32() as u128);
|
||||
res.insert(
|
||||
ty.discriminant_for_variant(tcx, *index)
|
||||
.map_or(index.as_u32() as u128, |discr| discr.val),
|
||||
);
|
||||
res
|
||||
}
|
||||
Variants::Multiple { variants, .. } => variants
|
||||
|
|
@ -75,16 +77,9 @@ impl<'tcx> MirPass<'tcx> for UninhabitedEnumBranching {
|
|||
}
|
||||
|
||||
fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
|
||||
if body.source.promoted.is_some() {
|
||||
return;
|
||||
}
|
||||
|
||||
trace!("UninhabitedEnumBranching starting for {:?}", body.source);
|
||||
|
||||
let basic_block_count = body.basic_blocks().len();
|
||||
|
||||
for bb in 0..basic_block_count {
|
||||
let bb = BasicBlock::from_usize(bb);
|
||||
for bb in body.basic_blocks().indices() {
|
||||
trace!("processing block {:?}", bb);
|
||||
|
||||
let Some(discriminant_ty) = get_switched_on_type(&body.basic_blocks()[bb], tcx, body) else {
|
||||
|
|
|
|||
|
|
@ -1148,19 +1148,11 @@ impl<'tcx> Visitor<'tcx> for TypePrivacyVisitor<'tcx> {
|
|||
if self.visit(ty).is_break() {
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
// We don't do anything for const infers here.
|
||||
}
|
||||
} else {
|
||||
let local_id = self.tcx.hir().local_def_id(inf.hir_id);
|
||||
if let Some(did) = self.tcx.opt_const_param_of(local_id) {
|
||||
if self.visit_def_id(did, "inferred", &"").is_break() {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME see above note for same issue.
|
||||
if self.visit(rustc_typeck::hir_ty_to_ty(self.tcx, &inf.to_ty())).is_break() {
|
||||
return;
|
||||
}
|
||||
bug!("visit_infer without typeck_results");
|
||||
}
|
||||
intravisit::walk_inf(self, inf);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -821,9 +821,9 @@ impl<'tcx> SaveContext<'tcx> {
|
|||
let mut result = String::new();
|
||||
|
||||
for attr in attrs {
|
||||
if let Some(val) = attr.doc_str() {
|
||||
if let Some((val, kind)) = attr.doc_str_and_comment_kind() {
|
||||
// FIXME: Should save-analysis beautify doc strings itself or leave it to users?
|
||||
result.push_str(beautify_doc_string(val).as_str());
|
||||
result.push_str(beautify_doc_string(val, kind).as_str());
|
||||
result.push('\n');
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -565,6 +565,7 @@ pub enum PrintRequest {
|
|||
TargetSpec,
|
||||
NativeStaticLibs,
|
||||
StackProtectorStrategies,
|
||||
LinkArgs,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
|
|
@ -1187,7 +1188,8 @@ pub fn rustc_short_optgroups() -> Vec<RustcOptGroup> {
|
|||
"Compiler information to print on stdout",
|
||||
"[crate-name|file-names|sysroot|target-libdir|cfg|target-list|\
|
||||
target-cpus|target-features|relocation-models|code-models|\
|
||||
tls-models|target-spec-json|native-static-libs|stack-protector-strategies]",
|
||||
tls-models|target-spec-json|native-static-libs|stack-protector-strategies\
|
||||
link-args]",
|
||||
),
|
||||
opt::flagmulti_s("g", "", "Equivalent to -C debuginfo=2"),
|
||||
opt::flagmulti_s("O", "", "Equivalent to -C opt-level=2"),
|
||||
|
|
@ -1619,6 +1621,7 @@ fn collect_print_requests(
|
|||
);
|
||||
}
|
||||
}
|
||||
"link-args" => PrintRequest::LinkArgs,
|
||||
req => early_error(error_format, &format!("unknown print request `{}`", req)),
|
||||
}));
|
||||
|
||||
|
|
|
|||
|
|
@ -1339,8 +1339,6 @@ options! {
|
|||
See #77382 and #74551."),
|
||||
print_fuel: Option<String> = (None, parse_opt_string, [TRACKED],
|
||||
"make rustc print the total optimization fuel used by a crate"),
|
||||
print_link_args: bool = (false, parse_bool, [UNTRACKED],
|
||||
"print the arguments passed to the linker (default: no)"),
|
||||
print_llvm_passes: bool = (false, parse_bool, [UNTRACKED],
|
||||
"print the LLVM optimization passes being run (default: no)"),
|
||||
print_mono_items: Option<String> = (None, parse_opt_string, [UNTRACKED],
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ mod errors;
|
|||
mod generics;
|
||||
|
||||
use crate::bounds::Bounds;
|
||||
use crate::collect::PlaceholderHirTyCollector;
|
||||
use crate::collect::HirPlaceholderCollector;
|
||||
use crate::errors::{
|
||||
AmbiguousLifetimeBound, MultipleRelaxedDefaultBounds, TraitObjectDeclaredWithNoTraits,
|
||||
TypeofReservedKeywordUsed, ValueOfAssociatedStructAlreadySpecified,
|
||||
|
|
@ -2504,7 +2504,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
|||
debug!(?bound_vars);
|
||||
|
||||
// We proactively collect all the inferred type params to emit a single error per fn def.
|
||||
let mut visitor = PlaceholderHirTyCollector::default();
|
||||
let mut visitor = HirPlaceholderCollector::default();
|
||||
for ty in decl.inputs {
|
||||
visitor.visit_ty(ty);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1909,7 +1909,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
_ => return,
|
||||
};
|
||||
let mut add_label = true;
|
||||
if let ty::Adt(def, _) = output_ty.kind() {
|
||||
if let ty::Adt(def, _) = output_ty.skip_binder().kind() {
|
||||
// no field access on enum type
|
||||
if !def.is_enum() {
|
||||
if def
|
||||
|
|
|
|||
|
|
@ -609,14 +609,18 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
let ty = self.tcx.erase_late_bound_regions(Binder::bind_with_vars(ty, bound_vars));
|
||||
let ty = self.normalize_associated_types_in(expr.span, ty);
|
||||
let ty = match self.tcx.asyncness(fn_id.owner) {
|
||||
hir::IsAsync::Async => self.tcx.infer_ctxt().enter(|infcx| {
|
||||
infcx.get_impl_future_output_ty(ty).unwrap_or_else(|| {
|
||||
span_bug!(
|
||||
fn_decl.output.span(),
|
||||
"failed to get output type of async function"
|
||||
)
|
||||
hir::IsAsync::Async => self
|
||||
.tcx
|
||||
.infer_ctxt()
|
||||
.enter(|infcx| {
|
||||
infcx.get_impl_future_output_ty(ty).unwrap_or_else(|| {
|
||||
span_bug!(
|
||||
fn_decl.output.span(),
|
||||
"failed to get output type of async function"
|
||||
)
|
||||
})
|
||||
})
|
||||
}),
|
||||
.skip_binder(),
|
||||
hir::IsAsync::NotAsync => ty,
|
||||
};
|
||||
if self.can_coerce(found, ty) {
|
||||
|
|
|
|||
|
|
@ -1274,7 +1274,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
span: Span,
|
||||
) {
|
||||
let output_ty = match self.infcx.get_impl_future_output_ty(ty) {
|
||||
Some(output_ty) => self.resolve_vars_if_possible(output_ty),
|
||||
Some(output_ty) => self.resolve_vars_if_possible(output_ty).skip_binder(),
|
||||
_ => return,
|
||||
};
|
||||
let method_exists = self.method_exists(item_name, output_ty, call.hir_id, true);
|
||||
|
|
|
|||
|
|
@ -112,9 +112,9 @@ pub struct ItemCtxt<'tcx> {
|
|||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#[derive(Default)]
|
||||
crate struct PlaceholderHirTyCollector(crate Vec<Span>);
|
||||
crate struct HirPlaceholderCollector(crate Vec<Span>);
|
||||
|
||||
impl<'v> Visitor<'v> for PlaceholderHirTyCollector {
|
||||
impl<'v> Visitor<'v> for HirPlaceholderCollector {
|
||||
fn visit_ty(&mut self, t: &'v hir::Ty<'v>) {
|
||||
if let hir::TyKind::Infer = t.kind {
|
||||
self.0.push(t.span);
|
||||
|
|
@ -131,6 +131,12 @@ impl<'v> Visitor<'v> for PlaceholderHirTyCollector {
|
|||
_ => {}
|
||||
}
|
||||
}
|
||||
fn visit_array_length(&mut self, length: &'v hir::ArrayLen) {
|
||||
if let &hir::ArrayLen::Infer(_, span) = length {
|
||||
self.0.push(span);
|
||||
}
|
||||
intravisit::walk_array_len(self, length)
|
||||
}
|
||||
}
|
||||
|
||||
struct CollectItemTypesVisitor<'tcx> {
|
||||
|
|
@ -175,7 +181,7 @@ crate fn placeholder_type_error<'tcx>(
|
|||
sugg.push((span, format!(", {}", type_name)));
|
||||
}
|
||||
|
||||
let mut err = bad_placeholder(tcx, "type", placeholder_types, kind);
|
||||
let mut err = bad_placeholder(tcx, placeholder_types, kind);
|
||||
|
||||
// Suggest, but only if it is not a function in const or static
|
||||
if suggest {
|
||||
|
|
@ -233,7 +239,7 @@ fn reject_placeholder_type_signatures_in_item<'tcx>(
|
|||
_ => return,
|
||||
};
|
||||
|
||||
let mut visitor = PlaceholderHirTyCollector::default();
|
||||
let mut visitor = HirPlaceholderCollector::default();
|
||||
visitor.visit_item(item);
|
||||
|
||||
placeholder_type_error(
|
||||
|
|
@ -311,7 +317,6 @@ impl<'tcx> Visitor<'tcx> for CollectItemTypesVisitor<'tcx> {
|
|||
|
||||
fn bad_placeholder<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
placeholder_kind: &'static str,
|
||||
mut spans: Vec<Span>,
|
||||
kind: &'static str,
|
||||
) -> rustc_errors::DiagnosticBuilder<'tcx> {
|
||||
|
|
@ -322,8 +327,7 @@ fn bad_placeholder<'tcx>(
|
|||
tcx.sess,
|
||||
spans.clone(),
|
||||
E0121,
|
||||
"the {} placeholder `_` is not allowed within types on item signatures for {}",
|
||||
placeholder_kind,
|
||||
"the placeholder `_` is not allowed within types on item signatures for {}",
|
||||
kind
|
||||
);
|
||||
for span in spans {
|
||||
|
|
@ -381,7 +385,7 @@ impl<'tcx> AstConv<'tcx> for ItemCtxt<'tcx> {
|
|||
}
|
||||
|
||||
fn ty_infer(&self, _: Option<&ty::GenericParamDef>, span: Span) -> Ty<'tcx> {
|
||||
self.tcx().ty_error_with_message(span, "bad_placeholder_type")
|
||||
self.tcx().ty_error_with_message(span, "bad placeholder type")
|
||||
}
|
||||
|
||||
fn ct_infer(
|
||||
|
|
@ -390,13 +394,11 @@ impl<'tcx> AstConv<'tcx> for ItemCtxt<'tcx> {
|
|||
_: Option<&ty::GenericParamDef>,
|
||||
span: Span,
|
||||
) -> &'tcx Const<'tcx> {
|
||||
bad_placeholder(self.tcx(), "const", vec![span], "generic").emit();
|
||||
// Typeck doesn't expect erased regions to be returned from `type_of`.
|
||||
let ty = self.tcx.fold_regions(ty, &mut false, |r, _| match r {
|
||||
ty::ReErased => self.tcx.lifetimes.re_static,
|
||||
_ => r,
|
||||
});
|
||||
self.tcx().const_error(ty)
|
||||
self.tcx().const_error_with_message(ty, span, "bad placeholder constant")
|
||||
}
|
||||
|
||||
fn projected_ty_from_poly_trait_ref(
|
||||
|
|
@ -743,7 +745,7 @@ fn convert_item(tcx: TyCtxt<'_>, item_id: hir::ItemId) {
|
|||
match item.kind {
|
||||
hir::ForeignItemKind::Fn(..) => tcx.ensure().fn_sig(item.def_id),
|
||||
hir::ForeignItemKind::Static(..) => {
|
||||
let mut visitor = PlaceholderHirTyCollector::default();
|
||||
let mut visitor = HirPlaceholderCollector::default();
|
||||
visitor.visit_foreign_item(item);
|
||||
placeholder_type_error(
|
||||
tcx,
|
||||
|
|
@ -826,7 +828,7 @@ fn convert_item(tcx: TyCtxt<'_>, item_id: hir::ItemId) {
|
|||
hir::ItemKind::Const(ty, ..) | hir::ItemKind::Static(ty, ..) => {
|
||||
// (#75889): Account for `const C: dyn Fn() -> _ = "";`
|
||||
if let hir::TyKind::TraitObject(..) = ty.kind {
|
||||
let mut visitor = PlaceholderHirTyCollector::default();
|
||||
let mut visitor = HirPlaceholderCollector::default();
|
||||
visitor.visit_item(it);
|
||||
placeholder_type_error(
|
||||
tcx,
|
||||
|
|
@ -862,7 +864,7 @@ fn convert_trait_item(tcx: TyCtxt<'_>, trait_item_id: hir::TraitItemId) {
|
|||
hir::TraitItemKind::Const(..) => {
|
||||
tcx.ensure().type_of(trait_item_id.def_id);
|
||||
// Account for `const C: _;`.
|
||||
let mut visitor = PlaceholderHirTyCollector::default();
|
||||
let mut visitor = HirPlaceholderCollector::default();
|
||||
visitor.visit_trait_item(trait_item);
|
||||
placeholder_type_error(tcx, None, &[], visitor.0, false, None, "constant");
|
||||
}
|
||||
|
|
@ -871,7 +873,7 @@ fn convert_trait_item(tcx: TyCtxt<'_>, trait_item_id: hir::TraitItemId) {
|
|||
tcx.ensure().item_bounds(trait_item_id.def_id);
|
||||
tcx.ensure().type_of(trait_item_id.def_id);
|
||||
// Account for `type T = _;`.
|
||||
let mut visitor = PlaceholderHirTyCollector::default();
|
||||
let mut visitor = HirPlaceholderCollector::default();
|
||||
visitor.visit_trait_item(trait_item);
|
||||
placeholder_type_error(tcx, None, &[], visitor.0, false, None, "associated type");
|
||||
}
|
||||
|
|
@ -880,7 +882,7 @@ fn convert_trait_item(tcx: TyCtxt<'_>, trait_item_id: hir::TraitItemId) {
|
|||
tcx.ensure().item_bounds(trait_item_id.def_id);
|
||||
// #74612: Visit and try to find bad placeholders
|
||||
// even if there is no concrete type.
|
||||
let mut visitor = PlaceholderHirTyCollector::default();
|
||||
let mut visitor = HirPlaceholderCollector::default();
|
||||
visitor.visit_trait_item(trait_item);
|
||||
|
||||
placeholder_type_error(tcx, None, &[], visitor.0, false, None, "associated type");
|
||||
|
|
@ -902,7 +904,7 @@ fn convert_impl_item(tcx: TyCtxt<'_>, impl_item_id: hir::ImplItemId) {
|
|||
}
|
||||
hir::ImplItemKind::TyAlias(_) => {
|
||||
// Account for `type T = _;`
|
||||
let mut visitor = PlaceholderHirTyCollector::default();
|
||||
let mut visitor = HirPlaceholderCollector::default();
|
||||
visitor.visit_impl_item(impl_item);
|
||||
|
||||
placeholder_type_error(tcx, None, &[], visitor.0, false, None, "associated type");
|
||||
|
|
@ -1822,10 +1824,14 @@ fn are_suggestable_generic_args(generic_args: &[hir::GenericArg<'_>]) -> bool {
|
|||
/// Whether `ty` is a type with `_` placeholders that can be inferred. Used in diagnostics only to
|
||||
/// use inference to provide suggestions for the appropriate type if possible.
|
||||
fn is_suggestable_infer_ty(ty: &hir::Ty<'_>) -> bool {
|
||||
debug!(?ty);
|
||||
use hir::TyKind::*;
|
||||
match &ty.kind {
|
||||
Infer => true,
|
||||
Slice(ty) | Array(ty, _) => is_suggestable_infer_ty(ty),
|
||||
Slice(ty) => is_suggestable_infer_ty(ty),
|
||||
Array(ty, length) => {
|
||||
is_suggestable_infer_ty(ty) || matches!(length, hir::ArrayLen::Infer(_, _))
|
||||
}
|
||||
Tup(tys) => tys.iter().any(is_suggestable_infer_ty),
|
||||
Ptr(mut_ty) | Rptr(_, mut_ty) => is_suggestable_infer_ty(mut_ty.ty),
|
||||
OpaqueDef(_, generic_args) => are_suggestable_generic_args(generic_args),
|
||||
|
|
@ -1877,9 +1883,9 @@ fn fn_sig(tcx: TyCtxt<'_>, def_id: DefId) -> ty::PolyFnSig<'_> {
|
|||
});
|
||||
let fn_sig = ty::Binder::dummy(fn_sig);
|
||||
|
||||
let mut visitor = PlaceholderHirTyCollector::default();
|
||||
let mut visitor = HirPlaceholderCollector::default();
|
||||
visitor.visit_ty(ty);
|
||||
let mut diag = bad_placeholder(tcx, "type", visitor.0, "return type");
|
||||
let mut diag = bad_placeholder(tcx, visitor.0, "return type");
|
||||
let ret_ty = fn_sig.skip_binder().output();
|
||||
if !ret_ty.references_error() {
|
||||
if !ret_ty.is_closure() {
|
||||
|
|
|
|||
|
|
@ -20,9 +20,6 @@ use super::{bad_placeholder, is_suggestable_infer_ty};
|
|||
/// This should be called using the query `tcx.opt_const_param_of`.
|
||||
#[instrument(level = "debug", skip(tcx))]
|
||||
pub(super) fn opt_const_param_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<DefId> {
|
||||
// FIXME(generic_arg_infer): allow for returning DefIds of inference of
|
||||
// GenericArg::Infer below. This may require a change where GenericArg::Infer has some flag
|
||||
// for const or type.
|
||||
use hir::*;
|
||||
let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
|
||||
|
||||
|
|
@ -753,7 +750,7 @@ fn infer_placeholder_type<'a>(
|
|||
err.emit();
|
||||
}
|
||||
None => {
|
||||
let mut diag = bad_placeholder(tcx, "type", vec![span], kind);
|
||||
let mut diag = bad_placeholder(tcx, vec![span], kind);
|
||||
|
||||
if !ty.references_error() {
|
||||
let mut mk_nameable = MakeNameable::new(tcx);
|
||||
|
|
|
|||
|
|
@ -1,8 +1,9 @@
|
|||
use crate::any::type_name;
|
||||
use crate::fmt;
|
||||
use crate::intrinsics;
|
||||
use crate::mem::ManuallyDrop;
|
||||
use crate::mem::{self, ManuallyDrop};
|
||||
use crate::ptr;
|
||||
use crate::slice;
|
||||
|
||||
/// A wrapper type to construct uninitialized instances of `T`.
|
||||
///
|
||||
|
|
@ -1160,4 +1161,126 @@ impl<T> MaybeUninit<T> {
|
|||
// SAFETY: Valid elements have just been written into `this` so it is initialized
|
||||
unsafe { MaybeUninit::slice_assume_init_mut(this) }
|
||||
}
|
||||
|
||||
/// Returns the contents of this `MaybeUninit` as a slice of potentially uninitialized bytes.
|
||||
///
|
||||
/// Note that even if the contents of a `MaybeUninit` have been initialized, the value may still
|
||||
/// contain padding bytes which are left uninitialized.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(maybe_uninit_as_bytes, maybe_uninit_slice)]
|
||||
/// use std::mem::MaybeUninit;
|
||||
///
|
||||
/// let val = 0x12345678i32;
|
||||
/// let uninit = MaybeUninit::new(val);
|
||||
/// let uninit_bytes = uninit.as_bytes();
|
||||
/// let bytes = unsafe { MaybeUninit::slice_assume_init_ref(uninit_bytes) };
|
||||
/// assert_eq!(bytes, val.to_ne_bytes());
|
||||
/// ```
|
||||
#[unstable(feature = "maybe_uninit_as_bytes", issue = "93092")]
|
||||
pub fn as_bytes(&self) -> &[MaybeUninit<u8>] {
|
||||
// SAFETY: MaybeUninit<u8> is always valid, even for padding bytes
|
||||
unsafe {
|
||||
slice::from_raw_parts(self.as_ptr() as *const MaybeUninit<u8>, mem::size_of::<T>())
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the contents of this `MaybeUninit` as a mutable slice of potentially uninitialized
|
||||
/// bytes.
|
||||
///
|
||||
/// Note that even if the contents of a `MaybeUninit` have been initialized, the value may still
|
||||
/// contain padding bytes which are left uninitialized.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(maybe_uninit_as_bytes)]
|
||||
/// use std::mem::MaybeUninit;
|
||||
///
|
||||
/// let val = 0x12345678i32;
|
||||
/// let mut uninit = MaybeUninit::new(val);
|
||||
/// let uninit_bytes = uninit.as_bytes_mut();
|
||||
/// if cfg!(target_endian = "little") {
|
||||
/// uninit_bytes[0].write(0xcd);
|
||||
/// } else {
|
||||
/// uninit_bytes[3].write(0xcd);
|
||||
/// }
|
||||
/// let val2 = unsafe { uninit.assume_init() };
|
||||
/// assert_eq!(val2, 0x123456cd);
|
||||
/// ```
|
||||
#[unstable(feature = "maybe_uninit_as_bytes", issue = "93092")]
|
||||
pub fn as_bytes_mut(&mut self) -> &mut [MaybeUninit<u8>] {
|
||||
// SAFETY: MaybeUninit<u8> is always valid, even for padding bytes
|
||||
unsafe {
|
||||
slice::from_raw_parts_mut(
|
||||
self.as_mut_ptr() as *mut MaybeUninit<u8>,
|
||||
mem::size_of::<T>(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the contents of this slice of `MaybeUninit` as a slice of potentially uninitialized
|
||||
/// bytes.
|
||||
///
|
||||
/// Note that even if the contents of a `MaybeUninit` have been initialized, the value may still
|
||||
/// contain padding bytes which are left uninitialized.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(maybe_uninit_as_bytes, maybe_uninit_write_slice, maybe_uninit_slice)]
|
||||
/// use std::mem::MaybeUninit;
|
||||
///
|
||||
/// let uninit = [MaybeUninit::new(0x1234u16), MaybeUninit::new(0x5678u16)];
|
||||
/// let uninit_bytes = MaybeUninit::slice_as_bytes(&uninit);
|
||||
/// let bytes = unsafe { MaybeUninit::slice_assume_init_ref(&uninit_bytes) };
|
||||
/// let val1 = u16::from_ne_bytes(bytes[0..2].try_into().unwrap());
|
||||
/// let val2 = u16::from_ne_bytes(bytes[2..4].try_into().unwrap());
|
||||
/// assert_eq!(&[val1, val2], &[0x1234u16, 0x5678u16]);
|
||||
/// ```
|
||||
#[unstable(feature = "maybe_uninit_as_bytes", issue = "93092")]
|
||||
pub fn slice_as_bytes(this: &[MaybeUninit<T>]) -> &[MaybeUninit<u8>] {
|
||||
// SAFETY: MaybeUninit<u8> is always valid, even for padding bytes
|
||||
unsafe {
|
||||
slice::from_raw_parts(
|
||||
this.as_ptr() as *const MaybeUninit<u8>,
|
||||
this.len() * mem::size_of::<T>(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the contents of this mutable slice of `MaybeUninit` as a mutable slice of
|
||||
/// potentially uninitialized bytes.
|
||||
///
|
||||
/// Note that even if the contents of a `MaybeUninit` have been initialized, the value may still
|
||||
/// contain padding bytes which are left uninitialized.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(maybe_uninit_as_bytes, maybe_uninit_write_slice, maybe_uninit_slice)]
|
||||
/// use std::mem::MaybeUninit;
|
||||
///
|
||||
/// let mut uninit = [MaybeUninit::<u16>::uninit(), MaybeUninit::<u16>::uninit()];
|
||||
/// let uninit_bytes = MaybeUninit::slice_as_bytes_mut(&mut uninit);
|
||||
/// MaybeUninit::write_slice(uninit_bytes, &[0x12, 0x34, 0x56, 0x78]);
|
||||
/// let vals = unsafe { MaybeUninit::slice_assume_init_ref(&uninit) };
|
||||
/// if cfg!(target_endian = "little") {
|
||||
/// assert_eq!(vals, &[0x3412u16, 0x7856u16]);
|
||||
/// } else {
|
||||
/// assert_eq!(vals, &[0x1234u16, 0x5678u16]);
|
||||
/// }
|
||||
/// ```
|
||||
#[unstable(feature = "maybe_uninit_as_bytes", issue = "93092")]
|
||||
pub fn slice_as_bytes_mut(this: &mut [MaybeUninit<T>]) -> &mut [MaybeUninit<u8>] {
|
||||
// SAFETY: MaybeUninit<u8> is always valid, even for padding bytes
|
||||
unsafe {
|
||||
slice::from_raw_parts_mut(
|
||||
this.as_mut_ptr() as *mut MaybeUninit<u8>,
|
||||
this.len() * mem::size_of::<T>(),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2042,13 +2042,17 @@ pub fn remove_dir<P: AsRef<Path>>(path: P) -> io::Result<()> {
|
|||
///
|
||||
/// # Platform-specific behavior
|
||||
///
|
||||
/// This function currently corresponds to `opendir`, `lstat`, `rm` and `rmdir` functions on Unix
|
||||
/// and the `FindFirstFile`, `GetFileAttributesEx`, `DeleteFile`, and `RemoveDirectory` functions
|
||||
/// on Windows.
|
||||
/// Note that, this [may change in the future][changes].
|
||||
/// This function currently corresponds to `openat`, `fdopendir`, `unlinkat` and `lstat` functions
|
||||
/// on Unix (except for macOS before version 10.10 and REDOX) and the `CreateFileW`,
|
||||
/// `GetFileInformationByHandleEx`, `SetFileInformationByHandle`, and `NtOpenFile` functions on
|
||||
/// Windows. Note that, this [may change in the future][changes].
|
||||
///
|
||||
/// [changes]: io#platform-specific-behavior
|
||||
///
|
||||
/// On macOS before version 10.10 and REDOX this function is not protected against time-of-check to
|
||||
/// time-of-use (TOCTOU) race conditions, and should not be used in security-sensitive code on
|
||||
/// those platforms. All other platforms are protected.
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// See [`fs::remove_file`] and [`fs::remove_dir`].
|
||||
|
|
|
|||
|
|
@ -4,8 +4,10 @@ use crate::fs::{self, File, OpenOptions};
|
|||
use crate::io::{ErrorKind, SeekFrom};
|
||||
use crate::path::Path;
|
||||
use crate::str;
|
||||
use crate::sync::Arc;
|
||||
use crate::sys_common::io::test::{tmpdir, TempDir};
|
||||
use crate::thread;
|
||||
use crate::time::{Duration, Instant};
|
||||
|
||||
use rand::{rngs::StdRng, RngCore, SeedableRng};
|
||||
|
||||
|
|
@ -601,6 +603,21 @@ fn recursive_rmdir_of_symlink() {
|
|||
assert!(canary.exists());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn recursive_rmdir_of_file_fails() {
|
||||
// test we do not delete a directly specified file.
|
||||
let tmpdir = tmpdir();
|
||||
let canary = tmpdir.join("do_not_delete");
|
||||
check!(check!(File::create(&canary)).write(b"foo"));
|
||||
let result = fs::remove_dir_all(&canary);
|
||||
#[cfg(unix)]
|
||||
error!(result, "Not a directory");
|
||||
#[cfg(windows)]
|
||||
error!(result, 267); // ERROR_DIRECTORY - The directory name is invalid.
|
||||
assert!(result.is_err());
|
||||
assert!(canary.exists());
|
||||
}
|
||||
|
||||
#[test]
|
||||
// only Windows makes a distinction between file and directory symlinks.
|
||||
#[cfg(windows)]
|
||||
|
|
@ -620,6 +637,59 @@ fn recursive_rmdir_of_file_symlink() {
|
|||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[ignore] // takes too much time
|
||||
fn recursive_rmdir_toctou() {
|
||||
// Test for time-of-check to time-of-use issues.
|
||||
//
|
||||
// Scenario:
|
||||
// The attacker wants to get directory contents deleted, to which he does not have access.
|
||||
// He has a way to get a privileged Rust binary call `std::fs::remove_dir_all()` on a
|
||||
// directory he controls, e.g. in his home directory.
|
||||
//
|
||||
// The POC sets up the `attack_dest/attack_file` which the attacker wants to have deleted.
|
||||
// The attacker repeatedly creates a directory and replaces it with a symlink from
|
||||
// `victim_del` to `attack_dest` while the victim code calls `std::fs::remove_dir_all()`
|
||||
// on `victim_del`. After a few seconds the attack has succeeded and
|
||||
// `attack_dest/attack_file` is deleted.
|
||||
let tmpdir = tmpdir();
|
||||
let victim_del_path = tmpdir.join("victim_del");
|
||||
let victim_del_path_clone = victim_del_path.clone();
|
||||
|
||||
// setup dest
|
||||
let attack_dest_dir = tmpdir.join("attack_dest");
|
||||
let attack_dest_dir = attack_dest_dir.as_path();
|
||||
fs::create_dir(attack_dest_dir).unwrap();
|
||||
let attack_dest_file = tmpdir.join("attack_dest/attack_file");
|
||||
File::create(&attack_dest_file).unwrap();
|
||||
|
||||
let drop_canary_arc = Arc::new(());
|
||||
let drop_canary_weak = Arc::downgrade(&drop_canary_arc);
|
||||
|
||||
eprintln!("x: {:?}", &victim_del_path);
|
||||
|
||||
// victim just continuously removes `victim_del`
|
||||
thread::spawn(move || {
|
||||
while drop_canary_weak.upgrade().is_some() {
|
||||
let _ = fs::remove_dir_all(&victim_del_path_clone);
|
||||
}
|
||||
});
|
||||
|
||||
// attacker (could of course be in a separate process)
|
||||
let start_time = Instant::now();
|
||||
while Instant::now().duration_since(start_time) < Duration::from_secs(1000) {
|
||||
if !attack_dest_file.exists() {
|
||||
panic!(
|
||||
"Victim deleted symlinked file outside of victim_del. Attack succeeded in {:?}.",
|
||||
Instant::now().duration_since(start_time)
|
||||
);
|
||||
}
|
||||
let _ = fs::create_dir(&victim_del_path);
|
||||
let _ = fs::remove_dir(&victim_del_path);
|
||||
let _ = symlink_dir(attack_dest_dir, &victim_del_path);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn unicode_path_is_dir() {
|
||||
assert!(Path::new(".").is_dir());
|
||||
|
|
|
|||
|
|
@ -263,7 +263,7 @@ fn default_hook(info: &PanicInfo<'_>) {
|
|||
// If this is a double panic, make sure that we print a backtrace
|
||||
// for this panic. Otherwise only print it if logging is enabled.
|
||||
let backtrace_env = if panic_count::get_count() >= 2 {
|
||||
RustBacktrace::Print(crate::backtrace_rs::PrintFmt::Full)
|
||||
backtrace::rust_backtrace_print_full()
|
||||
} else {
|
||||
backtrace::rust_backtrace_env()
|
||||
};
|
||||
|
|
|
|||
|
|
@ -64,7 +64,7 @@ use libc::{
|
|||
dirent64, fstat64, ftruncate64, lseek64, lstat64, off64_t, open64, readdir64_r, stat64,
|
||||
};
|
||||
|
||||
pub use crate::sys_common::fs::{remove_dir_all, try_exists};
|
||||
pub use crate::sys_common::fs::try_exists;
|
||||
|
||||
pub struct File(FileDesc);
|
||||
|
||||
|
|
@ -228,7 +228,7 @@ pub struct DirEntry {
|
|||
target_os = "fuchsia",
|
||||
target_os = "redox"
|
||||
))]
|
||||
name: Box<[u8]>,
|
||||
name: CString,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
|
|
@ -455,8 +455,6 @@ impl Iterator for ReadDir {
|
|||
target_os = "illumos"
|
||||
))]
|
||||
fn next(&mut self) -> Option<io::Result<DirEntry>> {
|
||||
use crate::slice;
|
||||
|
||||
unsafe {
|
||||
loop {
|
||||
// Although readdir_r(3) would be a correct function to use here because
|
||||
|
|
@ -474,14 +472,10 @@ impl Iterator for ReadDir {
|
|||
};
|
||||
}
|
||||
|
||||
let name = (*entry_ptr).d_name.as_ptr();
|
||||
let namelen = libc::strlen(name) as usize;
|
||||
|
||||
let ret = DirEntry {
|
||||
entry: *entry_ptr,
|
||||
name: slice::from_raw_parts(name as *const u8, namelen as usize)
|
||||
.to_owned()
|
||||
.into_boxed_slice(),
|
||||
// d_name is guaranteed to be null-terminated.
|
||||
name: CStr::from_ptr((*entry_ptr).d_name.as_ptr()).to_owned(),
|
||||
dir: Arc::clone(&self.inner),
|
||||
};
|
||||
if ret.name_bytes() != b"." && ret.name_bytes() != b".." {
|
||||
|
|
@ -664,7 +658,21 @@ impl DirEntry {
|
|||
target_os = "redox"
|
||||
))]
|
||||
fn name_bytes(&self) -> &[u8] {
|
||||
&*self.name
|
||||
self.name.as_bytes()
|
||||
}
|
||||
|
||||
#[cfg(not(any(
|
||||
target_os = "solaris",
|
||||
target_os = "illumos",
|
||||
target_os = "fuchsia",
|
||||
target_os = "redox"
|
||||
)))]
|
||||
fn name_cstr(&self) -> &CStr {
|
||||
unsafe { CStr::from_ptr(self.entry.d_name.as_ptr()) }
|
||||
}
|
||||
#[cfg(any(target_os = "solaris", target_os = "illumos", target_os = "fuchsia"))]
|
||||
fn name_cstr(&self) -> &CStr {
|
||||
&self.name
|
||||
}
|
||||
|
||||
pub fn file_name_os_str(&self) -> &OsStr {
|
||||
|
|
@ -1437,3 +1445,258 @@ pub fn chroot(dir: &Path) -> io::Result<()> {
|
|||
cvt(unsafe { libc::chroot(dir.as_ptr()) })?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub use remove_dir_impl::remove_dir_all;
|
||||
|
||||
// Fallback for REDOX
|
||||
#[cfg(target_os = "redox")]
|
||||
mod remove_dir_impl {
|
||||
pub use crate::sys_common::fs::remove_dir_all;
|
||||
}
|
||||
|
||||
// Dynamically choose implementation Macos x86-64: modern for 10.10+, fallback for older versions
|
||||
#[cfg(all(target_os = "macos", target_arch = "x86_64"))]
|
||||
mod remove_dir_impl {
|
||||
use super::{cstr, lstat, Dir, InnerReadDir, ReadDir};
|
||||
use crate::ffi::CStr;
|
||||
use crate::io;
|
||||
use crate::os::unix::io::{AsRawFd, FromRawFd, IntoRawFd};
|
||||
use crate::os::unix::prelude::{OwnedFd, RawFd};
|
||||
use crate::path::{Path, PathBuf};
|
||||
use crate::sync::Arc;
|
||||
use crate::sys::weak::weak;
|
||||
use crate::sys::{cvt, cvt_r};
|
||||
use libc::{c_char, c_int, DIR};
|
||||
|
||||
pub fn openat_nofollow_dironly(parent_fd: Option<RawFd>, p: &CStr) -> io::Result<OwnedFd> {
|
||||
weak!(fn openat(c_int, *const c_char, c_int) -> c_int);
|
||||
let fd = cvt_r(|| unsafe {
|
||||
openat.get().unwrap()(
|
||||
parent_fd.unwrap_or(libc::AT_FDCWD),
|
||||
p.as_ptr(),
|
||||
libc::O_CLOEXEC | libc::O_RDONLY | libc::O_NOFOLLOW | libc::O_DIRECTORY,
|
||||
)
|
||||
})?;
|
||||
Ok(unsafe { OwnedFd::from_raw_fd(fd) })
|
||||
}
|
||||
|
||||
fn fdreaddir(dir_fd: OwnedFd) -> io::Result<(ReadDir, RawFd)> {
|
||||
weak!(fn fdopendir(c_int) -> *mut DIR, "fdopendir$INODE64");
|
||||
let ptr = unsafe { fdopendir.get().unwrap()(dir_fd.as_raw_fd()) };
|
||||
if ptr.is_null() {
|
||||
return Err(io::Error::last_os_error());
|
||||
}
|
||||
let dirp = Dir(ptr);
|
||||
// file descriptor is automatically closed by libc::closedir() now, so give up ownership
|
||||
let new_parent_fd = dir_fd.into_raw_fd();
|
||||
// a valid root is not needed because we do not call any functions involving the full path
|
||||
// of the DirEntrys.
|
||||
let dummy_root = PathBuf::new();
|
||||
Ok((
|
||||
ReadDir {
|
||||
inner: Arc::new(InnerReadDir { dirp, root: dummy_root }),
|
||||
end_of_stream: false,
|
||||
},
|
||||
new_parent_fd,
|
||||
))
|
||||
}
|
||||
|
||||
fn remove_dir_all_recursive(parent_fd: Option<RawFd>, p: &Path) -> io::Result<()> {
|
||||
weak!(fn unlinkat(c_int, *const c_char, c_int) -> c_int);
|
||||
|
||||
let pcstr = cstr(p)?;
|
||||
|
||||
// entry is expected to be a directory, open as such
|
||||
let fd = openat_nofollow_dironly(parent_fd, &pcstr)?;
|
||||
|
||||
// open the directory passing ownership of the fd
|
||||
let (dir, fd) = fdreaddir(fd)?;
|
||||
for child in dir {
|
||||
let child = child?;
|
||||
match child.entry.d_type {
|
||||
libc::DT_DIR => {
|
||||
remove_dir_all_recursive(Some(fd), Path::new(&child.file_name()))?;
|
||||
}
|
||||
libc::DT_UNKNOWN => {
|
||||
match cvt(unsafe { unlinkat.get().unwrap()(fd, child.name_cstr().as_ptr(), 0) })
|
||||
{
|
||||
// type unknown - try to unlink
|
||||
Err(err) if err.raw_os_error() == Some(libc::EPERM) => {
|
||||
// if the file is a directory unlink fails with EPERM
|
||||
remove_dir_all_recursive(Some(fd), Path::new(&child.file_name()))?;
|
||||
}
|
||||
result => {
|
||||
result?;
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
// not a directory -> unlink
|
||||
cvt(unsafe { unlinkat.get().unwrap()(fd, child.name_cstr().as_ptr(), 0) })?;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// unlink the directory after removing its contents
|
||||
cvt(unsafe {
|
||||
unlinkat.get().unwrap()(
|
||||
parent_fd.unwrap_or(libc::AT_FDCWD),
|
||||
pcstr.as_ptr(),
|
||||
libc::AT_REMOVEDIR,
|
||||
)
|
||||
})?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn remove_dir_all_modern(p: &Path) -> io::Result<()> {
|
||||
// We cannot just call remove_dir_all_recursive() here because that would not delete a passed
|
||||
// symlink. No need to worry about races, because remove_dir_all_recursive() does not recurse
|
||||
// into symlinks.
|
||||
let attr = lstat(p)?;
|
||||
if attr.file_type().is_symlink() {
|
||||
crate::fs::remove_file(p)
|
||||
} else {
|
||||
remove_dir_all_recursive(None, p)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn remove_dir_all(p: &Path) -> io::Result<()> {
|
||||
weak!(fn openat(c_int, *const c_char, c_int) -> c_int);
|
||||
if openat.get().is_some() {
|
||||
// openat() is available with macOS 10.10+, just like unlinkat() and fdopendir()
|
||||
remove_dir_all_modern(p)
|
||||
} else {
|
||||
// fall back to classic implementation
|
||||
crate::sys_common::fs::remove_dir_all(p)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Modern implementation using openat(), unlinkat() and fdopendir()
|
||||
#[cfg(not(any(all(target_os = "macos", target_arch = "x86_64"), target_os = "redox")))]
|
||||
mod remove_dir_impl {
|
||||
use super::{cstr, lstat, Dir, DirEntry, InnerReadDir, ReadDir};
|
||||
use crate::ffi::CStr;
|
||||
use crate::io;
|
||||
use crate::os::unix::io::{AsRawFd, FromRawFd, IntoRawFd};
|
||||
use crate::os::unix::prelude::{OwnedFd, RawFd};
|
||||
use crate::path::{Path, PathBuf};
|
||||
use crate::sync::Arc;
|
||||
use crate::sys::{cvt, cvt_r};
|
||||
use libc::{fdopendir, openat, unlinkat};
|
||||
|
||||
pub fn openat_nofollow_dironly(parent_fd: Option<RawFd>, p: &CStr) -> io::Result<OwnedFd> {
|
||||
let fd = cvt_r(|| unsafe {
|
||||
openat(
|
||||
parent_fd.unwrap_or(libc::AT_FDCWD),
|
||||
p.as_ptr(),
|
||||
libc::O_CLOEXEC | libc::O_RDONLY | libc::O_NOFOLLOW | libc::O_DIRECTORY,
|
||||
)
|
||||
})?;
|
||||
Ok(unsafe { OwnedFd::from_raw_fd(fd) })
|
||||
}
|
||||
|
||||
fn fdreaddir(dir_fd: OwnedFd) -> io::Result<(ReadDir, RawFd)> {
|
||||
let ptr = unsafe { fdopendir(dir_fd.as_raw_fd()) };
|
||||
if ptr.is_null() {
|
||||
return Err(io::Error::last_os_error());
|
||||
}
|
||||
let dirp = Dir(ptr);
|
||||
// file descriptor is automatically closed by libc::closedir() now, so give up ownership
|
||||
let new_parent_fd = dir_fd.into_raw_fd();
|
||||
// a valid root is not needed because we do not call any functions involving the full path
|
||||
// of the DirEntrys.
|
||||
let dummy_root = PathBuf::new();
|
||||
Ok((
|
||||
ReadDir {
|
||||
inner: Arc::new(InnerReadDir { dirp, root: dummy_root }),
|
||||
#[cfg(not(any(
|
||||
target_os = "solaris",
|
||||
target_os = "illumos",
|
||||
target_os = "fuchsia",
|
||||
target_os = "redox",
|
||||
)))]
|
||||
end_of_stream: false,
|
||||
},
|
||||
new_parent_fd,
|
||||
))
|
||||
}
|
||||
|
||||
#[cfg(any(
|
||||
target_os = "solaris",
|
||||
target_os = "illumos",
|
||||
target_os = "haiku",
|
||||
target_os = "vxworks",
|
||||
target_os = "fuchsia"
|
||||
))]
|
||||
fn is_dir(_ent: &DirEntry) -> Option<bool> {
|
||||
None
|
||||
}
|
||||
|
||||
#[cfg(not(any(
|
||||
target_os = "solaris",
|
||||
target_os = "illumos",
|
||||
target_os = "haiku",
|
||||
target_os = "vxworks",
|
||||
target_os = "fuchsia"
|
||||
)))]
|
||||
fn is_dir(ent: &DirEntry) -> Option<bool> {
|
||||
match ent.entry.d_type {
|
||||
libc::DT_UNKNOWN => None,
|
||||
libc::DT_DIR => Some(true),
|
||||
_ => Some(false),
|
||||
}
|
||||
}
|
||||
|
||||
fn remove_dir_all_recursive(parent_fd: Option<RawFd>, p: &Path) -> io::Result<()> {
|
||||
let pcstr = cstr(p)?;
|
||||
|
||||
// entry is expected to be a directory, open as such
|
||||
let fd = openat_nofollow_dironly(parent_fd, &pcstr)?;
|
||||
|
||||
// open the directory passing ownership of the fd
|
||||
let (dir, fd) = fdreaddir(fd)?;
|
||||
for child in dir {
|
||||
let child = child?;
|
||||
match is_dir(&child) {
|
||||
Some(true) => {
|
||||
remove_dir_all_recursive(Some(fd), Path::new(&child.file_name()))?;
|
||||
}
|
||||
Some(false) => {
|
||||
cvt(unsafe { unlinkat(fd, child.name_cstr().as_ptr(), 0) })?;
|
||||
}
|
||||
None => match cvt(unsafe { unlinkat(fd, child.name_cstr().as_ptr(), 0) }) {
|
||||
// type unknown - try to unlink
|
||||
Err(err)
|
||||
if err.raw_os_error() == Some(libc::EISDIR)
|
||||
|| err.raw_os_error() == Some(libc::EPERM) =>
|
||||
{
|
||||
// if the file is a directory unlink fails with EISDIR on Linux and EPERM everyhwere else
|
||||
remove_dir_all_recursive(Some(fd), Path::new(&child.file_name()))?;
|
||||
}
|
||||
result => {
|
||||
result?;
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// unlink the directory after removing its contents
|
||||
cvt(unsafe {
|
||||
unlinkat(parent_fd.unwrap_or(libc::AT_FDCWD), pcstr.as_ptr(), libc::AT_REMOVEDIR)
|
||||
})?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn remove_dir_all(p: &Path) -> io::Result<()> {
|
||||
// We cannot just call remove_dir_all_recursive() here because that would not delete a passed
|
||||
// symlink. No need to worry about races, because remove_dir_all_recursive() does not recurse
|
||||
// into symlinks.
|
||||
let attr = lstat(p)?;
|
||||
if attr.file_type().is_symlink() {
|
||||
crate::fs::remove_file(p)
|
||||
} else {
|
||||
remove_dir_all_recursive(None, p)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -73,12 +73,14 @@ impl<F> ExternWeak<F> {
|
|||
|
||||
pub(crate) macro dlsym {
|
||||
(fn $name:ident($($t:ty),*) -> $ret:ty) => (
|
||||
dlsym!(fn $name($($t),*) -> $ret, stringify!($name));
|
||||
),
|
||||
(fn $name:ident($($t:ty),*) -> $ret:ty, $sym:expr) => (
|
||||
static DLSYM: DlsymWeak<unsafe extern "C" fn($($t),*) -> $ret> =
|
||||
DlsymWeak::new(concat!(stringify!($name), '\0'));
|
||||
DlsymWeak::new(concat!($sym, '\0'));
|
||||
let $name = &DLSYM;
|
||||
)
|
||||
}
|
||||
|
||||
pub(crate) struct DlsymWeak<F> {
|
||||
name: &'static str,
|
||||
addr: AtomicUsize,
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ use crate::sys::time::SystemTime;
|
|||
use crate::sys::unsupported;
|
||||
use crate::sys_common::{AsInner, FromInner, IntoInner};
|
||||
|
||||
pub use crate::sys_common::fs::{remove_dir_all, try_exists};
|
||||
pub use crate::sys_common::fs::try_exists;
|
||||
|
||||
pub struct File {
|
||||
fd: WasiFd,
|
||||
|
|
@ -130,6 +130,18 @@ impl FileType {
|
|||
}
|
||||
}
|
||||
|
||||
impl ReadDir {
|
||||
fn new(dir: File, root: PathBuf) -> ReadDir {
|
||||
ReadDir {
|
||||
cookie: Some(0),
|
||||
buf: vec![0; 128],
|
||||
offset: 0,
|
||||
cap: 0,
|
||||
inner: Arc::new(ReadDirInner { dir, root }),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for ReadDir {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.debug_struct("ReadDir").finish_non_exhaustive()
|
||||
|
|
@ -516,13 +528,7 @@ pub fn readdir(p: &Path) -> io::Result<ReadDir> {
|
|||
opts.directory(true);
|
||||
opts.read(true);
|
||||
let dir = File::open(p, &opts)?;
|
||||
Ok(ReadDir {
|
||||
cookie: Some(0),
|
||||
buf: vec![0; 128],
|
||||
offset: 0,
|
||||
cap: 0,
|
||||
inner: Arc::new(ReadDirInner { dir, root: p.to_path_buf() }),
|
||||
})
|
||||
Ok(ReadDir::new(dir, p.to_path_buf()))
|
||||
}
|
||||
|
||||
pub fn unlink(p: &Path) -> io::Result<()> {
|
||||
|
|
@ -716,3 +722,52 @@ pub fn copy(from: &Path, to: &Path) -> io::Result<u64> {
|
|||
|
||||
io::copy(&mut reader, &mut writer)
|
||||
}
|
||||
|
||||
pub fn remove_dir_all(path: &Path) -> io::Result<()> {
|
||||
let (parent, path) = open_parent(path)?;
|
||||
remove_dir_all_recursive(&parent, &path)
|
||||
}
|
||||
|
||||
fn remove_dir_all_recursive(parent: &WasiFd, path: &Path) -> io::Result<()> {
|
||||
// Open up a file descriptor for the directory itself. Note that we don't
|
||||
// follow symlinks here and we specifically open directories.
|
||||
//
|
||||
// At the root invocation of this function this will correctly handle
|
||||
// symlinks passed to the top-level `remove_dir_all`. At the recursive
|
||||
// level this will double-check that after the `readdir` call deduced this
|
||||
// was a directory it's still a directory by the time we open it up.
|
||||
//
|
||||
// If the opened file was actually a symlink then the symlink is deleted,
|
||||
// not the directory recursively.
|
||||
let mut opts = OpenOptions::new();
|
||||
opts.lookup_flags(0);
|
||||
opts.directory(true);
|
||||
opts.read(true);
|
||||
let fd = open_at(parent, path, &opts)?;
|
||||
if fd.file_attr()?.file_type().is_symlink() {
|
||||
return parent.unlink_file(osstr2str(path.as_ref())?);
|
||||
}
|
||||
|
||||
// this "root" is only used by `DirEntry::path` which we don't use below so
|
||||
// it's ok for this to be a bogus value
|
||||
let dummy_root = PathBuf::new();
|
||||
|
||||
// Iterate over all the entries in this directory, and travel recursively if
|
||||
// necessary
|
||||
for entry in ReadDir::new(fd, dummy_root) {
|
||||
let entry = entry?;
|
||||
let path = crate::str::from_utf8(&entry.name).map_err(|_| {
|
||||
io::Error::new_const(io::ErrorKind::Uncategorized, &"invalid utf-8 file name found")
|
||||
})?;
|
||||
|
||||
if entry.file_type()?.is_dir() {
|
||||
remove_dir_all_recursive(&entry.inner.dir.fd, path.as_ref())?;
|
||||
} else {
|
||||
entry.inner.dir.fd.unlink_file(path)?;
|
||||
}
|
||||
}
|
||||
|
||||
// Once all this directory's contents are deleted it should be safe to
|
||||
// delete the directory tiself.
|
||||
parent.remove_directory(osstr2str(path.as_ref())?)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@
|
|||
#![cfg_attr(test, allow(dead_code))]
|
||||
#![unstable(issue = "none", feature = "windows_c")]
|
||||
|
||||
use crate::mem;
|
||||
use crate::os::raw::NonZero_c_ulong;
|
||||
use crate::os::raw::{c_char, c_int, c_long, c_longlong, c_uint, c_ulong, c_ushort};
|
||||
use crate::ptr;
|
||||
|
|
@ -36,6 +37,7 @@ pub type USHORT = c_ushort;
|
|||
pub type SIZE_T = usize;
|
||||
pub type WORD = u16;
|
||||
pub type CHAR = c_char;
|
||||
pub type CCHAR = c_char;
|
||||
pub type ULONG_PTR = usize;
|
||||
pub type ULONG = c_ulong;
|
||||
pub type NTSTATUS = LONG;
|
||||
|
|
@ -86,16 +88,21 @@ pub const FILE_SHARE_DELETE: DWORD = 0x4;
|
|||
pub const FILE_SHARE_READ: DWORD = 0x1;
|
||||
pub const FILE_SHARE_WRITE: DWORD = 0x2;
|
||||
|
||||
pub const FILE_OPEN_REPARSE_POINT: ULONG = 0x200000;
|
||||
pub const OBJ_DONT_REPARSE: ULONG = 0x1000;
|
||||
|
||||
pub const CREATE_ALWAYS: DWORD = 2;
|
||||
pub const CREATE_NEW: DWORD = 1;
|
||||
pub const OPEN_ALWAYS: DWORD = 4;
|
||||
pub const OPEN_EXISTING: DWORD = 3;
|
||||
pub const TRUNCATE_EXISTING: DWORD = 5;
|
||||
|
||||
pub const FILE_LIST_DIRECTORY: DWORD = 0x1;
|
||||
pub const FILE_WRITE_DATA: DWORD = 0x00000002;
|
||||
pub const FILE_APPEND_DATA: DWORD = 0x00000004;
|
||||
pub const FILE_WRITE_EA: DWORD = 0x00000010;
|
||||
pub const FILE_WRITE_ATTRIBUTES: DWORD = 0x00000100;
|
||||
pub const DELETE: DWORD = 0x10000;
|
||||
pub const READ_CONTROL: DWORD = 0x00020000;
|
||||
pub const SYNCHRONIZE: DWORD = 0x00100000;
|
||||
pub const GENERIC_READ: DWORD = 0x80000000;
|
||||
|
|
@ -261,9 +268,61 @@ pub const FD_SETSIZE: usize = 64;
|
|||
pub const STACK_SIZE_PARAM_IS_A_RESERVATION: DWORD = 0x00010000;
|
||||
|
||||
pub const STATUS_SUCCESS: NTSTATUS = 0x00000000;
|
||||
pub const STATUS_DELETE_PENDING: NTSTATUS = 0xc0000056_u32 as _;
|
||||
pub const STATUS_INVALID_PARAMETER: NTSTATUS = 0xc000000d_u32 as _;
|
||||
|
||||
// Equivalent to the `NT_SUCCESS` C preprocessor macro.
|
||||
// See: https://docs.microsoft.com/en-us/windows-hardware/drivers/kernel/using-ntstatus-values
|
||||
pub fn nt_success(status: NTSTATUS) -> bool {
|
||||
status >= 0
|
||||
}
|
||||
|
||||
pub const BCRYPT_USE_SYSTEM_PREFERRED_RNG: DWORD = 0x00000002;
|
||||
|
||||
#[repr(C)]
|
||||
pub struct UNICODE_STRING {
|
||||
pub Length: u16,
|
||||
pub MaximumLength: u16,
|
||||
pub Buffer: *mut u16,
|
||||
}
|
||||
impl UNICODE_STRING {
|
||||
pub fn from_ref(slice: &[u16]) -> Self {
|
||||
let len = slice.len() * mem::size_of::<u16>();
|
||||
Self { Length: len as _, MaximumLength: len as _, Buffer: slice.as_ptr() as _ }
|
||||
}
|
||||
}
|
||||
#[repr(C)]
|
||||
pub struct OBJECT_ATTRIBUTES {
|
||||
pub Length: ULONG,
|
||||
pub RootDirectory: HANDLE,
|
||||
pub ObjectName: *const UNICODE_STRING,
|
||||
pub Attributes: ULONG,
|
||||
pub SecurityDescriptor: *mut c_void,
|
||||
pub SecurityQualityOfService: *mut c_void,
|
||||
}
|
||||
impl Default for OBJECT_ATTRIBUTES {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
Length: mem::size_of::<Self>() as _,
|
||||
RootDirectory: ptr::null_mut(),
|
||||
ObjectName: ptr::null_mut(),
|
||||
Attributes: 0,
|
||||
SecurityDescriptor: ptr::null_mut(),
|
||||
SecurityQualityOfService: ptr::null_mut(),
|
||||
}
|
||||
}
|
||||
}
|
||||
#[repr(C)]
|
||||
pub struct IO_STATUS_BLOCK {
|
||||
pub Pointer: *mut c_void,
|
||||
pub Information: usize,
|
||||
}
|
||||
impl Default for IO_STATUS_BLOCK {
|
||||
fn default() -> Self {
|
||||
Self { Pointer: ptr::null_mut(), Information: 0 }
|
||||
}
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[cfg(not(target_pointer_width = "64"))]
|
||||
pub struct WSADATA {
|
||||
|
|
@ -353,9 +412,43 @@ pub enum FILE_INFO_BY_HANDLE_CLASS {
|
|||
FileIdInfo = 18, // 0x12
|
||||
FileIdExtdDirectoryInfo = 19, // 0x13
|
||||
FileIdExtdDirectoryRestartInfo = 20, // 0x14
|
||||
FileDispositionInfoEx = 21, // 0x15, Windows 10 version 1607
|
||||
MaximumFileInfoByHandlesClass,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub struct FILE_DISPOSITION_INFO {
|
||||
pub DeleteFile: BOOLEAN,
|
||||
}
|
||||
|
||||
pub const FILE_DISPOSITION_DELETE: DWORD = 0x1;
|
||||
pub const FILE_DISPOSITION_POSIX_SEMANTICS: DWORD = 0x2;
|
||||
pub const FILE_DISPOSITION_IGNORE_READONLY_ATTRIBUTE: DWORD = 0x10;
|
||||
|
||||
#[repr(C)]
|
||||
pub struct FILE_DISPOSITION_INFO_EX {
|
||||
pub Flags: DWORD,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Default)]
|
||||
pub struct FILE_ID_BOTH_DIR_INFO {
|
||||
pub NextEntryOffset: DWORD,
|
||||
pub FileIndex: DWORD,
|
||||
pub CreationTime: LARGE_INTEGER,
|
||||
pub LastAccessTime: LARGE_INTEGER,
|
||||
pub LastWriteTime: LARGE_INTEGER,
|
||||
pub ChangeTime: LARGE_INTEGER,
|
||||
pub EndOfFile: LARGE_INTEGER,
|
||||
pub AllocationSize: LARGE_INTEGER,
|
||||
pub FileAttributes: DWORD,
|
||||
pub FileNameLength: DWORD,
|
||||
pub EaSize: DWORD,
|
||||
pub ShortNameLength: CCHAR,
|
||||
pub ShortName: [WCHAR; 12],
|
||||
pub FileId: LARGE_INTEGER,
|
||||
pub FileName: [WCHAR; 1],
|
||||
}
|
||||
#[repr(C)]
|
||||
pub struct FILE_BASIC_INFO {
|
||||
pub CreationTime: LARGE_INTEGER,
|
||||
|
|
@ -750,16 +843,6 @@ if #[cfg(target_vendor = "uwp")] {
|
|||
pub DeletePending: BOOLEAN,
|
||||
pub Directory: BOOLEAN,
|
||||
}
|
||||
|
||||
#[link(name = "kernel32")]
|
||||
extern "system" {
|
||||
pub fn GetFileInformationByHandleEx(
|
||||
hFile: HANDLE,
|
||||
fileInfoClass: FILE_INFO_BY_HANDLE_CLASS,
|
||||
lpFileInformation: LPVOID,
|
||||
dwBufferSize: DWORD,
|
||||
) -> BOOL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -949,6 +1032,12 @@ extern "system" {
|
|||
cchFilePath: DWORD,
|
||||
dwFlags: DWORD,
|
||||
) -> DWORD;
|
||||
pub fn GetFileInformationByHandleEx(
|
||||
hFile: HANDLE,
|
||||
fileInfoClass: FILE_INFO_BY_HANDLE_CLASS,
|
||||
lpFileInformation: LPVOID,
|
||||
dwBufferSize: DWORD,
|
||||
) -> BOOL;
|
||||
pub fn SetFileInformationByHandle(
|
||||
hFile: HANDLE,
|
||||
FileInformationClass: FILE_INFO_BY_HANDLE_CLASS,
|
||||
|
|
@ -1139,6 +1228,21 @@ compat_fn! {
|
|||
|
||||
compat_fn! {
|
||||
"ntdll":
|
||||
pub fn NtOpenFile(
|
||||
FileHandle: *mut HANDLE,
|
||||
DesiredAccess: ACCESS_MASK,
|
||||
ObjectAttributes: *const OBJECT_ATTRIBUTES,
|
||||
IoStatusBlock: *mut IO_STATUS_BLOCK,
|
||||
ShareAccess: ULONG,
|
||||
OpenOptions: ULONG
|
||||
) -> NTSTATUS {
|
||||
panic!("`NtOpenFile` not available");
|
||||
}
|
||||
pub fn RtlNtStatusToDosError(
|
||||
Status: NTSTATUS
|
||||
) -> ULONG {
|
||||
panic!("`RtlNtStatusToDosError` not available");
|
||||
}
|
||||
pub fn NtCreateKeyedEvent(
|
||||
KeyedEventHandle: LPHANDLE,
|
||||
DesiredAccess: ACCESS_MASK,
|
||||
|
|
|
|||
|
|
@ -547,6 +547,218 @@ impl File {
|
|||
})?;
|
||||
Ok(())
|
||||
}
|
||||
/// Get only basic file information such as attributes and file times.
|
||||
fn basic_info(&self) -> io::Result<c::FILE_BASIC_INFO> {
|
||||
unsafe {
|
||||
let mut info: c::FILE_BASIC_INFO = mem::zeroed();
|
||||
let size = mem::size_of_val(&info);
|
||||
cvt(c::GetFileInformationByHandleEx(
|
||||
self.handle.as_raw_handle(),
|
||||
c::FileBasicInfo,
|
||||
&mut info as *mut _ as *mut libc::c_void,
|
||||
size as c::DWORD,
|
||||
))?;
|
||||
Ok(info)
|
||||
}
|
||||
}
|
||||
/// Delete using POSIX semantics.
|
||||
///
|
||||
/// Files will be deleted as soon as the handle is closed. This is supported
|
||||
/// for Windows 10 1607 (aka RS1) and later. However some filesystem
|
||||
/// drivers will not support it even then, e.g. FAT32.
|
||||
///
|
||||
/// If the operation is not supported for this filesystem or OS version
|
||||
/// then errors will be `ERROR_NOT_SUPPORTED` or `ERROR_INVALID_PARAMETER`.
|
||||
fn posix_delete(&self) -> io::Result<()> {
|
||||
let mut info = c::FILE_DISPOSITION_INFO_EX {
|
||||
Flags: c::FILE_DISPOSITION_DELETE
|
||||
| c::FILE_DISPOSITION_POSIX_SEMANTICS
|
||||
| c::FILE_DISPOSITION_IGNORE_READONLY_ATTRIBUTE,
|
||||
};
|
||||
let size = mem::size_of_val(&info);
|
||||
cvt(unsafe {
|
||||
c::SetFileInformationByHandle(
|
||||
self.handle.as_raw_handle(),
|
||||
c::FileDispositionInfoEx,
|
||||
&mut info as *mut _ as *mut _,
|
||||
size as c::DWORD,
|
||||
)
|
||||
})?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Delete a file using win32 semantics. The file won't actually be deleted
|
||||
/// until all file handles are closed. However, marking a file for deletion
|
||||
/// will prevent anyone from opening a new handle to the file.
|
||||
fn win32_delete(&self) -> io::Result<()> {
|
||||
let mut info = c::FILE_DISPOSITION_INFO { DeleteFile: c::TRUE as _ };
|
||||
let size = mem::size_of_val(&info);
|
||||
cvt(unsafe {
|
||||
c::SetFileInformationByHandle(
|
||||
self.handle.as_raw_handle(),
|
||||
c::FileDispositionInfo,
|
||||
&mut info as *mut _ as *mut _,
|
||||
size as c::DWORD,
|
||||
)
|
||||
})?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Fill the given buffer with as many directory entries as will fit.
|
||||
/// This will remember its position and continue from the last call unless
|
||||
/// `restart` is set to `true`.
|
||||
///
|
||||
/// The returned bool indicates if there are more entries or not.
|
||||
/// It is an error if `self` is not a directory.
|
||||
///
|
||||
/// # Symlinks and other reparse points
|
||||
///
|
||||
/// On Windows a file is either a directory or a non-directory.
|
||||
/// A symlink directory is simply an empty directory with some "reparse" metadata attached.
|
||||
/// So if you open a link (not its target) and iterate the directory,
|
||||
/// you will always iterate an empty directory regardless of the target.
|
||||
fn fill_dir_buff(&self, buffer: &mut DirBuff, restart: bool) -> io::Result<bool> {
|
||||
let class =
|
||||
if restart { c::FileIdBothDirectoryRestartInfo } else { c::FileIdBothDirectoryInfo };
|
||||
|
||||
unsafe {
|
||||
let result = cvt(c::GetFileInformationByHandleEx(
|
||||
self.handle.as_raw_handle(),
|
||||
class,
|
||||
buffer.as_mut_ptr().cast(),
|
||||
buffer.capacity() as _,
|
||||
));
|
||||
match result {
|
||||
Ok(_) => Ok(true),
|
||||
Err(e) if e.raw_os_error() == Some(c::ERROR_NO_MORE_FILES as _) => Ok(false),
|
||||
Err(e) => Err(e),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// A buffer for holding directory entries.
|
||||
struct DirBuff {
|
||||
buffer: Vec<u8>,
|
||||
}
|
||||
impl DirBuff {
|
||||
fn new() -> Self {
|
||||
const BUFFER_SIZE: usize = 1024;
|
||||
Self { buffer: vec![0_u8; BUFFER_SIZE] }
|
||||
}
|
||||
fn capacity(&self) -> usize {
|
||||
self.buffer.len()
|
||||
}
|
||||
fn as_mut_ptr(&mut self) -> *mut u8 {
|
||||
self.buffer.as_mut_ptr().cast()
|
||||
}
|
||||
/// Returns a `DirBuffIter`.
|
||||
fn iter(&self) -> DirBuffIter<'_> {
|
||||
DirBuffIter::new(self)
|
||||
}
|
||||
}
|
||||
impl AsRef<[u8]> for DirBuff {
|
||||
fn as_ref(&self) -> &[u8] {
|
||||
&self.buffer
|
||||
}
|
||||
}
|
||||
|
||||
/// An iterator over entries stored in a `DirBuff`.
|
||||
///
|
||||
/// Currently only returns file names (UTF-16 encoded).
|
||||
struct DirBuffIter<'a> {
|
||||
buffer: Option<&'a [u8]>,
|
||||
cursor: usize,
|
||||
}
|
||||
impl<'a> DirBuffIter<'a> {
|
||||
fn new(buffer: &'a DirBuff) -> Self {
|
||||
Self { buffer: Some(buffer.as_ref()), cursor: 0 }
|
||||
}
|
||||
}
|
||||
impl<'a> Iterator for DirBuffIter<'a> {
|
||||
type Item = &'a [u16];
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
use crate::mem::size_of;
|
||||
let buffer = &self.buffer?[self.cursor..];
|
||||
|
||||
// Get the name and next entry from the buffer.
|
||||
// SAFETY: The buffer contains a `FILE_ID_BOTH_DIR_INFO` struct but the
|
||||
// last field (the file name) is unsized. So an offset has to be
|
||||
// used to get the file name slice.
|
||||
let (name, next_entry) = unsafe {
|
||||
let info = buffer.as_ptr().cast::<c::FILE_ID_BOTH_DIR_INFO>();
|
||||
let next_entry = (*info).NextEntryOffset as usize;
|
||||
let name = crate::slice::from_raw_parts(
|
||||
(*info).FileName.as_ptr().cast::<u16>(),
|
||||
(*info).FileNameLength as usize / size_of::<u16>(),
|
||||
);
|
||||
(name, next_entry)
|
||||
};
|
||||
|
||||
if next_entry == 0 {
|
||||
self.buffer = None
|
||||
} else {
|
||||
self.cursor += next_entry
|
||||
}
|
||||
|
||||
// Skip `.` and `..` pseudo entries.
|
||||
const DOT: u16 = b'.' as u16;
|
||||
match name {
|
||||
[DOT] | [DOT, DOT] => self.next(),
|
||||
_ => Some(name),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Open a link relative to the parent directory, ensure no symlinks are followed.
|
||||
fn open_link_no_reparse(parent: &File, name: &[u16], access: u32) -> io::Result<File> {
|
||||
// This is implemented using the lower level `NtOpenFile` function as
|
||||
// unfortunately opening a file relative to a parent is not supported by
|
||||
// win32 functions. It is however a fundamental feature of the NT kernel.
|
||||
//
|
||||
// See https://docs.microsoft.com/en-us/windows/win32/api/winternl/nf-winternl-ntopenfile
|
||||
unsafe {
|
||||
let mut handle = ptr::null_mut();
|
||||
let mut io_status = c::IO_STATUS_BLOCK::default();
|
||||
let name_str = c::UNICODE_STRING::from_ref(name);
|
||||
use crate::sync::atomic::{AtomicU32, Ordering};
|
||||
// The `OBJ_DONT_REPARSE` attribute ensures that we haven't been
|
||||
// tricked into following a symlink. However, it may not be available in
|
||||
// earlier versions of Windows.
|
||||
static ATTRIBUTES: AtomicU32 = AtomicU32::new(c::OBJ_DONT_REPARSE);
|
||||
let object = c::OBJECT_ATTRIBUTES {
|
||||
ObjectName: &name_str,
|
||||
RootDirectory: parent.as_raw_handle(),
|
||||
Attributes: ATTRIBUTES.load(Ordering::Relaxed),
|
||||
..c::OBJECT_ATTRIBUTES::default()
|
||||
};
|
||||
let status = c::NtOpenFile(
|
||||
&mut handle,
|
||||
access,
|
||||
&object,
|
||||
&mut io_status,
|
||||
c::FILE_SHARE_DELETE | c::FILE_SHARE_READ | c::FILE_SHARE_WRITE,
|
||||
// If `name` is a symlink then open the link rather than the target.
|
||||
c::FILE_OPEN_REPARSE_POINT,
|
||||
);
|
||||
// Convert an NTSTATUS to the more familiar Win32 error codes (aka "DosError")
|
||||
if c::nt_success(status) {
|
||||
Ok(File::from_raw_handle(handle))
|
||||
} else if status == c::STATUS_DELETE_PENDING {
|
||||
// We make a special exception for `STATUS_DELETE_PENDING` because
|
||||
// otherwise this will be mapped to `ERROR_ACCESS_DENIED` which is
|
||||
// very unhelpful.
|
||||
Err(io::Error::from_raw_os_error(c::ERROR_DELETE_PENDING as _))
|
||||
} else if status == c::STATUS_INVALID_PARAMETER
|
||||
&& ATTRIBUTES.load(Ordering::Relaxed) == c::OBJ_DONT_REPARSE
|
||||
{
|
||||
// Try without `OBJ_DONT_REPARSE`. See above.
|
||||
ATTRIBUTES.store(0, Ordering::Relaxed);
|
||||
open_link_no_reparse(parent, name, access)
|
||||
} else {
|
||||
Err(io::Error::from_raw_os_error(c::RtlNtStatusToDosError(status) as _))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl AsInner<Handle> for File {
|
||||
|
|
@ -756,30 +968,106 @@ pub fn rmdir(p: &Path) -> io::Result<()> {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
/// Open a file or directory without following symlinks.
|
||||
fn open_link(path: &Path, access_mode: u32) -> io::Result<File> {
|
||||
let mut opts = OpenOptions::new();
|
||||
opts.access_mode(access_mode);
|
||||
// `FILE_FLAG_BACKUP_SEMANTICS` allows opening directories.
|
||||
// `FILE_FLAG_OPEN_REPARSE_POINT` opens a link instead of its target.
|
||||
opts.custom_flags(c::FILE_FLAG_BACKUP_SEMANTICS | c::FILE_FLAG_OPEN_REPARSE_POINT);
|
||||
File::open(path, &opts)
|
||||
}
|
||||
|
||||
pub fn remove_dir_all(path: &Path) -> io::Result<()> {
|
||||
let filetype = lstat(path)?.file_type();
|
||||
if filetype.is_symlink() {
|
||||
// On Windows symlinks to files and directories are removed differently.
|
||||
// rmdir only deletes dir symlinks and junctions, not file symlinks.
|
||||
rmdir(path)
|
||||
let file = open_link(path, c::DELETE | c::FILE_LIST_DIRECTORY)?;
|
||||
|
||||
// Test if the file is not a directory or a symlink to a directory.
|
||||
if (file.basic_info()?.FileAttributes & c::FILE_ATTRIBUTE_DIRECTORY) == 0 {
|
||||
return Err(io::Error::from_raw_os_error(c::ERROR_DIRECTORY as _));
|
||||
}
|
||||
let mut delete: fn(&File) -> io::Result<()> = File::posix_delete;
|
||||
let result = match delete(&file) {
|
||||
Err(e) if e.kind() == io::ErrorKind::DirectoryNotEmpty => {
|
||||
match remove_dir_all_recursive(&file, delete) {
|
||||
// Return unexpected errors.
|
||||
Err(e) if e.kind() != io::ErrorKind::DirectoryNotEmpty => return Err(e),
|
||||
result => result,
|
||||
}
|
||||
}
|
||||
// If POSIX delete is not supported for this filesystem then fallback to win32 delete.
|
||||
Err(e)
|
||||
if e.raw_os_error() == Some(c::ERROR_NOT_SUPPORTED as i32)
|
||||
|| e.raw_os_error() == Some(c::ERROR_INVALID_PARAMETER as i32) =>
|
||||
{
|
||||
delete = File::win32_delete;
|
||||
Err(e)
|
||||
}
|
||||
result => result,
|
||||
};
|
||||
if result.is_ok() {
|
||||
Ok(())
|
||||
} else {
|
||||
remove_dir_all_recursive(path)
|
||||
// This is a fallback to make sure the directory is actually deleted.
|
||||
// Otherwise this function is prone to failing with `DirectoryNotEmpty`
|
||||
// due to possible delays between marking a file for deletion and the
|
||||
// file actually being deleted from the filesystem.
|
||||
//
|
||||
// So we retry a few times before giving up.
|
||||
for _ in 0..5 {
|
||||
match remove_dir_all_recursive(&file, delete) {
|
||||
Err(e) if e.kind() == io::ErrorKind::DirectoryNotEmpty => {}
|
||||
result => return result,
|
||||
}
|
||||
}
|
||||
// Try one last time.
|
||||
delete(&file)
|
||||
}
|
||||
}
|
||||
|
||||
fn remove_dir_all_recursive(path: &Path) -> io::Result<()> {
|
||||
for child in readdir(path)? {
|
||||
let child = child?;
|
||||
let child_type = child.file_type()?;
|
||||
if child_type.is_dir() {
|
||||
remove_dir_all_recursive(&child.path())?;
|
||||
} else if child_type.is_symlink_dir() {
|
||||
rmdir(&child.path())?;
|
||||
} else {
|
||||
unlink(&child.path())?;
|
||||
fn remove_dir_all_recursive(f: &File, delete: fn(&File) -> io::Result<()>) -> io::Result<()> {
|
||||
let mut buffer = DirBuff::new();
|
||||
let mut restart = true;
|
||||
// Fill the buffer and iterate the entries.
|
||||
while f.fill_dir_buff(&mut buffer, restart)? {
|
||||
for name in buffer.iter() {
|
||||
// Open the file without following symlinks and try deleting it.
|
||||
// We try opening will all needed permissions and if that is denied
|
||||
// fallback to opening without `FILE_LIST_DIRECTORY` permission.
|
||||
// Note `SYNCHRONIZE` permission is needed for synchronous access.
|
||||
let mut result =
|
||||
open_link_no_reparse(&f, name, c::SYNCHRONIZE | c::DELETE | c::FILE_LIST_DIRECTORY);
|
||||
if matches!(&result, Err(e) if e.kind() == io::ErrorKind::PermissionDenied) {
|
||||
result = open_link_no_reparse(&f, name, c::SYNCHRONIZE | c::DELETE);
|
||||
}
|
||||
match result {
|
||||
Ok(file) => match delete(&file) {
|
||||
Err(e) if e.kind() == io::ErrorKind::DirectoryNotEmpty => {
|
||||
// Iterate the directory's files.
|
||||
// Ignore `DirectoryNotEmpty` errors here. They will be
|
||||
// caught when `remove_dir_all` tries to delete the top
|
||||
// level directory. It can then decide if to retry or not.
|
||||
match remove_dir_all_recursive(&file, delete) {
|
||||
Err(e) if e.kind() == io::ErrorKind::DirectoryNotEmpty => {}
|
||||
result => result?,
|
||||
}
|
||||
}
|
||||
result => result?,
|
||||
},
|
||||
// Ignore error if a delete is already in progress or the file
|
||||
// has already been deleted. It also ignores sharing violations
|
||||
// (where a file is locked by another process) as these are
|
||||
// usually temporary.
|
||||
Err(e)
|
||||
if e.raw_os_error() == Some(c::ERROR_DELETE_PENDING as _)
|
||||
|| e.kind() == io::ErrorKind::NotFound
|
||||
|| e.raw_os_error() == Some(c::ERROR_SHARING_VIOLATION as _) => {}
|
||||
Err(e) => return Err(e),
|
||||
}
|
||||
}
|
||||
// Continue reading directory entries without restarting from the beginning,
|
||||
restart = false;
|
||||
}
|
||||
rmdir(path)
|
||||
delete(&f)
|
||||
}
|
||||
|
||||
pub fn readlink(path: &Path) -> io::Result<PathBuf> {
|
||||
|
|
|
|||
|
|
@ -150,16 +150,18 @@ pub enum RustBacktrace {
|
|||
RuntimeDisabled,
|
||||
}
|
||||
|
||||
// If the `backtrace` feature of this crate isn't enabled quickly return
|
||||
// `Disabled` so this can be constant propagated all over the place to
|
||||
// optimize away callers.
|
||||
#[cfg(not(feature = "backtrace"))]
|
||||
pub fn rust_backtrace_env() -> RustBacktrace {
|
||||
RustBacktrace::Disabled
|
||||
}
|
||||
|
||||
// For now logging is turned off by default, and this function checks to see
|
||||
// whether the magical environment variable is present to see if it's turned on.
|
||||
#[cfg(feature = "backtrace")]
|
||||
pub fn rust_backtrace_env() -> RustBacktrace {
|
||||
// If the `backtrace` feature of this crate isn't enabled quickly return
|
||||
// `None` so this can be constant propagated all over the place to turn
|
||||
// optimize away callers.
|
||||
if !cfg!(feature = "backtrace") {
|
||||
return RustBacktrace::Disabled;
|
||||
}
|
||||
|
||||
// Setting environment variables for Fuchsia components isn't a standard
|
||||
// or easily supported workflow. For now, always display backtraces.
|
||||
if cfg!(target_os = "fuchsia") {
|
||||
|
|
@ -189,6 +191,15 @@ pub fn rust_backtrace_env() -> RustBacktrace {
|
|||
format
|
||||
}
|
||||
|
||||
/// Setting for printing the full backtrace, unless backtraces are completely disabled
|
||||
pub(crate) fn rust_backtrace_print_full() -> RustBacktrace {
|
||||
if cfg!(feature = "backtrace") {
|
||||
RustBacktrace::Print(PrintFmt::Full)
|
||||
} else {
|
||||
RustBacktrace::Disabled
|
||||
}
|
||||
}
|
||||
|
||||
/// Prints the filename of the backtrace frame.
|
||||
///
|
||||
/// See also `output`.
|
||||
|
|
|
|||
|
|
@ -170,6 +170,12 @@ The valid types of print values are:
|
|||
include a diagnostic note that indicates the linker flags to use when
|
||||
linking the resulting static library. The note starts with the text
|
||||
`native-static-libs:` to make it easier to fetch the output.
|
||||
- `link-args` — This flag does not disable the `--emit` step. When linking,
|
||||
this flag causes `rustc` to print the full linker invocation in a
|
||||
human-readable form. This can be useful when debugging linker options. The
|
||||
exact format of this debugging output is not a stable guarantee, other than
|
||||
that it will include the linker executable and the text of each command-line
|
||||
argument passed to the linker.
|
||||
|
||||
[conditional compilation]: ../reference/conditional-compilation.html
|
||||
|
||||
|
|
|
|||
|
|
@ -1040,9 +1040,9 @@ impl Attributes {
|
|||
) -> Attributes {
|
||||
let mut doc_strings: Vec<DocFragment> = vec![];
|
||||
let clean_attr = |(attr, parent_module): (&ast::Attribute, Option<DefId>)| {
|
||||
if let Some(value) = attr.doc_str() {
|
||||
if let Some((value, kind)) = attr.doc_str_and_comment_kind() {
|
||||
trace!("got doc_str={:?}", value);
|
||||
let value = beautify_doc_string(value);
|
||||
let value = beautify_doc_string(value, kind);
|
||||
let kind = if attr.is_doc_comment() {
|
||||
DocFragmentKind::SugaredDoc
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -799,6 +799,20 @@ fn assoc_type(
|
|||
}
|
||||
}
|
||||
|
||||
/// Writes a span containing the versions at which an item became stable and/or const-stable. For
|
||||
/// example, if the item became stable at 1.0.0, and const-stable at 1.45.0, this function would
|
||||
/// write a span containing "1.0.0 (const: 1.45.0)".
|
||||
///
|
||||
/// Returns `true` if a stability annotation was rendered.
|
||||
///
|
||||
/// Stability and const-stability are considered separately. If the item is unstable, no version
|
||||
/// will be written. If the item is const-unstable, "const: unstable" will be appended to the
|
||||
/// span, with a link to the tracking issue if present. If an item's stability or const-stability
|
||||
/// version matches the version of its enclosing item, that version will be omitted.
|
||||
///
|
||||
/// Note that it is possible for an unstable function to be const-stable. In that case, the span
|
||||
/// will include the const-stable version, but no stable version will be emitted, as a natural
|
||||
/// consequence of the above rules.
|
||||
fn render_stability_since_raw(
|
||||
w: &mut Buffer,
|
||||
ver: Option<Symbol>,
|
||||
|
|
@ -806,51 +820,56 @@ fn render_stability_since_raw(
|
|||
containing_ver: Option<Symbol>,
|
||||
containing_const_ver: Option<Symbol>,
|
||||
) -> bool {
|
||||
let ver = ver.filter(|inner| !inner.is_empty());
|
||||
let stable_version = ver.filter(|inner| !inner.is_empty() && Some(*inner) != containing_ver);
|
||||
|
||||
match (ver, const_stability) {
|
||||
// stable and const stable
|
||||
(Some(v), Some(ConstStability { level: StabilityLevel::Stable { since }, .. }))
|
||||
let mut title = String::new();
|
||||
let mut stability = String::new();
|
||||
|
||||
if let Some(ver) = stable_version {
|
||||
stability.push_str(&ver.as_str());
|
||||
title.push_str(&format!("Stable since Rust version {}", ver));
|
||||
}
|
||||
|
||||
let const_title_and_stability = match const_stability {
|
||||
Some(ConstStability { level: StabilityLevel::Stable { since }, .. })
|
||||
if Some(since) != containing_const_ver =>
|
||||
{
|
||||
write!(
|
||||
w,
|
||||
"<span class=\"since\" title=\"Stable since Rust version {0}, const since {1}\">{0} (const: {1})</span>",
|
||||
v, since
|
||||
);
|
||||
Some((format!("const since {}", since), format!("const: {}", since)))
|
||||
}
|
||||
// stable and const unstable
|
||||
(
|
||||
Some(v),
|
||||
Some(ConstStability { level: StabilityLevel::Unstable { issue, .. }, feature, .. }),
|
||||
) => {
|
||||
write!(
|
||||
w,
|
||||
"<span class=\"since\" title=\"Stable since Rust version {0}, const unstable\">{0} (const: ",
|
||||
v
|
||||
);
|
||||
if let Some(n) = issue {
|
||||
write!(
|
||||
w,
|
||||
"<a href=\"https://github.com/rust-lang/rust/issues/{}\" title=\"Tracking issue for {}\">unstable</a>",
|
||||
Some(ConstStability { level: StabilityLevel::Unstable { issue, .. }, feature, .. }) => {
|
||||
let unstable = if let Some(n) = issue {
|
||||
format!(
|
||||
r#"<a href="https://github.com/rust-lang/rust/issues/{}" title="Tracking issue for {}">unstable</a>"#,
|
||||
n, feature
|
||||
);
|
||||
)
|
||||
} else {
|
||||
write!(w, "unstable");
|
||||
}
|
||||
write!(w, ")</span>");
|
||||
String::from("unstable")
|
||||
};
|
||||
|
||||
Some((String::from("const unstable"), format!("const: {}", unstable)))
|
||||
}
|
||||
// stable
|
||||
(Some(v), _) if ver != containing_ver => {
|
||||
write!(
|
||||
w,
|
||||
"<span class=\"since\" title=\"Stable since Rust version {0}\">{0}</span>",
|
||||
v
|
||||
);
|
||||
_ => None,
|
||||
};
|
||||
|
||||
if let Some((const_title, const_stability)) = const_title_and_stability {
|
||||
if !title.is_empty() {
|
||||
title.push_str(&format!(", {}", const_title));
|
||||
} else {
|
||||
title.push_str(&const_title);
|
||||
}
|
||||
|
||||
if !stability.is_empty() {
|
||||
stability.push_str(&format!(" ({})", const_stability));
|
||||
} else {
|
||||
stability.push_str(&const_stability);
|
||||
}
|
||||
_ => return false,
|
||||
}
|
||||
true
|
||||
|
||||
if !stability.is_empty() {
|
||||
write!(w, r#"<span class="since" title="{}">{}</span>"#, title, stability);
|
||||
}
|
||||
|
||||
!stability.is_empty()
|
||||
}
|
||||
|
||||
fn render_assoc_item(
|
||||
|
|
|
|||
|
|
@ -148,11 +148,11 @@ h1.fqn {
|
|||
}
|
||||
.main-heading {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
justify-content: space-between;
|
||||
border-bottom: 1px dashed #DDDDDD;
|
||||
padding-bottom: 6px;
|
||||
margin-bottom: 15px;
|
||||
|
||||
/* workaround to keep flex from breaking below 700 px width due to the float: right on the nav
|
||||
above the h1 */
|
||||
padding-left: 1px;
|
||||
}
|
||||
.main-heading a:hover {
|
||||
text-decoration: underline;
|
||||
|
|
@ -623,11 +623,7 @@ nav.sub {
|
|||
|
||||
.content .out-of-band {
|
||||
flex-grow: 0;
|
||||
text-align: right;
|
||||
margin-left: auto;
|
||||
margin-right: 0;
|
||||
font-size: 1.15rem;
|
||||
padding: 0 0 0 12px;
|
||||
font-weight: normal;
|
||||
float: right;
|
||||
}
|
||||
|
|
@ -1748,10 +1744,25 @@ details.rustdoc-toggle[open] > summary.hideme::after {
|
|||
padding-top: 0px;
|
||||
}
|
||||
|
||||
.rustdoc {
|
||||
.rustdoc,
|
||||
.main-heading {
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.content .out-of-band {
|
||||
text-align: left;
|
||||
margin-left: initial;
|
||||
padding: initial;
|
||||
}
|
||||
|
||||
.content .out-of-band .since::before {
|
||||
content: "Since ";
|
||||
}
|
||||
|
||||
#copy-path {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* Hide the logo and item name from the sidebar. Those are displayed
|
||||
in the mobile-topbar instead. */
|
||||
.sidebar .sidebar-logo,
|
||||
|
|
|
|||
|
|
@ -305,16 +305,15 @@ crate enum FragmentKind {
|
|||
|
||||
impl ItemFragment {
|
||||
/// Create a fragment for an associated item.
|
||||
///
|
||||
/// `is_prototype` is whether this associated item is a trait method
|
||||
/// without a default definition.
|
||||
fn from_assoc_item(def_id: DefId, kind: ty::AssocKind, is_prototype: bool) -> Self {
|
||||
match kind {
|
||||
#[instrument(level = "debug")]
|
||||
fn from_assoc_item(item: &ty::AssocItem) -> Self {
|
||||
let def_id = item.def_id;
|
||||
match item.kind {
|
||||
ty::AssocKind::Fn => {
|
||||
if is_prototype {
|
||||
ItemFragment(FragmentKind::TyMethod, def_id)
|
||||
} else {
|
||||
if item.defaultness.has_value() {
|
||||
ItemFragment(FragmentKind::Method, def_id)
|
||||
} else {
|
||||
ItemFragment(FragmentKind::TyMethod, def_id)
|
||||
}
|
||||
}
|
||||
ty::AssocKind::Const => ItemFragment(FragmentKind::AssociatedConstant, def_id),
|
||||
|
|
@ -473,8 +472,7 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
|
|||
tcx.associated_items(impl_)
|
||||
.find_by_name_and_namespace(tcx, Ident::with_dummy_span(item_name), ns, impl_)
|
||||
.map(|item| {
|
||||
let kind = item.kind;
|
||||
let fragment = ItemFragment::from_assoc_item(item.def_id, kind, false);
|
||||
let fragment = ItemFragment::from_assoc_item(item);
|
||||
(Res::Primitive(prim_ty), fragment)
|
||||
})
|
||||
})
|
||||
|
|
@ -726,8 +724,7 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
|
|||
.flatten();
|
||||
|
||||
assoc_item.map(|item| {
|
||||
let kind = item.kind;
|
||||
let fragment = ItemFragment::from_assoc_item(item.def_id, kind, false);
|
||||
let fragment = ItemFragment::from_assoc_item(&item);
|
||||
(root_res, fragment)
|
||||
})
|
||||
})
|
||||
|
|
@ -765,20 +762,19 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
|
|||
// To handle that properly resolve() would have to support
|
||||
// something like [`ambi_fn`](<SomeStruct as SomeTrait>::ambi_fn)
|
||||
.or_else(|| {
|
||||
let item = resolve_associated_trait_item(
|
||||
resolve_associated_trait_item(
|
||||
tcx.type_of(did),
|
||||
module_id,
|
||||
item_name,
|
||||
ns,
|
||||
self.cx,
|
||||
);
|
||||
debug!("got associated item {:?}", item);
|
||||
item
|
||||
)
|
||||
});
|
||||
|
||||
debug!("got associated item {:?}", assoc_item);
|
||||
|
||||
if let Some(item) = assoc_item {
|
||||
let kind = item.kind;
|
||||
let fragment = ItemFragment::from_assoc_item(item.def_id, kind, false);
|
||||
let fragment = ItemFragment::from_assoc_item(&item);
|
||||
return Some((root_res, fragment));
|
||||
}
|
||||
|
||||
|
|
@ -813,11 +809,7 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
|
|||
.associated_items(did)
|
||||
.find_by_name_and_namespace(tcx, Ident::with_dummy_span(item_name), ns, did)
|
||||
.map(|item| {
|
||||
let fragment = ItemFragment::from_assoc_item(
|
||||
item.def_id,
|
||||
item.kind,
|
||||
!item.defaultness.has_value(),
|
||||
);
|
||||
let fragment = ItemFragment::from_assoc_item(item);
|
||||
let res = Res::Def(item.kind.as_def_kind(), item.def_id);
|
||||
(res, fragment)
|
||||
}),
|
||||
|
|
@ -883,30 +875,56 @@ fn resolve_associated_trait_item<'a>(
|
|||
|
||||
// Next consider explicit impls: `impl MyTrait for MyType`
|
||||
// Give precedence to inherent impls.
|
||||
let traits = traits_implemented_by(cx, ty, module);
|
||||
let traits = trait_impls_for(cx, ty, module);
|
||||
debug!("considering traits {:?}", traits);
|
||||
let mut candidates = traits.iter().filter_map(|&trait_| {
|
||||
cx.tcx.associated_items(trait_).find_by_name_and_namespace(
|
||||
cx.tcx,
|
||||
Ident::with_dummy_span(item_name),
|
||||
ns,
|
||||
trait_,
|
||||
)
|
||||
let mut candidates = traits.iter().filter_map(|&(impl_, trait_)| {
|
||||
cx.tcx
|
||||
.associated_items(trait_)
|
||||
.find_by_name_and_namespace(cx.tcx, Ident::with_dummy_span(item_name), ns, trait_)
|
||||
.map(|trait_assoc| {
|
||||
trait_assoc_to_impl_assoc_item(cx.tcx, impl_, trait_assoc.def_id)
|
||||
.unwrap_or(trait_assoc)
|
||||
})
|
||||
});
|
||||
// FIXME(#74563): warn about ambiguity
|
||||
debug!("the candidates were {:?}", candidates.clone().collect::<Vec<_>>());
|
||||
candidates.next().copied()
|
||||
}
|
||||
|
||||
/// Given a type, return all traits in scope in `module` implemented by that type.
|
||||
/// Find the associated item in the impl `impl_id` that corresponds to the
|
||||
/// trait associated item `trait_assoc_id`.
|
||||
///
|
||||
/// This function returns `None` if no associated item was found in the impl.
|
||||
/// This can occur when the trait associated item has a default value that is
|
||||
/// not overriden in the impl.
|
||||
///
|
||||
/// This is just a wrapper around [`TyCtxt::impl_item_implementor_ids()`] and
|
||||
/// [`TyCtxt::associated_item()`] (with some helpful logging added).
|
||||
#[instrument(level = "debug", skip(tcx))]
|
||||
fn trait_assoc_to_impl_assoc_item<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
impl_id: DefId,
|
||||
trait_assoc_id: DefId,
|
||||
) -> Option<&'tcx ty::AssocItem> {
|
||||
let trait_to_impl_assoc_map = tcx.impl_item_implementor_ids(impl_id);
|
||||
debug!(?trait_to_impl_assoc_map);
|
||||
let impl_assoc_id = *trait_to_impl_assoc_map.get(&trait_assoc_id)?;
|
||||
debug!(?impl_assoc_id);
|
||||
let impl_assoc = tcx.associated_item(impl_assoc_id);
|
||||
debug!(?impl_assoc);
|
||||
Some(impl_assoc)
|
||||
}
|
||||
|
||||
/// Given a type, return all trait impls in scope in `module` for that type.
|
||||
/// Returns a set of pairs of `(impl_id, trait_id)`.
|
||||
///
|
||||
/// NOTE: this cannot be a query because more traits could be available when more crates are compiled!
|
||||
/// So it is not stable to serialize cross-crate.
|
||||
fn traits_implemented_by<'a>(
|
||||
fn trait_impls_for<'a>(
|
||||
cx: &mut DocContext<'a>,
|
||||
ty: Ty<'a>,
|
||||
module: DefId,
|
||||
) -> FxHashSet<DefId> {
|
||||
) -> FxHashSet<(DefId, DefId)> {
|
||||
let mut resolver = cx.resolver.borrow_mut();
|
||||
let in_scope_traits = cx.module_trait_cache.entry(module).or_insert_with(|| {
|
||||
resolver.access(|resolver| {
|
||||
|
|
@ -948,7 +966,7 @@ fn traits_implemented_by<'a>(
|
|||
_ => false,
|
||||
};
|
||||
|
||||
if saw_impl { Some(trait_) } else { None }
|
||||
if saw_impl { Some((impl_, trait_)) } else { None }
|
||||
})
|
||||
});
|
||||
iter.collect()
|
||||
|
|
|
|||
|
|
@ -24,8 +24,8 @@ all:
|
|||
$(RUSTC) -C lto dummy.rs
|
||||
|
||||
# Should not link dead code...
|
||||
$(RUSTC) -Z print-link-args dummy.rs 2>&1 | \
|
||||
$(RUSTC) --print link-args dummy.rs 2>&1 | \
|
||||
$(CGREP) -e '--gc-sections|-z[^ ]* [^ ]*<ignore>|-dead_strip|/OPT:REF'
|
||||
# ... unless you specifically ask to keep it
|
||||
$(RUSTC) -Z print-link-args -C link-dead-code dummy.rs 2>&1 | \
|
||||
$(RUSTC) --print link-args -C link-dead-code dummy.rs 2>&1 | \
|
||||
$(CGREP) -ve '--gc-sections|-z[^ ]* [^ ]*<ignore>|-dead_strip|/OPT:REF'
|
||||
|
|
|
|||
|
|
@ -11,4 +11,4 @@
|
|||
all: $(call NATIVE_STATICLIB,foo) $(call NATIVE_STATICLIB,bar)
|
||||
$(RUSTC) foo.rs
|
||||
$(RUSTC) bar.rs
|
||||
$(RUSTC) main.rs -Z print-link-args
|
||||
$(RUSTC) main.rs --print link-args
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
-include ../tools.mk
|
||||
RUSTC_FLAGS = -C link-arg="-lfoo" -C link-arg="-lbar" -Z print-link-args
|
||||
RUSTC_FLAGS = -C link-arg="-lfoo" -C link-arg="-lbar" --print link-args
|
||||
|
||||
all:
|
||||
$(RUSTC) $(RUSTC_FLAGS) empty.rs | $(CGREP) lfoo lbar
|
||||
|
|
|
|||
|
|
@ -6,5 +6,5 @@ all:
|
|||
$(RUSTC) bar.rs \
|
||||
--extern foo1=$(TMPDIR)/libfoo-a.rlib \
|
||||
--extern foo2=$(TMPDIR)/libfoo-b.rlib \
|
||||
-Z print-link-args
|
||||
--print link-args
|
||||
$(call RUN,bar)
|
||||
|
|
|
|||
|
|
@ -6,4 +6,4 @@ all:
|
|||
# Build an executable that depends on that crate using LTO. The no_builtins crate doesn't
|
||||
# participate in LTO, so its rlib must be explicitly linked into the final binary. Verify this by
|
||||
# grepping the linker arguments.
|
||||
$(RUSTC) main.rs -C lto -Z print-link-args | $(CGREP) 'libno_builtins.rlib'
|
||||
$(RUSTC) main.rs -C lto --print link-args | $(CGREP) 'libno_builtins.rlib'
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ RUSTC_FLAGS = \
|
|||
-l foo \
|
||||
-l static=baz \
|
||||
-l foo \
|
||||
-Z print-link-args
|
||||
--print link-args
|
||||
|
||||
all: $(call DYLIB,foo) $(call STATICLIB,bar) $(call STATICLIB,baz)
|
||||
$(RUSTC) $(RUSTC_FLAGS) main.rs
|
||||
|
|
|
|||
|
|
@ -13,9 +13,9 @@ all: $(call NATIVE_STATICLIB,aaa)
|
|||
nm $(TMPDIR)/libbbb.rlib | $(CGREP) -e "U _*native_func"
|
||||
|
||||
# Check that aaa gets linked (either as `-l aaa` or `aaa.lib`) when building ccc.
|
||||
$(RUSTC) ccc.rs -C prefer-dynamic --crate-type=dylib -Z print-link-args | $(CGREP) -e '-l[" ]*aaa|aaa\.lib'
|
||||
$(RUSTC) ccc.rs -C prefer-dynamic --crate-type=dylib --print link-args | $(CGREP) -e '-l[" ]*aaa|aaa\.lib'
|
||||
|
||||
# Check that aaa does NOT get linked when building ddd.
|
||||
$(RUSTC) ddd.rs -Z print-link-args | $(CGREP) -ve '-l[" ]*aaa|aaa\.lib'
|
||||
$(RUSTC) ddd.rs --print link-args | $(CGREP) -ve '-l[" ]*aaa|aaa\.lib'
|
||||
|
||||
$(call RUN,ddd)
|
||||
|
|
|
|||
17
src/test/rustdoc-gui/mobile.goml
Normal file
17
src/test/rustdoc-gui/mobile.goml
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
// Test various properties of the mobile UI
|
||||
goto: file://|DOC_PATH|/staged_api/struct.Foo.html
|
||||
size: (400, 600)
|
||||
|
||||
// The out-of-band info (source, stable version, collapse) should be below the
|
||||
// h1 when the screen gets narrow enough.
|
||||
assert-css: (".main-heading", {
|
||||
"display": "flex",
|
||||
"flex-direction": "column"
|
||||
})
|
||||
|
||||
// Note: We can't use assert-text here because the 'Since' is set by CSS and
|
||||
// is therefore not part of the DOM.
|
||||
assert-css: (".content .out-of-band .since::before", { "content": "\"Since \"" })
|
||||
|
||||
size: (1000, 1000)
|
||||
assert-css-false: (".content .out-of-band .since::before", { "content": "\"Since \"" })
|
||||
|
|
@ -1,12 +1,12 @@
|
|||
goto: file://|DOC_PATH|/test_docs/struct.Foo.html
|
||||
size: (433, 600)
|
||||
assert-attribute: (".top-doc", {"open": ""})
|
||||
click: (4, 250) // This is the position of the top doc comment toggle
|
||||
click: (4, 270) // This is the position of the top doc comment toggle
|
||||
assert-attribute-false: (".top-doc", {"open": ""})
|
||||
click: (4, 250)
|
||||
click: (4, 270)
|
||||
assert-attribute: (".top-doc", {"open": ""})
|
||||
// To ensure that the toggle isn't over the text, we check that the toggle isn't clicked.
|
||||
click: (3, 250)
|
||||
click: (3, 270)
|
||||
assert-attribute: (".top-doc", {"open": ""})
|
||||
|
||||
// Assert the position of the toggle on the top doc block.
|
||||
|
|
@ -22,10 +22,10 @@ assert-position: (
|
|||
// Now we do the same but with a little bigger width
|
||||
size: (600, 600)
|
||||
assert-attribute: (".top-doc", {"open": ""})
|
||||
click: (4, 250) // New Y position since all search elements are back on one line.
|
||||
click: (4, 270) // New Y position since all search elements are back on one line.
|
||||
assert-attribute-false: (".top-doc", {"open": ""})
|
||||
click: (4, 250)
|
||||
click: (4, 270)
|
||||
assert-attribute: (".top-doc", {"open": ""})
|
||||
// To ensure that the toggle isn't over the text, we check that the toggle isn't clicked.
|
||||
click: (3, 250)
|
||||
click: (3, 270)
|
||||
assert-attribute: (".top-doc", {"open": ""})
|
||||
|
|
|
|||
|
|
@ -67,3 +67,20 @@ impl Foo {
|
|||
#[rustc_const_stable(feature = "rust1", since = "1.2.0")]
|
||||
pub const fn stable_impl() -> u32 { 42 }
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub struct Bar;
|
||||
|
||||
impl Bar {
|
||||
// Do not show non-const stabilities that are the same as the enclosing item.
|
||||
// @matches 'foo/struct.Bar.html' '//span[@class="since"]' '^const: 1.2.0$'
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[rustc_const_stable(feature = "rust1", since = "1.2.0")]
|
||||
pub const fn stable_impl() -> u32 { 42 }
|
||||
|
||||
// Show const-stability even for unstable functions.
|
||||
// @matches 'foo/struct.Bar.html' '//span[@class="since"]' '^const: 1.3.0$'
|
||||
#[unstable(feature = "foo2", issue = "none")]
|
||||
#[rustc_const_stable(feature = "rust1", since = "1.3.0")]
|
||||
pub const fn const_stable_unstable() -> u32 { 42 }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ pub struct Bar;
|
|||
|
||||
impl Bar {
|
||||
// @has - '//*[@id="method.len"]' 'pub const fn len(&self) -> usize'
|
||||
// @has - '//*[@id="method.len"]//span[@class="since"]' '1.0.0 (const: 1.0.0)'
|
||||
// @has - '//*[@id="method.len"]//span[@class="since"]' 'const: 1.0.0'
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[rustc_const_stable(feature = "rust1", since = "1.0.0")]
|
||||
pub const fn len(&self) -> usize { 0 }
|
||||
|
|
|
|||
|
|
@ -0,0 +1,2 @@
|
|||
<div class="docblock"><p>a</p>
|
||||
</div>
|
||||
11
src/test/rustdoc/strip-block-doc-comments-stars.rs
Normal file
11
src/test/rustdoc/strip-block-doc-comments-stars.rs
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
#![crate_name = "foo"]
|
||||
|
||||
// The goal of this test is to answer that it won't be generated as a list because
|
||||
// block doc comments can have their lines starting with a star.
|
||||
|
||||
// @has foo/fn.foo.html
|
||||
// @snapshot docblock - '//*[@class="rustdoc-toggle top-doc"]//*[@class="docblock"]'
|
||||
/**
|
||||
* a
|
||||
*/
|
||||
pub fn foo() {}
|
||||
|
|
@ -2,23 +2,17 @@ error[E0623]: lifetime mismatch
|
|||
--> $DIR/issue-76547.rs:20:13
|
||||
|
|
||||
LL | async fn fut(bufs: &mut [&mut [u8]]) {
|
||||
| --------- -
|
||||
| | |
|
||||
| | this `async fn` implicitly returns an `impl Future<Output = ()>`
|
||||
| this parameter and the returned future are declared with different lifetimes...
|
||||
| ---------------- these two types are declared with different lifetimes...
|
||||
LL | ListFut(bufs).await
|
||||
| ^^^^ ...but data from `bufs` is held across an await point here
|
||||
| ^^^^ ...but data from `bufs` flows into `bufs` here
|
||||
|
||||
error[E0623]: lifetime mismatch
|
||||
--> $DIR/issue-76547.rs:34:14
|
||||
|
|
||||
LL | async fn fut2(bufs: &mut [&mut [u8]]) -> i32 {
|
||||
| --------- ---
|
||||
| | |
|
||||
| | this `async fn` implicitly returns an `impl Future<Output = i32>`
|
||||
| this parameter and the returned future are declared with different lifetimes...
|
||||
| ---------------- these two types are declared with different lifetimes...
|
||||
LL | ListFut2(bufs).await
|
||||
| ^^^^ ...but data from `bufs` is held across an await point here
|
||||
| ^^^^ ...but data from `bufs` flows into `bufs` here
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
|
|
|
|||
|
|
@ -2,14 +2,12 @@ error[E0623]: lifetime mismatch
|
|||
--> $DIR/issue-63388-1.rs:14:9
|
||||
|
|
||||
LL | &'a self, foo: &dyn Foo
|
||||
| -------- this parameter and the returned future are declared with different lifetimes...
|
||||
| -------- this parameter and the return type are declared with different lifetimes...
|
||||
LL | ) -> &dyn Foo
|
||||
| --------
|
||||
| |
|
||||
| this `async fn` implicitly returns an `impl Future<Output = &dyn Foo>`
|
||||
LL | {
|
||||
LL | foo
|
||||
| ^^^ ...but data from `foo` is held across an await point here
|
||||
| ^^^ ...but data from `foo` is returned here
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
|
|
|||
|
|
@ -4,9 +4,8 @@ error[E0623]: lifetime mismatch
|
|||
LL | async fn async_ret_impl_trait3<'a, 'b>(a: &'a u8, b: &'b u8) -> impl Trait<'a> + 'b {
|
||||
| ------ ^^^^^^^^^^^^^^^^^^^
|
||||
| | |
|
||||
| | ...but data from `a` is held across an await point here
|
||||
| | this `async fn` implicitly returns an `impl Future<Output = impl Trait<'a> + 'b>`
|
||||
| this parameter and the returned future are declared with different lifetimes...
|
||||
| | ...but data from `a` is returned here
|
||||
| this parameter and the return type are declared with different lifetimes...
|
||||
|
||||
error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds
|
||||
--> $DIR/ret-impl-trait-one.rs:16:65
|
||||
|
|
|
|||
|
|
@ -1,12 +0,0 @@
|
|||
// To avoid having to `or` gate `_` as an expr.
|
||||
#![feature(generic_arg_infer)]
|
||||
|
||||
fn foo() -> [u8; _] {
|
||||
//~^ ERROR the const placeholder `_` is not allowed within types on item signatures for generics
|
||||
// FIXME(generic_arg_infer): this error message should say in the return type or sth like that.
|
||||
[0; 3]
|
||||
}
|
||||
|
||||
fn main() {
|
||||
foo();
|
||||
}
|
||||
|
|
@ -1,9 +0,0 @@
|
|||
error[E0121]: the const placeholder `_` is not allowed within types on item signatures for generics
|
||||
--> $DIR/array-in-sig.rs:4:18
|
||||
|
|
||||
LL | fn foo() -> [u8; _] {
|
||||
| ^ not allowed in type signatures
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0121`.
|
||||
61
src/test/ui/const-generics/generic_arg_infer/in-signature.rs
Normal file
61
src/test/ui/const-generics/generic_arg_infer/in-signature.rs
Normal file
|
|
@ -0,0 +1,61 @@
|
|||
#![crate_type = "rlib"]
|
||||
#![feature(generic_arg_infer)]
|
||||
|
||||
struct Foo<const N: usize>;
|
||||
struct Bar<T, const N: usize>(T);
|
||||
|
||||
fn arr_fn() -> [u8; _] {
|
||||
//~^ ERROR the placeholder `_` is not allowed within types on item signatures for return types
|
||||
[0; 3]
|
||||
}
|
||||
|
||||
fn ty_fn() -> Bar<i32, _> {
|
||||
//~^ ERROR the placeholder `_` is not allowed within types on item signatures for return types
|
||||
Bar::<i32, 3>(0)
|
||||
}
|
||||
|
||||
fn ty_fn_mixed() -> Bar<_, _> {
|
||||
//~^ ERROR the placeholder `_` is not allowed within types on item signatures for return types
|
||||
Bar::<i32, 3>(0)
|
||||
}
|
||||
|
||||
const ARR_CT: [u8; _] = [0; 3];
|
||||
//~^ ERROR the placeholder `_` is not allowed within types on item signatures for constants
|
||||
static ARR_STATIC: [u8; _] = [0; 3];
|
||||
//~^ ERROR the placeholder `_` is not allowed within types on item signatures for static variables
|
||||
const TY_CT: Bar<i32, _> = Bar::<i32, 3>(0);
|
||||
//~^ ERROR the placeholder `_` is not allowed within types on item signatures for constants
|
||||
static TY_STATIC: Bar<i32, _> = Bar::<i32, 3>(0);
|
||||
//~^ ERROR the placeholder `_` is not allowed within types on item signatures for static variables
|
||||
const TY_CT_MIXED: Bar<_, _> = Bar::<i32, 3>(0);
|
||||
//~^ ERROR the placeholder `_` is not allowed within types on item signatures for constants
|
||||
static TY_STATIC_MIXED: Bar<_, _> = Bar::<i32, 3>(0);
|
||||
//~^ ERROR the placeholder `_` is not allowed within types on item signatures for static variables
|
||||
trait ArrAssocConst {
|
||||
const ARR: [u8; _];
|
||||
//~^ ERROR the placeholder `_` is not allowed within types on item signatures for constants
|
||||
}
|
||||
trait TyAssocConst {
|
||||
const ARR: Bar<i32, _>;
|
||||
//~^ ERROR the placeholder `_` is not allowed within types on item signatures for constants
|
||||
}
|
||||
trait TyAssocConstMixed {
|
||||
const ARR: Bar<_, _>;
|
||||
//~^ ERROR the placeholder `_` is not allowed within types on item signatures for constants
|
||||
}
|
||||
|
||||
trait AssocTy {
|
||||
type Assoc;
|
||||
}
|
||||
impl AssocTy for i8 {
|
||||
type Assoc = [u8; _];
|
||||
//~^ ERROR the placeholder `_` is not allowed within types on item signatures for associated types
|
||||
}
|
||||
impl AssocTy for i16 {
|
||||
type Assoc = Bar<i32, _>;
|
||||
//~^ ERROR the placeholder `_` is not allowed within types on item signatures for associated types
|
||||
}
|
||||
impl AssocTy for i32 {
|
||||
type Assoc = Bar<_, _>;
|
||||
//~^ ERROR the placeholder `_` is not allowed within types on item signatures for associated types
|
||||
}
|
||||
119
src/test/ui/const-generics/generic_arg_infer/in-signature.stderr
Normal file
119
src/test/ui/const-generics/generic_arg_infer/in-signature.stderr
Normal file
|
|
@ -0,0 +1,119 @@
|
|||
error[E0121]: the placeholder `_` is not allowed within types on item signatures for return types
|
||||
--> $DIR/in-signature.rs:7:21
|
||||
|
|
||||
LL | fn arr_fn() -> [u8; _] {
|
||||
| -----^-
|
||||
| | |
|
||||
| | not allowed in type signatures
|
||||
| help: replace with the correct return type: `[u8; 3]`
|
||||
|
||||
error[E0121]: the placeholder `_` is not allowed within types on item signatures for return types
|
||||
--> $DIR/in-signature.rs:12:24
|
||||
|
|
||||
LL | fn ty_fn() -> Bar<i32, _> {
|
||||
| ---------^-
|
||||
| | |
|
||||
| | not allowed in type signatures
|
||||
| help: replace with the correct return type: `Bar<i32, 3_usize>`
|
||||
|
||||
error[E0121]: the placeholder `_` is not allowed within types on item signatures for return types
|
||||
--> $DIR/in-signature.rs:17:25
|
||||
|
|
||||
LL | fn ty_fn_mixed() -> Bar<_, _> {
|
||||
| ----^--^-
|
||||
| | | |
|
||||
| | | not allowed in type signatures
|
||||
| | not allowed in type signatures
|
||||
| help: replace with the correct return type: `Bar<i32, 3_usize>`
|
||||
|
||||
error[E0121]: the placeholder `_` is not allowed within types on item signatures for constants
|
||||
--> $DIR/in-signature.rs:22:15
|
||||
|
|
||||
LL | const ARR_CT: [u8; _] = [0; 3];
|
||||
| ^^^^^^^ not allowed in type signatures
|
||||
|
||||
error[E0121]: the placeholder `_` is not allowed within types on item signatures for static variables
|
||||
--> $DIR/in-signature.rs:24:20
|
||||
|
|
||||
LL | static ARR_STATIC: [u8; _] = [0; 3];
|
||||
| ^^^^^^^ not allowed in type signatures
|
||||
|
||||
error[E0121]: the placeholder `_` is not allowed within types on item signatures for constants
|
||||
--> $DIR/in-signature.rs:26:14
|
||||
|
|
||||
LL | const TY_CT: Bar<i32, _> = Bar::<i32, 3>(0);
|
||||
| ^^^^^^^^^^^
|
||||
| |
|
||||
| not allowed in type signatures
|
||||
| help: replace with the correct type: `Bar<i32, 3_usize>`
|
||||
|
||||
error[E0121]: the placeholder `_` is not allowed within types on item signatures for static variables
|
||||
--> $DIR/in-signature.rs:28:19
|
||||
|
|
||||
LL | static TY_STATIC: Bar<i32, _> = Bar::<i32, 3>(0);
|
||||
| ^^^^^^^^^^^
|
||||
| |
|
||||
| not allowed in type signatures
|
||||
| help: replace with the correct type: `Bar<i32, 3_usize>`
|
||||
|
||||
error[E0121]: the placeholder `_` is not allowed within types on item signatures for constants
|
||||
--> $DIR/in-signature.rs:30:20
|
||||
|
|
||||
LL | const TY_CT_MIXED: Bar<_, _> = Bar::<i32, 3>(0);
|
||||
| ^^^^^^^^^
|
||||
| |
|
||||
| not allowed in type signatures
|
||||
| help: replace with the correct type: `Bar<i32, 3_usize>`
|
||||
|
||||
error[E0121]: the placeholder `_` is not allowed within types on item signatures for static variables
|
||||
--> $DIR/in-signature.rs:32:25
|
||||
|
|
||||
LL | static TY_STATIC_MIXED: Bar<_, _> = Bar::<i32, 3>(0);
|
||||
| ^^^^^^^^^
|
||||
| |
|
||||
| not allowed in type signatures
|
||||
| help: replace with the correct type: `Bar<i32, 3_usize>`
|
||||
|
||||
error[E0121]: the placeholder `_` is not allowed within types on item signatures for constants
|
||||
--> $DIR/in-signature.rs:35:21
|
||||
|
|
||||
LL | const ARR: [u8; _];
|
||||
| ^ not allowed in type signatures
|
||||
|
||||
error[E0121]: the placeholder `_` is not allowed within types on item signatures for constants
|
||||
--> $DIR/in-signature.rs:39:25
|
||||
|
|
||||
LL | const ARR: Bar<i32, _>;
|
||||
| ^ not allowed in type signatures
|
||||
|
||||
error[E0121]: the placeholder `_` is not allowed within types on item signatures for constants
|
||||
--> $DIR/in-signature.rs:43:20
|
||||
|
|
||||
LL | const ARR: Bar<_, _>;
|
||||
| ^ ^ not allowed in type signatures
|
||||
| |
|
||||
| not allowed in type signatures
|
||||
|
||||
error[E0121]: the placeholder `_` is not allowed within types on item signatures for associated types
|
||||
--> $DIR/in-signature.rs:51:23
|
||||
|
|
||||
LL | type Assoc = [u8; _];
|
||||
| ^ not allowed in type signatures
|
||||
|
||||
error[E0121]: the placeholder `_` is not allowed within types on item signatures for associated types
|
||||
--> $DIR/in-signature.rs:55:27
|
||||
|
|
||||
LL | type Assoc = Bar<i32, _>;
|
||||
| ^ not allowed in type signatures
|
||||
|
||||
error[E0121]: the placeholder `_` is not allowed within types on item signatures for associated types
|
||||
--> $DIR/in-signature.rs:59:22
|
||||
|
|
||||
LL | type Assoc = Bar<_, _>;
|
||||
| ^ ^ not allowed in type signatures
|
||||
| |
|
||||
| not allowed in type signatures
|
||||
|
||||
error: aborting due to 15 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0121`.
|
||||
|
|
@ -16,7 +16,7 @@ type D = (u8, u8)::AssocTy;
|
|||
|
||||
type E = _::AssocTy;
|
||||
//~^ ERROR missing angle brackets in associated item path
|
||||
//~| ERROR the type placeholder `_` is not allowed within types on item signatures for type aliases
|
||||
//~| ERROR the placeholder `_` is not allowed within types on item signatures for type aliases
|
||||
|
||||
type F = &'static (u8)::AssocTy;
|
||||
//~^ ERROR missing angle brackets in associated item path
|
||||
|
|
@ -49,37 +49,37 @@ type I = ty!()::AssocTy;
|
|||
|
||||
trait K<A, B> {}
|
||||
fn foo<X: K<_, _>>(x: X) {}
|
||||
//~^ ERROR the type placeholder `_` is not allowed within types on item signatures for functions
|
||||
//~^ ERROR the placeholder `_` is not allowed within types on item signatures for functions
|
||||
|
||||
fn bar<F>(_: F) where F: Fn() -> _ {}
|
||||
//~^ ERROR the type placeholder `_` is not allowed within types on item signatures for functions
|
||||
//~^ ERROR the placeholder `_` is not allowed within types on item signatures for functions
|
||||
|
||||
fn baz<F: Fn() -> _>(_: F) {}
|
||||
//~^ ERROR the type placeholder `_` is not allowed within types on item signatures for functions
|
||||
//~^ ERROR the placeholder `_` is not allowed within types on item signatures for functions
|
||||
|
||||
struct L<F>(F) where F: Fn() -> _;
|
||||
//~^ ERROR the type placeholder `_` is not allowed within types on item signatures for structs
|
||||
//~^ ERROR the placeholder `_` is not allowed within types on item signatures for structs
|
||||
struct M<F> where F: Fn() -> _ {
|
||||
//~^ ERROR the type placeholder `_` is not allowed within types on item signatures for structs
|
||||
//~^ ERROR the placeholder `_` is not allowed within types on item signatures for structs
|
||||
a: F,
|
||||
}
|
||||
enum N<F> where F: Fn() -> _ {
|
||||
//~^ ERROR the type placeholder `_` is not allowed within types on item signatures for enums
|
||||
//~^ ERROR the placeholder `_` is not allowed within types on item signatures for enums
|
||||
Foo(F),
|
||||
}
|
||||
|
||||
union O<F> where F: Fn() -> _ {
|
||||
//~^ ERROR the type placeholder `_` is not allowed within types on item signatures for unions
|
||||
//~^ ERROR the placeholder `_` is not allowed within types on item signatures for unions
|
||||
foo: F,
|
||||
}
|
||||
|
||||
trait P<F> where F: Fn() -> _ {
|
||||
//~^ ERROR the type placeholder `_` is not allowed within types on item signatures for traits
|
||||
//~^ ERROR the placeholder `_` is not allowed within types on item signatures for traits
|
||||
}
|
||||
|
||||
trait Q {
|
||||
fn foo<F>(_: F) where F: Fn() -> _ {}
|
||||
//~^ ERROR the type placeholder `_` is not allowed within types on item signatures for functions
|
||||
//~^ ERROR the placeholder `_` is not allowed within types on item signatures for functions
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
|
|
|||
|
|
@ -81,7 +81,7 @@ error[E0223]: ambiguous associated type
|
|||
LL | type D = (u8, u8)::AssocTy;
|
||||
| ^^^^^^^^^^^^^^^^^ help: use fully-qualified syntax: `<(u8, u8) as Trait>::AssocTy`
|
||||
|
||||
error[E0121]: the type placeholder `_` is not allowed within types on item signatures for type aliases
|
||||
error[E0121]: the placeholder `_` is not allowed within types on item signatures for type aliases
|
||||
--> $DIR/bad-assoc-ty.rs:17:10
|
||||
|
|
||||
LL | type E = _::AssocTy;
|
||||
|
|
@ -136,7 +136,7 @@ error[E0223]: ambiguous associated type
|
|||
LL | type I = ty!()::AssocTy;
|
||||
| ^^^^^^^^^^^^^^ help: use fully-qualified syntax: `<u8 as Trait>::AssocTy`
|
||||
|
||||
error[E0121]: the type placeholder `_` is not allowed within types on item signatures for functions
|
||||
error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions
|
||||
--> $DIR/bad-assoc-ty.rs:51:13
|
||||
|
|
||||
LL | fn foo<X: K<_, _>>(x: X) {}
|
||||
|
|
@ -149,7 +149,7 @@ help: use type parameters instead
|
|||
LL | fn foo<X: K<T, T>, T>(x: X) {}
|
||||
| ~ ~ +++
|
||||
|
||||
error[E0121]: the type placeholder `_` is not allowed within types on item signatures for functions
|
||||
error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions
|
||||
--> $DIR/bad-assoc-ty.rs:54:34
|
||||
|
|
||||
LL | fn bar<F>(_: F) where F: Fn() -> _ {}
|
||||
|
|
@ -160,7 +160,7 @@ help: use type parameters instead
|
|||
LL | fn bar<F, T>(_: F) where F: Fn() -> T {}
|
||||
| +++ ~
|
||||
|
||||
error[E0121]: the type placeholder `_` is not allowed within types on item signatures for functions
|
||||
error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions
|
||||
--> $DIR/bad-assoc-ty.rs:57:19
|
||||
|
|
||||
LL | fn baz<F: Fn() -> _>(_: F) {}
|
||||
|
|
@ -171,7 +171,7 @@ help: use type parameters instead
|
|||
LL | fn baz<F: Fn() -> T, T>(_: F) {}
|
||||
| ~+++
|
||||
|
||||
error[E0121]: the type placeholder `_` is not allowed within types on item signatures for structs
|
||||
error[E0121]: the placeholder `_` is not allowed within types on item signatures for structs
|
||||
--> $DIR/bad-assoc-ty.rs:60:33
|
||||
|
|
||||
LL | struct L<F>(F) where F: Fn() -> _;
|
||||
|
|
@ -182,7 +182,7 @@ help: use type parameters instead
|
|||
LL | struct L<F, T>(F) where F: Fn() -> T;
|
||||
| +++ ~
|
||||
|
||||
error[E0121]: the type placeholder `_` is not allowed within types on item signatures for structs
|
||||
error[E0121]: the placeholder `_` is not allowed within types on item signatures for structs
|
||||
--> $DIR/bad-assoc-ty.rs:62:30
|
||||
|
|
||||
LL | struct M<F> where F: Fn() -> _ {
|
||||
|
|
@ -193,7 +193,7 @@ help: use type parameters instead
|
|||
LL | struct M<F, T> where F: Fn() -> T {
|
||||
| +++ ~
|
||||
|
||||
error[E0121]: the type placeholder `_` is not allowed within types on item signatures for enums
|
||||
error[E0121]: the placeholder `_` is not allowed within types on item signatures for enums
|
||||
--> $DIR/bad-assoc-ty.rs:66:28
|
||||
|
|
||||
LL | enum N<F> where F: Fn() -> _ {
|
||||
|
|
@ -204,7 +204,7 @@ help: use type parameters instead
|
|||
LL | enum N<F, T> where F: Fn() -> T {
|
||||
| +++ ~
|
||||
|
||||
error[E0121]: the type placeholder `_` is not allowed within types on item signatures for unions
|
||||
error[E0121]: the placeholder `_` is not allowed within types on item signatures for unions
|
||||
--> $DIR/bad-assoc-ty.rs:71:29
|
||||
|
|
||||
LL | union O<F> where F: Fn() -> _ {
|
||||
|
|
@ -215,7 +215,7 @@ help: use type parameters instead
|
|||
LL | union O<F, T> where F: Fn() -> T {
|
||||
| +++ ~
|
||||
|
||||
error[E0121]: the type placeholder `_` is not allowed within types on item signatures for traits
|
||||
error[E0121]: the placeholder `_` is not allowed within types on item signatures for traits
|
||||
--> $DIR/bad-assoc-ty.rs:76:29
|
||||
|
|
||||
LL | trait P<F> where F: Fn() -> _ {
|
||||
|
|
@ -226,7 +226,7 @@ help: use type parameters instead
|
|||
LL | trait P<F, T> where F: Fn() -> T {
|
||||
| +++ ~
|
||||
|
||||
error[E0121]: the type placeholder `_` is not allowed within types on item signatures for functions
|
||||
error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions
|
||||
--> $DIR/bad-assoc-ty.rs:81:38
|
||||
|
|
||||
LL | fn foo<F>(_: F) where F: Fn() -> _ {}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
error[E0121]: the type placeholder `_` is not allowed within types on item signatures for return types
|
||||
error[E0121]: the placeholder `_` is not allowed within types on item signatures for return types
|
||||
--> $DIR/E0121.rs:1:13
|
||||
|
|
||||
LL | fn foo() -> _ { 5 }
|
||||
|
|
@ -7,7 +7,7 @@ LL | fn foo() -> _ { 5 }
|
|||
| not allowed in type signatures
|
||||
| help: replace with the correct return type: `i32`
|
||||
|
||||
error[E0121]: the type placeholder `_` is not allowed within types on item signatures for static variables
|
||||
error[E0121]: the placeholder `_` is not allowed within types on item signatures for static variables
|
||||
--> $DIR/E0121.rs:3:13
|
||||
|
|
||||
LL | static BAR: _ = "test";
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ fn returns_i32() -> i32 {
|
|||
}
|
||||
|
||||
fn returns_fn_ptr() -> _ {
|
||||
//~^ ERROR the type placeholder `_` is not allowed within types on item signatures for return types [E0121]
|
||||
//~^ ERROR the placeholder `_` is not allowed within types on item signatures for return types [E0121]
|
||||
//~| NOTE not allowed in type signatures
|
||||
//~| HELP replace with the correct return type
|
||||
//~| SUGGESTION fn() -> i32
|
||||
|
|
@ -16,7 +16,7 @@ fn returns_fn_ptr() -> _ {
|
|||
}
|
||||
|
||||
fn returns_closure() -> _ {
|
||||
//~^ ERROR the type placeholder `_` is not allowed within types on item signatures for return types [E0121]
|
||||
//~^ ERROR the placeholder `_` is not allowed within types on item signatures for return types [E0121]
|
||||
//~| NOTE not allowed in type signatures
|
||||
//~| HELP consider using an `Fn`, `FnMut`, or `FnOnce` trait bound
|
||||
//~| NOTE for more information on `Fn` traits and closure types, see
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
error[E0121]: the type placeholder `_` is not allowed within types on item signatures for return types
|
||||
error[E0121]: the placeholder `_` is not allowed within types on item signatures for return types
|
||||
--> $DIR/issue-80179.rs:10:24
|
||||
|
|
||||
LL | fn returns_fn_ptr() -> _ {
|
||||
|
|
@ -7,7 +7,7 @@ LL | fn returns_fn_ptr() -> _ {
|
|||
| not allowed in type signatures
|
||||
| help: replace with the correct return type: `fn() -> i32`
|
||||
|
||||
error[E0121]: the type placeholder `_` is not allowed within types on item signatures for return types
|
||||
error[E0121]: the placeholder `_` is not allowed within types on item signatures for return types
|
||||
--> $DIR/issue-80179.rs:18:25
|
||||
|
|
||||
LL | fn returns_closure() -> _ {
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ macro_rules! suite {
|
|||
const A = "A".$fn();
|
||||
//~^ ERROR the name `A` is defined multiple times
|
||||
//~| ERROR missing type for `const` item
|
||||
//~| ERROR the type placeholder `_` is not allowed within types on item signatures for constants
|
||||
//~| ERROR the placeholder `_` is not allowed within types on item signatures for constants
|
||||
)*
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ LL | | }
|
|||
|
|
||||
= note: this error originates in the macro `suite` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
|
||||
error[E0121]: the type placeholder `_` is not allowed within types on item signatures for constants
|
||||
error[E0121]: the placeholder `_` is not allowed within types on item signatures for constants
|
||||
--> $DIR/issue-69396-const-no-type-in-macro.rs:4:19
|
||||
|
|
||||
LL | const A = "A".$fn();
|
||||
|
|
|
|||
|
|
@ -2,28 +2,25 @@ error[E0623]: lifetime mismatch
|
|||
--> $DIR/arbitrary_self_types_pin_lifetime_mismatch-async.rs:8:52
|
||||
|
|
||||
LL | async fn a(self: Pin<&Foo>, f: &Foo) -> &Foo { f }
|
||||
| ---- ---- ^ ...but data from `f` is held across an await point here
|
||||
| | |
|
||||
| | this `async fn` implicitly returns an `impl Future<Output = &Foo>`
|
||||
| this parameter and the returned future are declared with different lifetimes...
|
||||
| ---- ---- ^ ...but data from `f` is returned here
|
||||
| |
|
||||
| this parameter and the return type are declared with different lifetimes...
|
||||
|
||||
error[E0623]: lifetime mismatch
|
||||
--> $DIR/arbitrary_self_types_pin_lifetime_mismatch-async.rs:11:82
|
||||
|
|
||||
LL | async fn c(self: Pin<&Self>, f: &Foo, g: &Foo) -> (Pin<&Foo>, &Foo) { (self, f) }
|
||||
| ----- ----------------- ^ ...but data from `f` is held across an await point here
|
||||
| | |
|
||||
| | this `async fn` implicitly returns an `impl Future<Output = (Pin<&Foo>, &Foo)>`
|
||||
| this parameter and the returned future are declared with different lifetimes...
|
||||
| ---- ----------------- ^ ...but data from `f` is returned here
|
||||
| |
|
||||
| this parameter and the return type are declared with different lifetimes...
|
||||
|
||||
error[E0623]: lifetime mismatch
|
||||
--> $DIR/arbitrary_self_types_pin_lifetime_mismatch-async.rs:17:64
|
||||
|
|
||||
LL | async fn bar<'a>(self: Alias<&Self>, arg: &'a ()) -> &() { arg }
|
||||
| ----- --- ^^^ ...but data from `arg` is held across an await point here
|
||||
| | |
|
||||
| | this `async fn` implicitly returns an `impl Future<Output = &()>`
|
||||
| this parameter and the returned future are declared with different lifetimes...
|
||||
| ------ --- ^^^ ...but data from `arg` is returned here
|
||||
| |
|
||||
| this parameter and the return type are declared with different lifetimes...
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
|
||||
|
|
|
|||
|
|
@ -2,67 +2,61 @@ error[E0623]: lifetime mismatch
|
|||
--> $DIR/lt-ref-self-async.rs:13:9
|
||||
|
|
||||
LL | async fn ref_self(&self, f: &u32) -> &u32 {
|
||||
| ----- ----
|
||||
| | |
|
||||
| | this `async fn` implicitly returns an `impl Future<Output = &u32>`
|
||||
| this parameter and the returned future are declared with different lifetimes...
|
||||
| ---- ----
|
||||
| |
|
||||
| this parameter and the return type are declared with different lifetimes...
|
||||
LL | f
|
||||
| ^ ...but data from `f` is held across an await point here
|
||||
| ^ ...but data from `f` is returned here
|
||||
|
||||
error[E0623]: lifetime mismatch
|
||||
--> $DIR/lt-ref-self-async.rs:19:9
|
||||
|
|
||||
LL | async fn ref_Self(self: &Self, f: &u32) -> &u32 {
|
||||
| ----- ----
|
||||
| | |
|
||||
| | this `async fn` implicitly returns an `impl Future<Output = &u32>`
|
||||
| this parameter and the returned future are declared with different lifetimes...
|
||||
| ---- ----
|
||||
| |
|
||||
| this parameter and the return type are declared with different lifetimes...
|
||||
LL | f
|
||||
| ^ ...but data from `f` is held across an await point here
|
||||
| ^ ...but data from `f` is returned here
|
||||
|
||||
error[E0623]: lifetime mismatch
|
||||
--> $DIR/lt-ref-self-async.rs:23:9
|
||||
|
|
||||
LL | async fn box_ref_Self(self: Box<&Self>, f: &u32) -> &u32 {
|
||||
| ----- ----
|
||||
| | |
|
||||
| | this `async fn` implicitly returns an `impl Future<Output = &u32>`
|
||||
| this parameter and the returned future are declared with different lifetimes...
|
||||
| ---- ----
|
||||
| |
|
||||
| this parameter and the return type are declared with different lifetimes...
|
||||
LL | f
|
||||
| ^ ...but data from `f` is held across an await point here
|
||||
| ^ ...but data from `f` is returned here
|
||||
|
||||
error[E0623]: lifetime mismatch
|
||||
--> $DIR/lt-ref-self-async.rs:27:9
|
||||
|
|
||||
LL | async fn pin_ref_Self(self: Pin<&Self>, f: &u32) -> &u32 {
|
||||
| ----- ----
|
||||
| | |
|
||||
| | this `async fn` implicitly returns an `impl Future<Output = &u32>`
|
||||
| this parameter and the returned future are declared with different lifetimes...
|
||||
| ---- ----
|
||||
| |
|
||||
| this parameter and the return type are declared with different lifetimes...
|
||||
LL | f
|
||||
| ^ ...but data from `f` is held across an await point here
|
||||
| ^ ...but data from `f` is returned here
|
||||
|
||||
error[E0623]: lifetime mismatch
|
||||
--> $DIR/lt-ref-self-async.rs:31:9
|
||||
|
|
||||
LL | async fn box_box_ref_Self(self: Box<Box<&Self>>, f: &u32) -> &u32 {
|
||||
| ----- ----
|
||||
| | |
|
||||
| | this `async fn` implicitly returns an `impl Future<Output = &u32>`
|
||||
| this parameter and the returned future are declared with different lifetimes...
|
||||
| ---- ----
|
||||
| |
|
||||
| this parameter and the return type are declared with different lifetimes...
|
||||
LL | f
|
||||
| ^ ...but data from `f` is held across an await point here
|
||||
| ^ ...but data from `f` is returned here
|
||||
|
||||
error[E0623]: lifetime mismatch
|
||||
--> $DIR/lt-ref-self-async.rs:35:9
|
||||
|
|
||||
LL | async fn box_pin_Self(self: Box<Pin<&Self>>, f: &u32) -> &u32 {
|
||||
| ----- ----
|
||||
| | |
|
||||
| | this `async fn` implicitly returns an `impl Future<Output = &u32>`
|
||||
| this parameter and the returned future are declared with different lifetimes...
|
||||
| ---- ----
|
||||
| |
|
||||
| this parameter and the return type are declared with different lifetimes...
|
||||
LL | f
|
||||
| ^ ...but data from `f` is held across an await point here
|
||||
| ^ ...but data from `f` is returned here
|
||||
|
||||
error: aborting due to 6 previous errors
|
||||
|
||||
|
|
|
|||
|
|
@ -2,67 +2,61 @@ error[E0623]: lifetime mismatch
|
|||
--> $DIR/ref-mut-self-async.rs:13:9
|
||||
|
|
||||
LL | async fn ref_self(&mut self, f: &u32) -> &u32 {
|
||||
| --------- ----
|
||||
| | |
|
||||
| | this `async fn` implicitly returns an `impl Future<Output = &u32>`
|
||||
| this parameter and the returned future are declared with different lifetimes...
|
||||
| ---- ----
|
||||
| |
|
||||
| this parameter and the return type are declared with different lifetimes...
|
||||
LL | f
|
||||
| ^ ...but data from `f` is held across an await point here
|
||||
| ^ ...but data from `f` is returned here
|
||||
|
||||
error[E0623]: lifetime mismatch
|
||||
--> $DIR/ref-mut-self-async.rs:19:9
|
||||
|
|
||||
LL | async fn ref_Self(self: &mut Self, f: &u32) -> &u32 {
|
||||
| --------- ----
|
||||
| | |
|
||||
| | this `async fn` implicitly returns an `impl Future<Output = &u32>`
|
||||
| this parameter and the returned future are declared with different lifetimes...
|
||||
| ---- ----
|
||||
| |
|
||||
| this parameter and the return type are declared with different lifetimes...
|
||||
LL | f
|
||||
| ^ ...but data from `f` is held across an await point here
|
||||
| ^ ...but data from `f` is returned here
|
||||
|
||||
error[E0623]: lifetime mismatch
|
||||
--> $DIR/ref-mut-self-async.rs:23:9
|
||||
|
|
||||
LL | async fn box_ref_Self(self: Box<&mut Self>, f: &u32) -> &u32 {
|
||||
| --------- ----
|
||||
| | |
|
||||
| | this `async fn` implicitly returns an `impl Future<Output = &u32>`
|
||||
| this parameter and the returned future are declared with different lifetimes...
|
||||
| ---- ----
|
||||
| |
|
||||
| this parameter and the return type are declared with different lifetimes...
|
||||
LL | f
|
||||
| ^ ...but data from `f` is held across an await point here
|
||||
| ^ ...but data from `f` is returned here
|
||||
|
||||
error[E0623]: lifetime mismatch
|
||||
--> $DIR/ref-mut-self-async.rs:27:9
|
||||
|
|
||||
LL | async fn pin_ref_Self(self: Pin<&mut Self>, f: &u32) -> &u32 {
|
||||
| --------- ----
|
||||
| | |
|
||||
| | this `async fn` implicitly returns an `impl Future<Output = &u32>`
|
||||
| this parameter and the returned future are declared with different lifetimes...
|
||||
| ---- ----
|
||||
| |
|
||||
| this parameter and the return type are declared with different lifetimes...
|
||||
LL | f
|
||||
| ^ ...but data from `f` is held across an await point here
|
||||
| ^ ...but data from `f` is returned here
|
||||
|
||||
error[E0623]: lifetime mismatch
|
||||
--> $DIR/ref-mut-self-async.rs:31:9
|
||||
|
|
||||
LL | async fn box_box_ref_Self(self: Box<Box<&mut Self>>, f: &u32) -> &u32 {
|
||||
| --------- ----
|
||||
| | |
|
||||
| | this `async fn` implicitly returns an `impl Future<Output = &u32>`
|
||||
| this parameter and the returned future are declared with different lifetimes...
|
||||
| ---- ----
|
||||
| |
|
||||
| this parameter and the return type are declared with different lifetimes...
|
||||
LL | f
|
||||
| ^ ...but data from `f` is held across an await point here
|
||||
| ^ ...but data from `f` is returned here
|
||||
|
||||
error[E0623]: lifetime mismatch
|
||||
--> $DIR/ref-mut-self-async.rs:35:9
|
||||
|
|
||||
LL | async fn box_pin_ref_Self(self: Box<Pin<&mut Self>>, f: &u32) -> &u32 {
|
||||
| --------- ----
|
||||
| | |
|
||||
| | this `async fn` implicitly returns an `impl Future<Output = &u32>`
|
||||
| this parameter and the returned future are declared with different lifetimes...
|
||||
| ---- ----
|
||||
| |
|
||||
| this parameter and the return type are declared with different lifetimes...
|
||||
LL | f
|
||||
| ^ ...but data from `f` is held across an await point here
|
||||
| ^ ...but data from `f` is returned here
|
||||
|
||||
error: aborting due to 6 previous errors
|
||||
|
||||
|
|
|
|||
|
|
@ -2,56 +2,51 @@ error[E0623]: lifetime mismatch
|
|||
--> $DIR/ref-mut-struct-async.rs:13:9
|
||||
|
|
||||
LL | async fn ref_Struct(self: &mut Struct, f: &u32) -> &u32 {
|
||||
| ----------- ----
|
||||
| | |
|
||||
| | this `async fn` implicitly returns an `impl Future<Output = &u32>`
|
||||
| this parameter and the returned future are declared with different lifetimes...
|
||||
| ---- ----
|
||||
| |
|
||||
| this parameter and the return type are declared with different lifetimes...
|
||||
LL | f
|
||||
| ^ ...but data from `f` is held across an await point here
|
||||
| ^ ...but data from `f` is returned here
|
||||
|
||||
error[E0623]: lifetime mismatch
|
||||
--> $DIR/ref-mut-struct-async.rs:17:9
|
||||
|
|
||||
LL | async fn box_ref_Struct(self: Box<&mut Struct>, f: &u32) -> &u32 {
|
||||
| ----------- ----
|
||||
| | |
|
||||
| | this `async fn` implicitly returns an `impl Future<Output = &u32>`
|
||||
| this parameter and the returned future are declared with different lifetimes...
|
||||
| ---- ----
|
||||
| |
|
||||
| this parameter and the return type are declared with different lifetimes...
|
||||
LL | f
|
||||
| ^ ...but data from `f` is held across an await point here
|
||||
| ^ ...but data from `f` is returned here
|
||||
|
||||
error[E0623]: lifetime mismatch
|
||||
--> $DIR/ref-mut-struct-async.rs:21:9
|
||||
|
|
||||
LL | async fn pin_ref_Struct(self: Pin<&mut Struct>, f: &u32) -> &u32 {
|
||||
| ----------- ----
|
||||
| | |
|
||||
| | this `async fn` implicitly returns an `impl Future<Output = &u32>`
|
||||
| this parameter and the returned future are declared with different lifetimes...
|
||||
| ---- ----
|
||||
| |
|
||||
| this parameter and the return type are declared with different lifetimes...
|
||||
LL | f
|
||||
| ^ ...but data from `f` is held across an await point here
|
||||
| ^ ...but data from `f` is returned here
|
||||
|
||||
error[E0623]: lifetime mismatch
|
||||
--> $DIR/ref-mut-struct-async.rs:25:9
|
||||
|
|
||||
LL | async fn box_box_ref_Struct(self: Box<Box<&mut Struct>>, f: &u32) -> &u32 {
|
||||
| ----------- ----
|
||||
| | |
|
||||
| | this `async fn` implicitly returns an `impl Future<Output = &u32>`
|
||||
| this parameter and the returned future are declared with different lifetimes...
|
||||
| ---- ----
|
||||
| |
|
||||
| this parameter and the return type are declared with different lifetimes...
|
||||
LL | f
|
||||
| ^ ...but data from `f` is held across an await point here
|
||||
| ^ ...but data from `f` is returned here
|
||||
|
||||
error[E0623]: lifetime mismatch
|
||||
--> $DIR/ref-mut-struct-async.rs:29:9
|
||||
|
|
||||
LL | async fn box_pin_ref_Struct(self: Box<Pin<&mut Struct>>, f: &u32) -> &u32 {
|
||||
| ----------- ----
|
||||
| | |
|
||||
| | this `async fn` implicitly returns an `impl Future<Output = &u32>`
|
||||
| this parameter and the returned future are declared with different lifetimes...
|
||||
| ---- ----
|
||||
| |
|
||||
| this parameter and the return type are declared with different lifetimes...
|
||||
LL | f
|
||||
| ^ ...but data from `f` is held across an await point here
|
||||
| ^ ...but data from `f` is returned here
|
||||
|
||||
error: aborting due to 5 previous errors
|
||||
|
||||
|
|
|
|||
|
|
@ -2,78 +2,71 @@ error[E0623]: lifetime mismatch
|
|||
--> $DIR/ref-self-async.rs:23:9
|
||||
|
|
||||
LL | async fn ref_self(&self, f: &u32) -> &u32 {
|
||||
| ----- ----
|
||||
| | |
|
||||
| | this `async fn` implicitly returns an `impl Future<Output = &u32>`
|
||||
| this parameter and the returned future are declared with different lifetimes...
|
||||
| ---- ----
|
||||
| |
|
||||
| this parameter and the return type are declared with different lifetimes...
|
||||
LL | f
|
||||
| ^ ...but data from `f` is held across an await point here
|
||||
| ^ ...but data from `f` is returned here
|
||||
|
||||
error[E0623]: lifetime mismatch
|
||||
--> $DIR/ref-self-async.rs:29:9
|
||||
|
|
||||
LL | async fn ref_Self(self: &Self, f: &u32) -> &u32 {
|
||||
| ----- ----
|
||||
| | |
|
||||
| | this `async fn` implicitly returns an `impl Future<Output = &u32>`
|
||||
| this parameter and the returned future are declared with different lifetimes...
|
||||
| ---- ----
|
||||
| |
|
||||
| this parameter and the return type are declared with different lifetimes...
|
||||
LL | f
|
||||
| ^ ...but data from `f` is held across an await point here
|
||||
| ^ ...but data from `f` is returned here
|
||||
|
||||
error[E0623]: lifetime mismatch
|
||||
--> $DIR/ref-self-async.rs:33:9
|
||||
|
|
||||
LL | async fn box_ref_Self(self: Box<&Self>, f: &u32) -> &u32 {
|
||||
| ----- ----
|
||||
| | |
|
||||
| | this `async fn` implicitly returns an `impl Future<Output = &u32>`
|
||||
| this parameter and the returned future are declared with different lifetimes...
|
||||
| ---- ----
|
||||
| |
|
||||
| this parameter and the return type are declared with different lifetimes...
|
||||
LL | f
|
||||
| ^ ...but data from `f` is held across an await point here
|
||||
| ^ ...but data from `f` is returned here
|
||||
|
||||
error[E0623]: lifetime mismatch
|
||||
--> $DIR/ref-self-async.rs:37:9
|
||||
|
|
||||
LL | async fn pin_ref_Self(self: Pin<&Self>, f: &u32) -> &u32 {
|
||||
| ----- ----
|
||||
| | |
|
||||
| | this `async fn` implicitly returns an `impl Future<Output = &u32>`
|
||||
| this parameter and the returned future are declared with different lifetimes...
|
||||
| ---- ----
|
||||
| |
|
||||
| this parameter and the return type are declared with different lifetimes...
|
||||
LL | f
|
||||
| ^ ...but data from `f` is held across an await point here
|
||||
| ^ ...but data from `f` is returned here
|
||||
|
||||
error[E0623]: lifetime mismatch
|
||||
--> $DIR/ref-self-async.rs:41:9
|
||||
|
|
||||
LL | async fn box_box_ref_Self(self: Box<Box<&Self>>, f: &u32) -> &u32 {
|
||||
| ----- ----
|
||||
| | |
|
||||
| | this `async fn` implicitly returns an `impl Future<Output = &u32>`
|
||||
| this parameter and the returned future are declared with different lifetimes...
|
||||
| ---- ----
|
||||
| |
|
||||
| this parameter and the return type are declared with different lifetimes...
|
||||
LL | f
|
||||
| ^ ...but data from `f` is held across an await point here
|
||||
| ^ ...but data from `f` is returned here
|
||||
|
||||
error[E0623]: lifetime mismatch
|
||||
--> $DIR/ref-self-async.rs:45:9
|
||||
|
|
||||
LL | async fn box_pin_ref_Self(self: Box<Pin<&Self>>, f: &u32) -> &u32 {
|
||||
| ----- ----
|
||||
| | |
|
||||
| | this `async fn` implicitly returns an `impl Future<Output = &u32>`
|
||||
| this parameter and the returned future are declared with different lifetimes...
|
||||
| ---- ----
|
||||
| |
|
||||
| this parameter and the return type are declared with different lifetimes...
|
||||
LL | f
|
||||
| ^ ...but data from `f` is held across an await point here
|
||||
| ^ ...but data from `f` is returned here
|
||||
|
||||
error[E0623]: lifetime mismatch
|
||||
--> $DIR/ref-self-async.rs:49:9
|
||||
|
|
||||
LL | async fn wrap_ref_Self_Self(self: Wrap<&Self, Self>, f: &u8) -> &u8 {
|
||||
| ----- ---
|
||||
| | |
|
||||
| | this `async fn` implicitly returns an `impl Future<Output = &u8>`
|
||||
| this parameter and the returned future are declared with different lifetimes...
|
||||
| --- ---
|
||||
| |
|
||||
| this parameter and the return type are declared with different lifetimes...
|
||||
LL | f
|
||||
| ^ ...but data from `f` is held across an await point here
|
||||
| ^ ...but data from `f` is returned here
|
||||
|
||||
error: aborting due to 7 previous errors
|
||||
|
||||
|
|
|
|||
|
|
@ -2,56 +2,51 @@ error[E0623]: lifetime mismatch
|
|||
--> $DIR/ref-struct-async.rs:13:9
|
||||
|
|
||||
LL | async fn ref_Struct(self: &Struct, f: &u32) -> &u32 {
|
||||
| ------- ----
|
||||
| | |
|
||||
| | this `async fn` implicitly returns an `impl Future<Output = &u32>`
|
||||
| this parameter and the returned future are declared with different lifetimes...
|
||||
| ---- ----
|
||||
| |
|
||||
| this parameter and the return type are declared with different lifetimes...
|
||||
LL | f
|
||||
| ^ ...but data from `f` is held across an await point here
|
||||
| ^ ...but data from `f` is returned here
|
||||
|
||||
error[E0623]: lifetime mismatch
|
||||
--> $DIR/ref-struct-async.rs:17:9
|
||||
|
|
||||
LL | async fn box_ref_Struct(self: Box<&Struct>, f: &u32) -> &u32 {
|
||||
| ------- ----
|
||||
| | |
|
||||
| | this `async fn` implicitly returns an `impl Future<Output = &u32>`
|
||||
| this parameter and the returned future are declared with different lifetimes...
|
||||
| ---- ----
|
||||
| |
|
||||
| this parameter and the return type are declared with different lifetimes...
|
||||
LL | f
|
||||
| ^ ...but data from `f` is held across an await point here
|
||||
| ^ ...but data from `f` is returned here
|
||||
|
||||
error[E0623]: lifetime mismatch
|
||||
--> $DIR/ref-struct-async.rs:21:9
|
||||
|
|
||||
LL | async fn pin_ref_Struct(self: Pin<&Struct>, f: &u32) -> &u32 {
|
||||
| ------- ----
|
||||
| | |
|
||||
| | this `async fn` implicitly returns an `impl Future<Output = &u32>`
|
||||
| this parameter and the returned future are declared with different lifetimes...
|
||||
| ---- ----
|
||||
| |
|
||||
| this parameter and the return type are declared with different lifetimes...
|
||||
LL | f
|
||||
| ^ ...but data from `f` is held across an await point here
|
||||
| ^ ...but data from `f` is returned here
|
||||
|
||||
error[E0623]: lifetime mismatch
|
||||
--> $DIR/ref-struct-async.rs:25:9
|
||||
|
|
||||
LL | async fn box_box_ref_Struct(self: Box<Box<&Struct>>, f: &u32) -> &u32 {
|
||||
| ------- ----
|
||||
| | |
|
||||
| | this `async fn` implicitly returns an `impl Future<Output = &u32>`
|
||||
| this parameter and the returned future are declared with different lifetimes...
|
||||
| ---- ----
|
||||
| |
|
||||
| this parameter and the return type are declared with different lifetimes...
|
||||
LL | f
|
||||
| ^ ...but data from `f` is held across an await point here
|
||||
| ^ ...but data from `f` is returned here
|
||||
|
||||
error[E0623]: lifetime mismatch
|
||||
--> $DIR/ref-struct-async.rs:29:9
|
||||
|
|
||||
LL | async fn box_pin_Struct(self: Box<Pin<&Struct>>, f: &u32) -> &u32 {
|
||||
| ------- ----
|
||||
| | |
|
||||
| | this `async fn` implicitly returns an `impl Future<Output = &u32>`
|
||||
| this parameter and the returned future are declared with different lifetimes...
|
||||
| ---- ----
|
||||
| |
|
||||
| this parameter and the return type are declared with different lifetimes...
|
||||
LL | f
|
||||
| ^ ...but data from `f` is held across an await point here
|
||||
| ^ ...but data from `f` is returned here
|
||||
|
||||
error: aborting due to 5 previous errors
|
||||
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
struct S;
|
||||
|
||||
impl S {
|
||||
fn f(self: _) {} //~ERROR the type placeholder `_` is not allowed within types on item signatures for functions
|
||||
fn g(self: &_) {} //~ERROR the type placeholder `_` is not allowed within types on item signatures for functions
|
||||
fn f(self: _) {} //~ERROR the placeholder `_` is not allowed within types on item signatures for functions
|
||||
fn g(self: &_) {} //~ERROR the placeholder `_` is not allowed within types on item signatures for functions
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
error[E0121]: the type placeholder `_` is not allowed within types on item signatures for functions
|
||||
error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions
|
||||
--> $DIR/self-infer.rs:4:16
|
||||
|
|
||||
LL | fn f(self: _) {}
|
||||
|
|
@ -9,7 +9,7 @@ help: use type parameters instead
|
|||
LL | fn f<T>(self: T) {}
|
||||
| +++ ~
|
||||
|
||||
error[E0121]: the type placeholder `_` is not allowed within types on item signatures for functions
|
||||
error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions
|
||||
--> $DIR/self-infer.rs:5:17
|
||||
|
|
||||
LL | fn g(self: &_) {}
|
||||
|
|
|
|||
|
|
@ -8,14 +8,14 @@ const A = 5;
|
|||
//~| HELP: provide a type for the constant
|
||||
|
||||
static B: _ = "abc";
|
||||
//~^ ERROR: the type placeholder `_` is not allowed within types on item signatures for static variables
|
||||
//~^ ERROR: the placeholder `_` is not allowed within types on item signatures for static variables
|
||||
//~| NOTE: not allowed in type signatures
|
||||
//~| HELP: replace with the correct type
|
||||
|
||||
|
||||
// FIXME: this should also suggest a function pointer, as the closure is non-capturing
|
||||
const C: _ = || 42;
|
||||
//~^ ERROR: the type placeholder `_` is not allowed within types on item signatures for constants
|
||||
//~^ ERROR: the placeholder `_` is not allowed within types on item signatures for constants
|
||||
//~| NOTE: not allowed in type signatures
|
||||
//~| NOTE: however, the inferred type
|
||||
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ error: missing type for `const` item
|
|||
LL | const A = 5;
|
||||
| ^ help: provide a type for the constant: `A: i32`
|
||||
|
||||
error[E0121]: the type placeholder `_` is not allowed within types on item signatures for static variables
|
||||
error[E0121]: the placeholder `_` is not allowed within types on item signatures for static variables
|
||||
--> $DIR/unnamable-types.rs:10:11
|
||||
|
|
||||
LL | static B: _ = "abc";
|
||||
|
|
@ -13,7 +13,7 @@ LL | static B: _ = "abc";
|
|||
| not allowed in type signatures
|
||||
| help: replace with the correct type: `&str`
|
||||
|
||||
error[E0121]: the type placeholder `_` is not allowed within types on item signatures for constants
|
||||
error[E0121]: the placeholder `_` is not allowed within types on item signatures for constants
|
||||
--> $DIR/unnamable-types.rs:17:10
|
||||
|
|
||||
LL | const C: _ = || 42;
|
||||
|
|
|
|||
|
|
@ -4,5 +4,5 @@ use std::mem::transmute;
|
|||
|
||||
fn main() {
|
||||
let _a: &mut u8 = unsafe { transmute(&1u8) };
|
||||
//~^ ERROR mutating transmuted &mut T from &T may cause undefined behavior
|
||||
//~^ ERROR transmuting &T to &mut T is undefined behavior, even if the reference is unused, consider instead using an UnsafeCell
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
error: mutating transmuted &mut T from &T may cause undefined behavior, consider instead using an UnsafeCell
|
||||
error: transmuting &T to &mut T is undefined behavior, even if the reference is unused, consider instead using an UnsafeCell
|
||||
--> $DIR/transmute-imut-to-mut.rs:6:32
|
||||
|
|
||||
LL | let _a: &mut u8 = unsafe { transmute(&1u8) };
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
type Pointer<T> = impl std::ops::Deref<Target=T>;
|
||||
|
||||
fn test() -> Pointer<_> {
|
||||
//~^ ERROR: the type placeholder `_` is not allowed within types
|
||||
//~^ ERROR: the placeholder `_` is not allowed within types
|
||||
Box::new(1)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
error[E0121]: the type placeholder `_` is not allowed within types on item signatures for return types
|
||||
error[E0121]: the placeholder `_` is not allowed within types on item signatures for return types
|
||||
--> $DIR/issue-77179.rs:7:22
|
||||
|
|
||||
LL | fn test() -> Pointer<_> {
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
fn main() {
|
||||
static BUG: fn(_) -> u8 = |_| 8;
|
||||
//~^ ERROR the type placeholder `_` is not allowed within types on item signatures for functions [E0121]
|
||||
//~^ ERROR the placeholder `_` is not allowed within types on item signatures for functions [E0121]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
error[E0121]: the type placeholder `_` is not allowed within types on item signatures for functions
|
||||
error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions
|
||||
--> $DIR/issue-74086.rs:2:20
|
||||
|
|
||||
LL | static BUG: fn(_) -> u8 = |_| 8;
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ pub struct UI {}
|
|||
impl UI {
|
||||
pub fn run() -> Result<_> {
|
||||
//~^ ERROR: this enum takes 2 generic arguments but 1 generic argument was supplied
|
||||
//~| ERROR: the type placeholder `_` is not allowed within types on item signatures for return types
|
||||
//~| ERROR: the placeholder `_` is not allowed within types on item signatures for return types
|
||||
let mut ui = UI {};
|
||||
ui.interact();
|
||||
|
||||
|
|
@ -14,7 +14,7 @@ impl UI {
|
|||
|
||||
pub fn interact(&mut self) -> Result<_> {
|
||||
//~^ ERROR: this enum takes 2 generic arguments but 1 generic argument was supplied
|
||||
//~| ERROR: the type placeholder `_` is not allowed within types on item signatures for return types
|
||||
//~| ERROR: the placeholder `_` is not allowed within types on item signatures for return types
|
||||
unimplemented!();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -34,13 +34,13 @@ help: add missing generic argument
|
|||
LL | pub fn interact(&mut self) -> Result<_, E> {
|
||||
| +++
|
||||
|
||||
error[E0121]: the type placeholder `_` is not allowed within types on item signatures for return types
|
||||
error[E0121]: the placeholder `_` is not allowed within types on item signatures for return types
|
||||
--> $DIR/issue-75883.rs:15:42
|
||||
|
|
||||
LL | pub fn interact(&mut self) -> Result<_> {
|
||||
| ^ not allowed in type signatures
|
||||
|
||||
error[E0121]: the type placeholder `_` is not allowed within types on item signatures for return types
|
||||
error[E0121]: the placeholder `_` is not allowed within types on item signatures for return types
|
||||
--> $DIR/issue-75883.rs:6:28
|
||||
|
|
||||
LL | pub fn run() -> Result<_> {
|
||||
|
|
|
|||
|
|
@ -1,10 +1,10 @@
|
|||
error[E0121]: the type placeholder `_` is not allowed within types on item signatures for constant items
|
||||
error[E0121]: the placeholder `_` is not allowed within types on item signatures for constant items
|
||||
--> $DIR/issue-75889.rs:3:24
|
||||
|
|
||||
LL | const FOO: dyn Fn() -> _ = "";
|
||||
| ^ not allowed in type signatures
|
||||
|
||||
error[E0121]: the type placeholder `_` is not allowed within types on item signatures for static items
|
||||
error[E0121]: the placeholder `_` is not allowed within types on item signatures for static items
|
||||
--> $DIR/issue-75889.rs:4:25
|
||||
|
|
||||
LL | static BOO: dyn Fn() -> _ = "";
|
||||
|
|
|
|||
|
|
@ -3,11 +3,11 @@
|
|||
pub struct T<'a>(&'a str);
|
||||
|
||||
pub fn f<'a>(val: T<'a>) -> _ {
|
||||
//~^ ERROR: the type placeholder `_` is not allowed within types on item signatures for return types
|
||||
//~^ ERROR: the placeholder `_` is not allowed within types on item signatures for return types
|
||||
g(val)
|
||||
}
|
||||
|
||||
pub fn g(_: T<'static>) -> _ {}
|
||||
//~^ ERROR: the type placeholder `_` is not allowed within types on item signatures for return types
|
||||
//~^ ERROR: the placeholder `_` is not allowed within types on item signatures for return types
|
||||
|
||||
fn main() {}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
error[E0121]: the type placeholder `_` is not allowed within types on item signatures for return types
|
||||
error[E0121]: the placeholder `_` is not allowed within types on item signatures for return types
|
||||
--> $DIR/issue-80779.rs:10:28
|
||||
|
|
||||
LL | pub fn g(_: T<'static>) -> _ {}
|
||||
|
|
@ -7,7 +7,7 @@ LL | pub fn g(_: T<'static>) -> _ {}
|
|||
| not allowed in type signatures
|
||||
| help: replace with the correct return type: `()`
|
||||
|
||||
error[E0121]: the type placeholder `_` is not allowed within types on item signatures for return types
|
||||
error[E0121]: the placeholder `_` is not allowed within types on item signatures for return types
|
||||
--> $DIR/issue-80779.rs:5:29
|
||||
|
|
||||
LL | pub fn f<'a>(val: T<'a>) -> _ {
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
const TEST4: fn() -> _ = 42;
|
||||
//~^ ERROR the type placeholder `_` is not allowed within types on item signatures for functions
|
||||
//~^ ERROR the placeholder `_` is not allowed within types on item signatures for functions
|
||||
|
||||
fn main() {
|
||||
const TEST5: fn() -> _ = 42;
|
||||
//~^ ERROR the type placeholder `_` is not allowed within types on item signatures for functions
|
||||
//~^ ERROR the placeholder `_` is not allowed within types on item signatures for functions
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,10 +1,10 @@
|
|||
error[E0121]: the type placeholder `_` is not allowed within types on item signatures for functions
|
||||
error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions
|
||||
--> $DIR/issue-81885.rs:1:22
|
||||
|
|
||||
LL | const TEST4: fn() -> _ = 42;
|
||||
| ^ not allowed in type signatures
|
||||
|
||||
error[E0121]: the type placeholder `_` is not allowed within types on item signatures for functions
|
||||
error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions
|
||||
--> $DIR/issue-81885.rs:5:26
|
||||
|
|
||||
LL | const TEST5: fn() -> _ = 42;
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
error[E0121]: the type placeholder `_` is not allowed within types on item signatures for static variables
|
||||
error[E0121]: the placeholder `_` is not allowed within types on item signatures for static variables
|
||||
--> $DIR/issue-83621-placeholder-static-in-extern.rs:4:15
|
||||
|
|
||||
LL | static x: _;
|
||||
|
|
|
|||
|
|
@ -2,6 +2,6 @@
|
|||
// This test ensures that the compiler does not suggest `Foo<[type error]>` in diagnostic messages.
|
||||
|
||||
fn foo() -> Option<_> {} //~ ERROR: [E0308]
|
||||
//~^ ERROR: the type placeholder `_` is not allowed
|
||||
//~^ ERROR: the placeholder `_` is not allowed
|
||||
|
||||
fn main() {}
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ LL | fn foo() -> Option<_> {}
|
|||
= note: expected enum `Option<_>`
|
||||
found unit type `()`
|
||||
|
||||
error[E0121]: the type placeholder `_` is not allowed within types on item signatures for return types
|
||||
error[E0121]: the placeholder `_` is not allowed within types on item signatures for return types
|
||||
--> $DIR/issue-91450-inner-ty-error.rs:4:20
|
||||
|
|
||||
LL | fn foo() -> Option<_> {}
|
||||
|
|
|
|||
|
|
@ -2,13 +2,13 @@ struct MyStruct;
|
|||
|
||||
trait Test {
|
||||
const TEST: fn() -> _;
|
||||
//~^ ERROR: the type placeholder `_` is not allowed within types on item signatures for functions [E0121]
|
||||
//~| ERROR: the type placeholder `_` is not allowed within types on item signatures for constants [E0121]
|
||||
//~^ ERROR: the placeholder `_` is not allowed within types on item signatures for functions [E0121]
|
||||
//~| ERROR: the placeholder `_` is not allowed within types on item signatures for constants [E0121]
|
||||
}
|
||||
|
||||
impl Test for MyStruct {
|
||||
const TEST: fn() -> _ = 42;
|
||||
//~^ ERROR: the type placeholder `_` is not allowed within types on item signatures for functions [E0121]
|
||||
//~^ ERROR: the placeholder `_` is not allowed within types on item signatures for functions [E0121]
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
|
|
|||
|
|
@ -1,16 +1,16 @@
|
|||
error[E0121]: the type placeholder `_` is not allowed within types on item signatures for functions
|
||||
error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions
|
||||
--> $DIR/type-placeholder-fn-in-const.rs:4:25
|
||||
|
|
||||
LL | const TEST: fn() -> _;
|
||||
| ^ not allowed in type signatures
|
||||
|
||||
error[E0121]: the type placeholder `_` is not allowed within types on item signatures for constants
|
||||
error[E0121]: the placeholder `_` is not allowed within types on item signatures for constants
|
||||
--> $DIR/type-placeholder-fn-in-const.rs:4:25
|
||||
|
|
||||
LL | const TEST: fn() -> _;
|
||||
| ^ not allowed in type signatures
|
||||
|
||||
error[E0121]: the type placeholder `_` is not allowed within types on item signatures for functions
|
||||
error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions
|
||||
--> $DIR/type-placeholder-fn-in-const.rs:10:25
|
||||
|
|
||||
LL | const TEST: fn() -> _ = 42;
|
||||
|
|
|
|||
|
|
@ -5,67 +5,67 @@
|
|||
// inference by using the `_` type placeholder.
|
||||
|
||||
fn test() -> _ { 5 }
|
||||
//~^ ERROR the type placeholder `_` is not allowed within types on item signatures for return types
|
||||
//~^ ERROR the placeholder `_` is not allowed within types on item signatures for return types
|
||||
|
||||
fn test2() -> (_, _) { (5, 5) }
|
||||
//~^ ERROR the type placeholder `_` is not allowed within types on item signatures for return types
|
||||
//~^ ERROR the placeholder `_` is not allowed within types on item signatures for return types
|
||||
|
||||
static TEST3: _ = "test";
|
||||
//~^ ERROR the type placeholder `_` is not allowed within types on item signatures for static variables
|
||||
//~^ ERROR the placeholder `_` is not allowed within types on item signatures for static variables
|
||||
|
||||
static TEST4: _ = 145;
|
||||
//~^ ERROR the type placeholder `_` is not allowed within types on item signatures for static variables
|
||||
//~^ ERROR the placeholder `_` is not allowed within types on item signatures for static variables
|
||||
|
||||
static TEST5: (_, _) = (1, 2);
|
||||
//~^ ERROR the type placeholder `_` is not allowed within types on item signatures for static variables
|
||||
//~^ ERROR the placeholder `_` is not allowed within types on item signatures for static variables
|
||||
|
||||
fn test6(_: _) { }
|
||||
//~^ ERROR the type placeholder `_` is not allowed within types on item signatures for functions
|
||||
//~^ ERROR the placeholder `_` is not allowed within types on item signatures for functions
|
||||
|
||||
fn test6_b<T>(_: _, _: T) { }
|
||||
//~^ ERROR the type placeholder `_` is not allowed within types on item signatures for functions
|
||||
//~^ ERROR the placeholder `_` is not allowed within types on item signatures for functions
|
||||
|
||||
fn test6_c<T, K, L, A, B>(_: _, _: (T, K, L, A, B)) { }
|
||||
//~^ ERROR the type placeholder `_` is not allowed within types on item signatures for functions
|
||||
//~^ ERROR the placeholder `_` is not allowed within types on item signatures for functions
|
||||
|
||||
fn test7(x: _) { let _x: usize = x; }
|
||||
//~^ ERROR the type placeholder `_` is not allowed within types on item signatures for functions
|
||||
//~^ ERROR the placeholder `_` is not allowed within types on item signatures for functions
|
||||
|
||||
fn test8(_f: fn() -> _) { }
|
||||
//~^ ERROR the type placeholder `_` is not allowed within types on item signatures for functions
|
||||
//~^^ ERROR the type placeholder `_` is not allowed within types on item signatures for functions
|
||||
//~^ ERROR the placeholder `_` is not allowed within types on item signatures for functions
|
||||
//~^^ ERROR the placeholder `_` is not allowed within types on item signatures for functions
|
||||
|
||||
struct Test9;
|
||||
|
||||
impl Test9 {
|
||||
fn test9(&self) -> _ { () }
|
||||
//~^ ERROR the type placeholder `_` is not allowed within types on item signatures for return types
|
||||
//~^ ERROR the placeholder `_` is not allowed within types on item signatures for return types
|
||||
|
||||
fn test10(&self, _x : _) { }
|
||||
//~^ ERROR the type placeholder `_` is not allowed within types on item signatures for functions
|
||||
//~^ ERROR the placeholder `_` is not allowed within types on item signatures for functions
|
||||
}
|
||||
|
||||
fn test11(x: &usize) -> &_ {
|
||||
//~^ ERROR the type placeholder `_` is not allowed within types on item signatures for return types
|
||||
//~^ ERROR the placeholder `_` is not allowed within types on item signatures for return types
|
||||
&x
|
||||
}
|
||||
|
||||
unsafe fn test12(x: *const usize) -> *const *const _ {
|
||||
//~^ ERROR the type placeholder `_` is not allowed within types on item signatures for return types
|
||||
//~^ ERROR the placeholder `_` is not allowed within types on item signatures for return types
|
||||
&x
|
||||
}
|
||||
|
||||
impl Clone for Test9 {
|
||||
fn clone(&self) -> _ { Test9 }
|
||||
//~^ ERROR the type placeholder `_` is not allowed within types on item signatures for return types
|
||||
//~^ ERROR the placeholder `_` is not allowed within types on item signatures for return types
|
||||
|
||||
fn clone_from(&mut self, other: _) { *self = Test9; }
|
||||
//~^ ERROR the type placeholder `_` is not allowed within types on item signatures for functions
|
||||
//~^ ERROR the placeholder `_` is not allowed within types on item signatures for functions
|
||||
}
|
||||
|
||||
struct Test10 {
|
||||
a: _,
|
||||
//~^ ERROR the type placeholder `_` is not allowed within types on item signatures for structs
|
||||
//~^ ERROR the placeholder `_` is not allowed within types on item signatures for structs
|
||||
b: (_, _),
|
||||
}
|
||||
|
||||
|
|
@ -73,94 +73,94 @@ pub fn main() {
|
|||
static A = 42;
|
||||
//~^ ERROR missing type for `static` item
|
||||
static B: _ = 42;
|
||||
//~^ ERROR the type placeholder `_` is not allowed within types on item signatures for static variables
|
||||
//~^ ERROR the placeholder `_` is not allowed within types on item signatures for static variables
|
||||
static C: Option<_> = Some(42);
|
||||
//~^ ERROR the type placeholder `_` is not allowed within types on item signatures for static variables
|
||||
//~^ ERROR the placeholder `_` is not allowed within types on item signatures for static variables
|
||||
fn fn_test() -> _ { 5 }
|
||||
//~^ ERROR the type placeholder `_` is not allowed within types on item signatures for return types
|
||||
//~^ ERROR the placeholder `_` is not allowed within types on item signatures for return types
|
||||
|
||||
fn fn_test2() -> (_, _) { (5, 5) }
|
||||
//~^ ERROR the type placeholder `_` is not allowed within types on item signatures for return types
|
||||
//~^ ERROR the placeholder `_` is not allowed within types on item signatures for return types
|
||||
|
||||
static FN_TEST3: _ = "test";
|
||||
//~^ ERROR the type placeholder `_` is not allowed within types on item signatures for static variables
|
||||
//~^ ERROR the placeholder `_` is not allowed within types on item signatures for static variables
|
||||
|
||||
static FN_TEST4: _ = 145;
|
||||
//~^ ERROR the type placeholder `_` is not allowed within types on item signatures for static variables
|
||||
//~^ ERROR the placeholder `_` is not allowed within types on item signatures for static variables
|
||||
|
||||
static FN_TEST5: (_, _) = (1, 2);
|
||||
//~^ ERROR the type placeholder `_` is not allowed within types on item signatures for static variables
|
||||
//~^ ERROR the placeholder `_` is not allowed within types on item signatures for static variables
|
||||
|
||||
fn fn_test6(_: _) { }
|
||||
//~^ ERROR the type placeholder `_` is not allowed within types on item signatures for functions
|
||||
//~^ ERROR the placeholder `_` is not allowed within types on item signatures for functions
|
||||
|
||||
fn fn_test7(x: _) { let _x: usize = x; }
|
||||
//~^ ERROR the type placeholder `_` is not allowed within types on item signatures for functions
|
||||
//~^ ERROR the placeholder `_` is not allowed within types on item signatures for functions
|
||||
|
||||
fn fn_test8(_f: fn() -> _) { }
|
||||
//~^ ERROR the type placeholder `_` is not allowed within types on item signatures for functions
|
||||
//~^^ ERROR the type placeholder `_` is not allowed within types on item signatures for functions
|
||||
//~^ ERROR the placeholder `_` is not allowed within types on item signatures for functions
|
||||
//~^^ ERROR the placeholder `_` is not allowed within types on item signatures for functions
|
||||
|
||||
struct FnTest9;
|
||||
|
||||
impl FnTest9 {
|
||||
fn fn_test9(&self) -> _ { () }
|
||||
//~^ ERROR the type placeholder `_` is not allowed within types on item signatures for return types
|
||||
//~^ ERROR the placeholder `_` is not allowed within types on item signatures for return types
|
||||
|
||||
fn fn_test10(&self, _x : _) { }
|
||||
//~^ ERROR the type placeholder `_` is not allowed within types on item signatures for functions
|
||||
//~^ ERROR the placeholder `_` is not allowed within types on item signatures for functions
|
||||
}
|
||||
|
||||
impl Clone for FnTest9 {
|
||||
fn clone(&self) -> _ { FnTest9 }
|
||||
//~^ ERROR the type placeholder `_` is not allowed within types on item signatures for return types
|
||||
//~^ ERROR the placeholder `_` is not allowed within types on item signatures for return types
|
||||
|
||||
fn clone_from(&mut self, other: _) { *self = FnTest9; }
|
||||
//~^ ERROR the type placeholder `_` is not allowed within types on item signatures for functions
|
||||
//~^ ERROR the placeholder `_` is not allowed within types on item signatures for functions
|
||||
}
|
||||
|
||||
struct FnTest10 {
|
||||
a: _,
|
||||
//~^ ERROR the type placeholder `_` is not allowed within types on item signatures for structs
|
||||
//~^ ERROR the placeholder `_` is not allowed within types on item signatures for structs
|
||||
b: (_, _),
|
||||
}
|
||||
|
||||
fn fn_test11(_: _) -> (_, _) { panic!() }
|
||||
//~^ ERROR the type placeholder `_` is not allowed within types on item signatures for return types
|
||||
//~^ ERROR the placeholder `_` is not allowed within types on item signatures for return types
|
||||
//~| ERROR type annotations needed
|
||||
|
||||
fn fn_test12(x: i32) -> (_, _) { (x, x) }
|
||||
//~^ ERROR the type placeholder `_` is not allowed within types on item signatures for return types
|
||||
//~^ ERROR the placeholder `_` is not allowed within types on item signatures for return types
|
||||
|
||||
fn fn_test13(x: _) -> (i32, _) { (x, x) }
|
||||
//~^ ERROR the type placeholder `_` is not allowed within types on item signatures for return types
|
||||
//~^ ERROR the placeholder `_` is not allowed within types on item signatures for return types
|
||||
}
|
||||
|
||||
trait T {
|
||||
fn method_test1(&self, x: _);
|
||||
//~^ ERROR the type placeholder `_` is not allowed within types on item signatures for functions
|
||||
//~^ ERROR the placeholder `_` is not allowed within types on item signatures for functions
|
||||
fn method_test2(&self, x: _) -> _;
|
||||
//~^ ERROR the type placeholder `_` is not allowed within types on item signatures for functions
|
||||
//~^ ERROR the placeholder `_` is not allowed within types on item signatures for functions
|
||||
fn method_test3(&self) -> _;
|
||||
//~^ ERROR the type placeholder `_` is not allowed within types on item signatures for functions
|
||||
//~^ ERROR the placeholder `_` is not allowed within types on item signatures for functions
|
||||
fn assoc_fn_test1(x: _);
|
||||
//~^ ERROR the type placeholder `_` is not allowed within types on item signatures for functions
|
||||
//~^ ERROR the placeholder `_` is not allowed within types on item signatures for functions
|
||||
fn assoc_fn_test2(x: _) -> _;
|
||||
//~^ ERROR the type placeholder `_` is not allowed within types on item signatures for functions
|
||||
//~^ ERROR the placeholder `_` is not allowed within types on item signatures for functions
|
||||
fn assoc_fn_test3() -> _;
|
||||
//~^ ERROR the type placeholder `_` is not allowed within types on item signatures for functions
|
||||
//~^ ERROR the placeholder `_` is not allowed within types on item signatures for functions
|
||||
}
|
||||
|
||||
struct BadStruct<_>(_);
|
||||
//~^ ERROR expected identifier, found reserved identifier `_`
|
||||
//~| ERROR the type placeholder `_` is not allowed within types on item signatures for structs
|
||||
//~| ERROR the placeholder `_` is not allowed within types on item signatures for structs
|
||||
trait BadTrait<_> {}
|
||||
//~^ ERROR expected identifier, found reserved identifier `_`
|
||||
impl BadTrait<_> for BadStruct<_> {}
|
||||
//~^ ERROR the type placeholder `_` is not allowed within types on item signatures for implementations
|
||||
//~^ ERROR the placeholder `_` is not allowed within types on item signatures for implementations
|
||||
|
||||
fn impl_trait() -> impl BadTrait<_> {
|
||||
//~^ ERROR the type placeholder `_` is not allowed within types on item signatures for opaque types
|
||||
//~^ ERROR the placeholder `_` is not allowed within types on item signatures for opaque types
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
|
|
@ -168,19 +168,19 @@ struct BadStruct1<_, _>(_);
|
|||
//~^ ERROR expected identifier, found reserved identifier `_`
|
||||
//~| ERROR expected identifier, found reserved identifier `_`
|
||||
//~| ERROR the name `_` is already used
|
||||
//~| ERROR the type placeholder `_` is not allowed within types on item signatures for structs
|
||||
//~| ERROR the placeholder `_` is not allowed within types on item signatures for structs
|
||||
struct BadStruct2<_, T>(_, T);
|
||||
//~^ ERROR expected identifier, found reserved identifier `_`
|
||||
//~| ERROR the type placeholder `_` is not allowed within types on item signatures for structs
|
||||
//~| ERROR the placeholder `_` is not allowed within types on item signatures for structs
|
||||
|
||||
type X = Box<_>;
|
||||
//~^ ERROR the type placeholder `_` is not allowed within types on item signatures for type aliases
|
||||
//~^ ERROR the placeholder `_` is not allowed within types on item signatures for type aliases
|
||||
|
||||
struct Struct;
|
||||
trait Trait<T> {}
|
||||
impl Trait<usize> for Struct {}
|
||||
type Y = impl Trait<_>;
|
||||
//~^ ERROR the type placeholder `_` is not allowed within types on item signatures for opaque types
|
||||
//~^ ERROR the placeholder `_` is not allowed within types on item signatures for opaque types
|
||||
fn foo() -> Y {
|
||||
Struct
|
||||
}
|
||||
|
|
@ -188,25 +188,25 @@ fn foo() -> Y {
|
|||
trait Qux {
|
||||
type A;
|
||||
type B = _;
|
||||
//~^ ERROR the type placeholder `_` is not allowed within types on item signatures for associated types
|
||||
//~^ ERROR the placeholder `_` is not allowed within types on item signatures for associated types
|
||||
const C: _;
|
||||
//~^ ERROR the type placeholder `_` is not allowed within types on item signatures for constants
|
||||
//~^ ERROR the placeholder `_` is not allowed within types on item signatures for constants
|
||||
const D: _ = 42;
|
||||
//~^ ERROR the type placeholder `_` is not allowed within types on item signatures for constants
|
||||
//~^ ERROR the placeholder `_` is not allowed within types on item signatures for constants
|
||||
// type E: _; // FIXME: make the parser propagate the existence of `B`
|
||||
type F: std::ops::Fn(_);
|
||||
//~^ ERROR the type placeholder `_` is not allowed within types on item signatures for associated types
|
||||
//~^ ERROR the placeholder `_` is not allowed within types on item signatures for associated types
|
||||
}
|
||||
impl Qux for Struct {
|
||||
type A = _;
|
||||
//~^ ERROR the type placeholder `_` is not allowed within types on item signatures for associated types
|
||||
//~^ ERROR the placeholder `_` is not allowed within types on item signatures for associated types
|
||||
type B = _;
|
||||
//~^ ERROR the type placeholder `_` is not allowed within types on item signatures for associated types
|
||||
//~^ ERROR the placeholder `_` is not allowed within types on item signatures for associated types
|
||||
const C: _;
|
||||
//~^ ERROR the type placeholder `_` is not allowed within types on item signatures for constants
|
||||
//~^ ERROR the placeholder `_` is not allowed within types on item signatures for constants
|
||||
//~| ERROR associated constant in `impl` without body
|
||||
const D: _ = 42;
|
||||
//~^ ERROR the type placeholder `_` is not allowed within types on item signatures for constants
|
||||
//~^ ERROR the placeholder `_` is not allowed within types on item signatures for constants
|
||||
}
|
||||
|
||||
fn map<T>(_: fn() -> Option<&'static T>) -> Option<T> {
|
||||
|
|
@ -214,9 +214,9 @@ fn map<T>(_: fn() -> Option<&'static T>) -> Option<T> {
|
|||
}
|
||||
|
||||
fn value() -> Option<&'static _> {
|
||||
//~^ ERROR the type placeholder `_` is not allowed within types on item signatures for return types
|
||||
//~^ ERROR the placeholder `_` is not allowed within types on item signatures for return types
|
||||
Option::<&'static u8>::None
|
||||
}
|
||||
|
||||
const _: Option<_> = map(value);
|
||||
//~^ ERROR the type placeholder `_` is not allowed within types on item signatures for constants
|
||||
//~^ ERROR the placeholder `_` is not allowed within types on item signatures for constants
|
||||
|
|
|
|||
|
|
@ -44,7 +44,7 @@ LL | struct BadStruct1<_, _>(_);
|
|||
| |
|
||||
| first use of `_`
|
||||
|
||||
error[E0121]: the type placeholder `_` is not allowed within types on item signatures for return types
|
||||
error[E0121]: the placeholder `_` is not allowed within types on item signatures for return types
|
||||
--> $DIR/typeck_type_placeholder_item.rs:7:14
|
||||
|
|
||||
LL | fn test() -> _ { 5 }
|
||||
|
|
@ -53,7 +53,7 @@ LL | fn test() -> _ { 5 }
|
|||
| not allowed in type signatures
|
||||
| help: replace with the correct return type: `i32`
|
||||
|
||||
error[E0121]: the type placeholder `_` is not allowed within types on item signatures for return types
|
||||
error[E0121]: the placeholder `_` is not allowed within types on item signatures for return types
|
||||
--> $DIR/typeck_type_placeholder_item.rs:10:16
|
||||
|
|
||||
LL | fn test2() -> (_, _) { (5, 5) }
|
||||
|
|
@ -63,7 +63,7 @@ LL | fn test2() -> (_, _) { (5, 5) }
|
|||
| |not allowed in type signatures
|
||||
| help: replace with the correct return type: `(i32, i32)`
|
||||
|
||||
error[E0121]: the type placeholder `_` is not allowed within types on item signatures for static variables
|
||||
error[E0121]: the placeholder `_` is not allowed within types on item signatures for static variables
|
||||
--> $DIR/typeck_type_placeholder_item.rs:13:15
|
||||
|
|
||||
LL | static TEST3: _ = "test";
|
||||
|
|
@ -72,7 +72,7 @@ LL | static TEST3: _ = "test";
|
|||
| not allowed in type signatures
|
||||
| help: replace with the correct type: `&str`
|
||||
|
||||
error[E0121]: the type placeholder `_` is not allowed within types on item signatures for static variables
|
||||
error[E0121]: the placeholder `_` is not allowed within types on item signatures for static variables
|
||||
--> $DIR/typeck_type_placeholder_item.rs:16:15
|
||||
|
|
||||
LL | static TEST4: _ = 145;
|
||||
|
|
@ -81,13 +81,13 @@ LL | static TEST4: _ = 145;
|
|||
| not allowed in type signatures
|
||||
| help: replace with the correct type: `i32`
|
||||
|
||||
error[E0121]: the type placeholder `_` is not allowed within types on item signatures for static variables
|
||||
error[E0121]: the placeholder `_` is not allowed within types on item signatures for static variables
|
||||
--> $DIR/typeck_type_placeholder_item.rs:19:15
|
||||
|
|
||||
LL | static TEST5: (_, _) = (1, 2);
|
||||
| ^^^^^^ not allowed in type signatures
|
||||
|
||||
error[E0121]: the type placeholder `_` is not allowed within types on item signatures for functions
|
||||
error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions
|
||||
--> $DIR/typeck_type_placeholder_item.rs:22:13
|
||||
|
|
||||
LL | fn test6(_: _) { }
|
||||
|
|
@ -98,7 +98,7 @@ help: use type parameters instead
|
|||
LL | fn test6<T>(_: T) { }
|
||||
| +++ ~
|
||||
|
||||
error[E0121]: the type placeholder `_` is not allowed within types on item signatures for functions
|
||||
error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions
|
||||
--> $DIR/typeck_type_placeholder_item.rs:25:18
|
||||
|
|
||||
LL | fn test6_b<T>(_: _, _: T) { }
|
||||
|
|
@ -109,7 +109,7 @@ help: use type parameters instead
|
|||
LL | fn test6_b<T, U>(_: U, _: T) { }
|
||||
| +++ ~
|
||||
|
||||
error[E0121]: the type placeholder `_` is not allowed within types on item signatures for functions
|
||||
error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions
|
||||
--> $DIR/typeck_type_placeholder_item.rs:28:30
|
||||
|
|
||||
LL | fn test6_c<T, K, L, A, B>(_: _, _: (T, K, L, A, B)) { }
|
||||
|
|
@ -120,7 +120,7 @@ help: use type parameters instead
|
|||
LL | fn test6_c<T, K, L, A, B, U>(_: U, _: (T, K, L, A, B)) { }
|
||||
| +++ ~
|
||||
|
||||
error[E0121]: the type placeholder `_` is not allowed within types on item signatures for functions
|
||||
error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions
|
||||
--> $DIR/typeck_type_placeholder_item.rs:31:13
|
||||
|
|
||||
LL | fn test7(x: _) { let _x: usize = x; }
|
||||
|
|
@ -131,7 +131,7 @@ help: use type parameters instead
|
|||
LL | fn test7<T>(x: T) { let _x: usize = x; }
|
||||
| +++ ~
|
||||
|
||||
error[E0121]: the type placeholder `_` is not allowed within types on item signatures for functions
|
||||
error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions
|
||||
--> $DIR/typeck_type_placeholder_item.rs:34:22
|
||||
|
|
||||
LL | fn test8(_f: fn() -> _) { }
|
||||
|
|
@ -140,7 +140,7 @@ LL | fn test8(_f: fn() -> _) { }
|
|||
| not allowed in type signatures
|
||||
| help: use type parameters instead: `T`
|
||||
|
||||
error[E0121]: the type placeholder `_` is not allowed within types on item signatures for functions
|
||||
error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions
|
||||
--> $DIR/typeck_type_placeholder_item.rs:34:22
|
||||
|
|
||||
LL | fn test8(_f: fn() -> _) { }
|
||||
|
|
@ -151,7 +151,7 @@ help: use type parameters instead
|
|||
LL | fn test8<T>(_f: fn() -> T) { }
|
||||
| +++ ~
|
||||
|
||||
error[E0121]: the type placeholder `_` is not allowed within types on item signatures for return types
|
||||
error[E0121]: the placeholder `_` is not allowed within types on item signatures for return types
|
||||
--> $DIR/typeck_type_placeholder_item.rs:48:26
|
||||
|
|
||||
LL | fn test11(x: &usize) -> &_ {
|
||||
|
|
@ -160,7 +160,7 @@ LL | fn test11(x: &usize) -> &_ {
|
|||
| |not allowed in type signatures
|
||||
| help: replace with the correct return type: `&'static &'static usize`
|
||||
|
||||
error[E0121]: the type placeholder `_` is not allowed within types on item signatures for return types
|
||||
error[E0121]: the placeholder `_` is not allowed within types on item signatures for return types
|
||||
--> $DIR/typeck_type_placeholder_item.rs:53:52
|
||||
|
|
||||
LL | unsafe fn test12(x: *const usize) -> *const *const _ {
|
||||
|
|
@ -169,7 +169,7 @@ LL | unsafe fn test12(x: *const usize) -> *const *const _ {
|
|||
| | not allowed in type signatures
|
||||
| help: replace with the correct return type: `*const *const usize`
|
||||
|
||||
error[E0121]: the type placeholder `_` is not allowed within types on item signatures for structs
|
||||
error[E0121]: the placeholder `_` is not allowed within types on item signatures for structs
|
||||
--> $DIR/typeck_type_placeholder_item.rs:67:8
|
||||
|
|
||||
LL | a: _,
|
||||
|
|
@ -194,7 +194,7 @@ error: missing type for `static` item
|
|||
LL | static A = 42;
|
||||
| ^ help: provide a type for the static variable: `A: i32`
|
||||
|
||||
error[E0121]: the type placeholder `_` is not allowed within types on item signatures for static variables
|
||||
error[E0121]: the placeholder `_` is not allowed within types on item signatures for static variables
|
||||
--> $DIR/typeck_type_placeholder_item.rs:75:15
|
||||
|
|
||||
LL | static B: _ = 42;
|
||||
|
|
@ -203,13 +203,13 @@ LL | static B: _ = 42;
|
|||
| not allowed in type signatures
|
||||
| help: replace with the correct type: `i32`
|
||||
|
||||
error[E0121]: the type placeholder `_` is not allowed within types on item signatures for static variables
|
||||
error[E0121]: the placeholder `_` is not allowed within types on item signatures for static variables
|
||||
--> $DIR/typeck_type_placeholder_item.rs:77:15
|
||||
|
|
||||
LL | static C: Option<_> = Some(42);
|
||||
| ^^^^^^^^^ not allowed in type signatures
|
||||
|
||||
error[E0121]: the type placeholder `_` is not allowed within types on item signatures for return types
|
||||
error[E0121]: the placeholder `_` is not allowed within types on item signatures for return types
|
||||
--> $DIR/typeck_type_placeholder_item.rs:79:21
|
||||
|
|
||||
LL | fn fn_test() -> _ { 5 }
|
||||
|
|
@ -218,7 +218,7 @@ LL | fn fn_test() -> _ { 5 }
|
|||
| not allowed in type signatures
|
||||
| help: replace with the correct return type: `i32`
|
||||
|
||||
error[E0121]: the type placeholder `_` is not allowed within types on item signatures for return types
|
||||
error[E0121]: the placeholder `_` is not allowed within types on item signatures for return types
|
||||
--> $DIR/typeck_type_placeholder_item.rs:82:23
|
||||
|
|
||||
LL | fn fn_test2() -> (_, _) { (5, 5) }
|
||||
|
|
@ -228,7 +228,7 @@ LL | fn fn_test2() -> (_, _) { (5, 5) }
|
|||
| |not allowed in type signatures
|
||||
| help: replace with the correct return type: `(i32, i32)`
|
||||
|
||||
error[E0121]: the type placeholder `_` is not allowed within types on item signatures for static variables
|
||||
error[E0121]: the placeholder `_` is not allowed within types on item signatures for static variables
|
||||
--> $DIR/typeck_type_placeholder_item.rs:85:22
|
||||
|
|
||||
LL | static FN_TEST3: _ = "test";
|
||||
|
|
@ -237,7 +237,7 @@ LL | static FN_TEST3: _ = "test";
|
|||
| not allowed in type signatures
|
||||
| help: replace with the correct type: `&str`
|
||||
|
||||
error[E0121]: the type placeholder `_` is not allowed within types on item signatures for static variables
|
||||
error[E0121]: the placeholder `_` is not allowed within types on item signatures for static variables
|
||||
--> $DIR/typeck_type_placeholder_item.rs:88:22
|
||||
|
|
||||
LL | static FN_TEST4: _ = 145;
|
||||
|
|
@ -246,13 +246,13 @@ LL | static FN_TEST4: _ = 145;
|
|||
| not allowed in type signatures
|
||||
| help: replace with the correct type: `i32`
|
||||
|
||||
error[E0121]: the type placeholder `_` is not allowed within types on item signatures for static variables
|
||||
error[E0121]: the placeholder `_` is not allowed within types on item signatures for static variables
|
||||
--> $DIR/typeck_type_placeholder_item.rs:91:22
|
||||
|
|
||||
LL | static FN_TEST5: (_, _) = (1, 2);
|
||||
| ^^^^^^ not allowed in type signatures
|
||||
|
||||
error[E0121]: the type placeholder `_` is not allowed within types on item signatures for functions
|
||||
error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions
|
||||
--> $DIR/typeck_type_placeholder_item.rs:94:20
|
||||
|
|
||||
LL | fn fn_test6(_: _) { }
|
||||
|
|
@ -263,7 +263,7 @@ help: use type parameters instead
|
|||
LL | fn fn_test6<T>(_: T) { }
|
||||
| +++ ~
|
||||
|
||||
error[E0121]: the type placeholder `_` is not allowed within types on item signatures for functions
|
||||
error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions
|
||||
--> $DIR/typeck_type_placeholder_item.rs:97:20
|
||||
|
|
||||
LL | fn fn_test7(x: _) { let _x: usize = x; }
|
||||
|
|
@ -274,7 +274,7 @@ help: use type parameters instead
|
|||
LL | fn fn_test7<T>(x: T) { let _x: usize = x; }
|
||||
| +++ ~
|
||||
|
||||
error[E0121]: the type placeholder `_` is not allowed within types on item signatures for functions
|
||||
error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions
|
||||
--> $DIR/typeck_type_placeholder_item.rs:100:29
|
||||
|
|
||||
LL | fn fn_test8(_f: fn() -> _) { }
|
||||
|
|
@ -283,7 +283,7 @@ LL | fn fn_test8(_f: fn() -> _) { }
|
|||
| not allowed in type signatures
|
||||
| help: use type parameters instead: `T`
|
||||
|
||||
error[E0121]: the type placeholder `_` is not allowed within types on item signatures for functions
|
||||
error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions
|
||||
--> $DIR/typeck_type_placeholder_item.rs:100:29
|
||||
|
|
||||
LL | fn fn_test8(_f: fn() -> _) { }
|
||||
|
|
@ -294,7 +294,7 @@ help: use type parameters instead
|
|||
LL | fn fn_test8<T>(_f: fn() -> T) { }
|
||||
| +++ ~
|
||||
|
||||
error[E0121]: the type placeholder `_` is not allowed within types on item signatures for structs
|
||||
error[E0121]: the placeholder `_` is not allowed within types on item signatures for structs
|
||||
--> $DIR/typeck_type_placeholder_item.rs:123:12
|
||||
|
|
||||
LL | a: _,
|
||||
|
|
@ -319,7 +319,7 @@ error[E0282]: type annotations needed
|
|||
LL | fn fn_test11(_: _) -> (_, _) { panic!() }
|
||||
| ^ cannot infer type
|
||||
|
||||
error[E0121]: the type placeholder `_` is not allowed within types on item signatures for return types
|
||||
error[E0121]: the placeholder `_` is not allowed within types on item signatures for return types
|
||||
--> $DIR/typeck_type_placeholder_item.rs:128:28
|
||||
|
|
||||
LL | fn fn_test11(_: _) -> (_, _) { panic!() }
|
||||
|
|
@ -327,7 +327,7 @@ LL | fn fn_test11(_: _) -> (_, _) { panic!() }
|
|||
| |
|
||||
| not allowed in type signatures
|
||||
|
||||
error[E0121]: the type placeholder `_` is not allowed within types on item signatures for return types
|
||||
error[E0121]: the placeholder `_` is not allowed within types on item signatures for return types
|
||||
--> $DIR/typeck_type_placeholder_item.rs:132:30
|
||||
|
|
||||
LL | fn fn_test12(x: i32) -> (_, _) { (x, x) }
|
||||
|
|
@ -337,7 +337,7 @@ LL | fn fn_test12(x: i32) -> (_, _) { (x, x) }
|
|||
| |not allowed in type signatures
|
||||
| help: replace with the correct return type: `(i32, i32)`
|
||||
|
||||
error[E0121]: the type placeholder `_` is not allowed within types on item signatures for return types
|
||||
error[E0121]: the placeholder `_` is not allowed within types on item signatures for return types
|
||||
--> $DIR/typeck_type_placeholder_item.rs:135:33
|
||||
|
|
||||
LL | fn fn_test13(x: _) -> (i32, _) { (x, x) }
|
||||
|
|
@ -346,7 +346,7 @@ LL | fn fn_test13(x: _) -> (i32, _) { (x, x) }
|
|||
| | not allowed in type signatures
|
||||
| help: replace with the correct return type: `(i32, i32)`
|
||||
|
||||
error[E0121]: the type placeholder `_` is not allowed within types on item signatures for structs
|
||||
error[E0121]: the placeholder `_` is not allowed within types on item signatures for structs
|
||||
--> $DIR/typeck_type_placeholder_item.rs:154:21
|
||||
|
|
||||
LL | struct BadStruct<_>(_);
|
||||
|
|
@ -357,7 +357,7 @@ help: use type parameters instead
|
|||
LL | struct BadStruct<T>(T);
|
||||
| ~ ~
|
||||
|
||||
error[E0121]: the type placeholder `_` is not allowed within types on item signatures for implementations
|
||||
error[E0121]: the placeholder `_` is not allowed within types on item signatures for implementations
|
||||
--> $DIR/typeck_type_placeholder_item.rs:159:15
|
||||
|
|
||||
LL | impl BadTrait<_> for BadStruct<_> {}
|
||||
|
|
@ -370,13 +370,13 @@ help: use type parameters instead
|
|||
LL | impl<T> BadTrait<T> for BadStruct<T> {}
|
||||
| +++ ~ ~
|
||||
|
||||
error[E0121]: the type placeholder `_` is not allowed within types on item signatures for opaque types
|
||||
error[E0121]: the placeholder `_` is not allowed within types on item signatures for opaque types
|
||||
--> $DIR/typeck_type_placeholder_item.rs:162:34
|
||||
|
|
||||
LL | fn impl_trait() -> impl BadTrait<_> {
|
||||
| ^ not allowed in type signatures
|
||||
|
||||
error[E0121]: the type placeholder `_` is not allowed within types on item signatures for structs
|
||||
error[E0121]: the placeholder `_` is not allowed within types on item signatures for structs
|
||||
--> $DIR/typeck_type_placeholder_item.rs:167:25
|
||||
|
|
||||
LL | struct BadStruct1<_, _>(_);
|
||||
|
|
@ -387,7 +387,7 @@ help: use type parameters instead
|
|||
LL | struct BadStruct1<T, _>(T);
|
||||
| ~ ~
|
||||
|
||||
error[E0121]: the type placeholder `_` is not allowed within types on item signatures for structs
|
||||
error[E0121]: the placeholder `_` is not allowed within types on item signatures for structs
|
||||
--> $DIR/typeck_type_placeholder_item.rs:172:25
|
||||
|
|
||||
LL | struct BadStruct2<_, T>(_, T);
|
||||
|
|
@ -398,19 +398,19 @@ help: use type parameters instead
|
|||
LL | struct BadStruct2<U, T>(U, T);
|
||||
| ~ ~
|
||||
|
||||
error[E0121]: the type placeholder `_` is not allowed within types on item signatures for type aliases
|
||||
error[E0121]: the placeholder `_` is not allowed within types on item signatures for type aliases
|
||||
--> $DIR/typeck_type_placeholder_item.rs:176:14
|
||||
|
|
||||
LL | type X = Box<_>;
|
||||
| ^ not allowed in type signatures
|
||||
|
||||
error[E0121]: the type placeholder `_` is not allowed within types on item signatures for opaque types
|
||||
error[E0121]: the placeholder `_` is not allowed within types on item signatures for opaque types
|
||||
--> $DIR/typeck_type_placeholder_item.rs:182:21
|
||||
|
|
||||
LL | type Y = impl Trait<_>;
|
||||
| ^ not allowed in type signatures
|
||||
|
||||
error[E0121]: the type placeholder `_` is not allowed within types on item signatures for return types
|
||||
error[E0121]: the placeholder `_` is not allowed within types on item signatures for return types
|
||||
--> $DIR/typeck_type_placeholder_item.rs:216:31
|
||||
|
|
||||
LL | fn value() -> Option<&'static _> {
|
||||
|
|
@ -419,7 +419,7 @@ LL | fn value() -> Option<&'static _> {
|
|||
| | not allowed in type signatures
|
||||
| help: replace with the correct return type: `Option<&'static u8>`
|
||||
|
||||
error[E0121]: the type placeholder `_` is not allowed within types on item signatures for constants
|
||||
error[E0121]: the placeholder `_` is not allowed within types on item signatures for constants
|
||||
--> $DIR/typeck_type_placeholder_item.rs:221:10
|
||||
|
|
||||
LL | const _: Option<_> = map(value);
|
||||
|
|
@ -428,7 +428,7 @@ LL | const _: Option<_> = map(value);
|
|||
| not allowed in type signatures
|
||||
| help: replace with the correct type: `Option<u8>`
|
||||
|
||||
error[E0121]: the type placeholder `_` is not allowed within types on item signatures for functions
|
||||
error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions
|
||||
--> $DIR/typeck_type_placeholder_item.rs:140:31
|
||||
|
|
||||
LL | fn method_test1(&self, x: _);
|
||||
|
|
@ -439,7 +439,7 @@ help: use type parameters instead
|
|||
LL | fn method_test1<T>(&self, x: T);
|
||||
| +++ ~
|
||||
|
||||
error[E0121]: the type placeholder `_` is not allowed within types on item signatures for functions
|
||||
error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions
|
||||
--> $DIR/typeck_type_placeholder_item.rs:142:31
|
||||
|
|
||||
LL | fn method_test2(&self, x: _) -> _;
|
||||
|
|
@ -452,7 +452,7 @@ help: use type parameters instead
|
|||
LL | fn method_test2<T>(&self, x: T) -> T;
|
||||
| +++ ~ ~
|
||||
|
||||
error[E0121]: the type placeholder `_` is not allowed within types on item signatures for functions
|
||||
error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions
|
||||
--> $DIR/typeck_type_placeholder_item.rs:144:31
|
||||
|
|
||||
LL | fn method_test3(&self) -> _;
|
||||
|
|
@ -463,7 +463,7 @@ help: use type parameters instead
|
|||
LL | fn method_test3<T>(&self) -> T;
|
||||
| +++ ~
|
||||
|
||||
error[E0121]: the type placeholder `_` is not allowed within types on item signatures for functions
|
||||
error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions
|
||||
--> $DIR/typeck_type_placeholder_item.rs:146:26
|
||||
|
|
||||
LL | fn assoc_fn_test1(x: _);
|
||||
|
|
@ -474,7 +474,7 @@ help: use type parameters instead
|
|||
LL | fn assoc_fn_test1<T>(x: T);
|
||||
| +++ ~
|
||||
|
||||
error[E0121]: the type placeholder `_` is not allowed within types on item signatures for functions
|
||||
error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions
|
||||
--> $DIR/typeck_type_placeholder_item.rs:148:26
|
||||
|
|
||||
LL | fn assoc_fn_test2(x: _) -> _;
|
||||
|
|
@ -487,7 +487,7 @@ help: use type parameters instead
|
|||
LL | fn assoc_fn_test2<T>(x: T) -> T;
|
||||
| +++ ~ ~
|
||||
|
||||
error[E0121]: the type placeholder `_` is not allowed within types on item signatures for functions
|
||||
error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions
|
||||
--> $DIR/typeck_type_placeholder_item.rs:150:28
|
||||
|
|
||||
LL | fn assoc_fn_test3() -> _;
|
||||
|
|
@ -498,19 +498,19 @@ help: use type parameters instead
|
|||
LL | fn assoc_fn_test3<T>() -> T;
|
||||
| +++ ~
|
||||
|
||||
error[E0121]: the type placeholder `_` is not allowed within types on item signatures for associated types
|
||||
error[E0121]: the placeholder `_` is not allowed within types on item signatures for associated types
|
||||
--> $DIR/typeck_type_placeholder_item.rs:190:14
|
||||
|
|
||||
LL | type B = _;
|
||||
| ^ not allowed in type signatures
|
||||
|
||||
error[E0121]: the type placeholder `_` is not allowed within types on item signatures for constants
|
||||
error[E0121]: the placeholder `_` is not allowed within types on item signatures for constants
|
||||
--> $DIR/typeck_type_placeholder_item.rs:192:14
|
||||
|
|
||||
LL | const C: _;
|
||||
| ^ not allowed in type signatures
|
||||
|
||||
error[E0121]: the type placeholder `_` is not allowed within types on item signatures for constants
|
||||
error[E0121]: the placeholder `_` is not allowed within types on item signatures for constants
|
||||
--> $DIR/typeck_type_placeholder_item.rs:194:14
|
||||
|
|
||||
LL | const D: _ = 42;
|
||||
|
|
@ -519,13 +519,13 @@ LL | const D: _ = 42;
|
|||
| not allowed in type signatures
|
||||
| help: replace with the correct type: `i32`
|
||||
|
||||
error[E0121]: the type placeholder `_` is not allowed within types on item signatures for associated types
|
||||
error[E0121]: the placeholder `_` is not allowed within types on item signatures for associated types
|
||||
--> $DIR/typeck_type_placeholder_item.rs:197:26
|
||||
|
|
||||
LL | type F: std::ops::Fn(_);
|
||||
| ^ not allowed in type signatures
|
||||
|
||||
error[E0121]: the type placeholder `_` is not allowed within types on item signatures for return types
|
||||
error[E0121]: the placeholder `_` is not allowed within types on item signatures for return types
|
||||
--> $DIR/typeck_type_placeholder_item.rs:41:24
|
||||
|
|
||||
LL | fn test9(&self) -> _ { () }
|
||||
|
|
@ -534,7 +534,7 @@ LL | fn test9(&self) -> _ { () }
|
|||
| not allowed in type signatures
|
||||
| help: replace with the correct return type: `()`
|
||||
|
||||
error[E0121]: the type placeholder `_` is not allowed within types on item signatures for functions
|
||||
error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions
|
||||
--> $DIR/typeck_type_placeholder_item.rs:44:27
|
||||
|
|
||||
LL | fn test10(&self, _x : _) { }
|
||||
|
|
@ -545,7 +545,7 @@ help: use type parameters instead
|
|||
LL | fn test10<T>(&self, _x : T) { }
|
||||
| +++ ~
|
||||
|
||||
error[E0121]: the type placeholder `_` is not allowed within types on item signatures for return types
|
||||
error[E0121]: the placeholder `_` is not allowed within types on item signatures for return types
|
||||
--> $DIR/typeck_type_placeholder_item.rs:59:24
|
||||
|
|
||||
LL | fn clone(&self) -> _ { Test9 }
|
||||
|
|
@ -554,7 +554,7 @@ LL | fn clone(&self) -> _ { Test9 }
|
|||
| not allowed in type signatures
|
||||
| help: replace with the correct return type: `Test9`
|
||||
|
||||
error[E0121]: the type placeholder `_` is not allowed within types on item signatures for functions
|
||||
error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions
|
||||
--> $DIR/typeck_type_placeholder_item.rs:62:37
|
||||
|
|
||||
LL | fn clone_from(&mut self, other: _) { *self = Test9; }
|
||||
|
|
@ -565,7 +565,7 @@ help: use type parameters instead
|
|||
LL | fn clone_from<T>(&mut self, other: T) { *self = Test9; }
|
||||
| +++ ~
|
||||
|
||||
error[E0121]: the type placeholder `_` is not allowed within types on item signatures for return types
|
||||
error[E0121]: the placeholder `_` is not allowed within types on item signatures for return types
|
||||
--> $DIR/typeck_type_placeholder_item.rs:107:31
|
||||
|
|
||||
LL | fn fn_test9(&self) -> _ { () }
|
||||
|
|
@ -574,7 +574,7 @@ LL | fn fn_test9(&self) -> _ { () }
|
|||
| not allowed in type signatures
|
||||
| help: replace with the correct return type: `()`
|
||||
|
||||
error[E0121]: the type placeholder `_` is not allowed within types on item signatures for functions
|
||||
error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions
|
||||
--> $DIR/typeck_type_placeholder_item.rs:110:34
|
||||
|
|
||||
LL | fn fn_test10(&self, _x : _) { }
|
||||
|
|
@ -585,7 +585,7 @@ help: use type parameters instead
|
|||
LL | fn fn_test10<T>(&self, _x : T) { }
|
||||
| +++ ~
|
||||
|
||||
error[E0121]: the type placeholder `_` is not allowed within types on item signatures for return types
|
||||
error[E0121]: the placeholder `_` is not allowed within types on item signatures for return types
|
||||
--> $DIR/typeck_type_placeholder_item.rs:115:28
|
||||
|
|
||||
LL | fn clone(&self) -> _ { FnTest9 }
|
||||
|
|
@ -594,7 +594,7 @@ LL | fn clone(&self) -> _ { FnTest9 }
|
|||
| not allowed in type signatures
|
||||
| help: replace with the correct return type: `FnTest9`
|
||||
|
||||
error[E0121]: the type placeholder `_` is not allowed within types on item signatures for functions
|
||||
error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions
|
||||
--> $DIR/typeck_type_placeholder_item.rs:118:41
|
||||
|
|
||||
LL | fn clone_from(&mut self, other: _) { *self = FnTest9; }
|
||||
|
|
@ -605,25 +605,25 @@ help: use type parameters instead
|
|||
LL | fn clone_from<T>(&mut self, other: T) { *self = FnTest9; }
|
||||
| +++ ~
|
||||
|
||||
error[E0121]: the type placeholder `_` is not allowed within types on item signatures for associated types
|
||||
error[E0121]: the placeholder `_` is not allowed within types on item signatures for associated types
|
||||
--> $DIR/typeck_type_placeholder_item.rs:201:14
|
||||
|
|
||||
LL | type A = _;
|
||||
| ^ not allowed in type signatures
|
||||
|
||||
error[E0121]: the type placeholder `_` is not allowed within types on item signatures for associated types
|
||||
error[E0121]: the placeholder `_` is not allowed within types on item signatures for associated types
|
||||
--> $DIR/typeck_type_placeholder_item.rs:203:14
|
||||
|
|
||||
LL | type B = _;
|
||||
| ^ not allowed in type signatures
|
||||
|
||||
error[E0121]: the type placeholder `_` is not allowed within types on item signatures for constants
|
||||
error[E0121]: the placeholder `_` is not allowed within types on item signatures for constants
|
||||
--> $DIR/typeck_type_placeholder_item.rs:205:14
|
||||
|
|
||||
LL | const C: _;
|
||||
| ^ not allowed in type signatures
|
||||
|
||||
error[E0121]: the type placeholder `_` is not allowed within types on item signatures for constants
|
||||
error[E0121]: the placeholder `_` is not allowed within types on item signatures for constants
|
||||
--> $DIR/typeck_type_placeholder_item.rs:208:14
|
||||
|
|
||||
LL | const D: _ = 42;
|
||||
|
|
|
|||
|
|
@ -2,27 +2,27 @@
|
|||
// using the `_` type placeholder.
|
||||
|
||||
fn test1() -> _ { Some(42) }
|
||||
//~^ ERROR the type placeholder `_` is not allowed within types on item signatures for return types
|
||||
//~^ ERROR the placeholder `_` is not allowed within types on item signatures for return types
|
||||
|
||||
const TEST2: _ = 42u32;
|
||||
//~^ ERROR the type placeholder `_` is not allowed within types on item signatures for constants
|
||||
//~^ ERROR the placeholder `_` is not allowed within types on item signatures for constants
|
||||
|
||||
const TEST3: _ = Some(42);
|
||||
//~^ ERROR the type placeholder `_` is not allowed within types on item signatures for constants
|
||||
//~^ ERROR the placeholder `_` is not allowed within types on item signatures for constants
|
||||
|
||||
const TEST4: fn() -> _ = 42;
|
||||
//~^ ERROR the type placeholder `_` is not allowed within types on item signatures for functions
|
||||
//~^ ERROR the placeholder `_` is not allowed within types on item signatures for functions
|
||||
|
||||
trait Test5 {
|
||||
const TEST5: _ = 42;
|
||||
//~^ ERROR the type placeholder `_` is not allowed within types on item signatures for constants
|
||||
//~^ ERROR the placeholder `_` is not allowed within types on item signatures for constants
|
||||
}
|
||||
|
||||
struct Test6;
|
||||
|
||||
impl Test6 {
|
||||
const TEST6: _ = 13;
|
||||
//~^ ERROR the type placeholder `_` is not allowed within types on item signatures for constants
|
||||
//~^ ERROR the placeholder `_` is not allowed within types on item signatures for constants
|
||||
}
|
||||
|
||||
pub fn main() {
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
error[E0121]: the type placeholder `_` is not allowed within types on item signatures for return types
|
||||
error[E0121]: the placeholder `_` is not allowed within types on item signatures for return types
|
||||
--> $DIR/typeck_type_placeholder_item_help.rs:4:15
|
||||
|
|
||||
LL | fn test1() -> _ { Some(42) }
|
||||
|
|
@ -7,7 +7,7 @@ LL | fn test1() -> _ { Some(42) }
|
|||
| not allowed in type signatures
|
||||
| help: replace with the correct return type: `Option<i32>`
|
||||
|
||||
error[E0121]: the type placeholder `_` is not allowed within types on item signatures for constants
|
||||
error[E0121]: the placeholder `_` is not allowed within types on item signatures for constants
|
||||
--> $DIR/typeck_type_placeholder_item_help.rs:7:14
|
||||
|
|
||||
LL | const TEST2: _ = 42u32;
|
||||
|
|
@ -16,7 +16,7 @@ LL | const TEST2: _ = 42u32;
|
|||
| not allowed in type signatures
|
||||
| help: replace with the correct type: `u32`
|
||||
|
||||
error[E0121]: the type placeholder `_` is not allowed within types on item signatures for constants
|
||||
error[E0121]: the placeholder `_` is not allowed within types on item signatures for constants
|
||||
--> $DIR/typeck_type_placeholder_item_help.rs:10:14
|
||||
|
|
||||
LL | const TEST3: _ = Some(42);
|
||||
|
|
@ -25,13 +25,13 @@ LL | const TEST3: _ = Some(42);
|
|||
| not allowed in type signatures
|
||||
| help: replace with the correct type: `Option<i32>`
|
||||
|
||||
error[E0121]: the type placeholder `_` is not allowed within types on item signatures for functions
|
||||
error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions
|
||||
--> $DIR/typeck_type_placeholder_item_help.rs:13:22
|
||||
|
|
||||
LL | const TEST4: fn() -> _ = 42;
|
||||
| ^ not allowed in type signatures
|
||||
|
||||
error[E0121]: the type placeholder `_` is not allowed within types on item signatures for constants
|
||||
error[E0121]: the placeholder `_` is not allowed within types on item signatures for constants
|
||||
--> $DIR/typeck_type_placeholder_item_help.rs:17:18
|
||||
|
|
||||
LL | const TEST5: _ = 42;
|
||||
|
|
@ -40,7 +40,7 @@ LL | const TEST5: _ = 42;
|
|||
| not allowed in type signatures
|
||||
| help: replace with the correct type: `i32`
|
||||
|
||||
error[E0121]: the type placeholder `_` is not allowed within types on item signatures for constants
|
||||
error[E0121]: the placeholder `_` is not allowed within types on item signatures for constants
|
||||
--> $DIR/typeck_type_placeholder_item_help.rs:24:18
|
||||
|
|
||||
LL | const TEST6: _ = 13;
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
Subproject commit 8e9ccbf97a70259b6c6576e8fd7d77d28238737e
|
||||
Subproject commit 9700addc82111200a2150b9a796f62dd8e600ddf
|
||||
Loading…
Add table
Add a link
Reference in a new issue