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:
bors 2022-01-20 20:44:14 +00:00
commit 777bb86bcd
99 changed files with 1916 additions and 805 deletions

View file

@ -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),

View file

@ -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 {

View file

@ -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");
})
}

View file

@ -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);
}

View file

@ -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

View file

@ -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 {

View file

@ -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, .. }) => {

View file

@ -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)
}

View file

@ -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
}

View file

@ -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

View file

@ -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);

View file

@ -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());
}
}

View file

@ -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 })
}

View file

@ -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 {

View file

@ -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);
}

View file

@ -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');
}
}

View file

@ -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)),
}));

View file

@ -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],

View file

@ -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);
}

View file

@ -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

View file

@ -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) {

View file

@ -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);

View file

@ -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() {

View file

@ -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);

View file

@ -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>(),
)
}
}
}

View file

@ -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`].

View file

@ -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());

View file

@ -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()
};

View file

@ -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)
}
}
}

View file

@ -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,

View file

@ -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())?)
}

View file

@ -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,

View file

@ -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> {

View file

@ -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`.

View file

@ -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

View file

@ -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 {

View file

@ -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(

View file

@ -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,

View file

@ -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()

View file

@ -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'

View file

@ -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

View file

@ -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

View file

@ -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)

View file

@ -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'

View file

@ -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

View file

@ -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)

View 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 \"" })

View file

@ -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": ""})

View file

@ -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 }
}

View file

@ -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 }

View file

@ -0,0 +1,2 @@
<div class="docblock"><p>a</p>
</div>

View 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() {}

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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();
}

View file

@ -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`.

View 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
}

View 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`.

View file

@ -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() {}

View file

@ -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() -> _ {}

View file

@ -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";

View file

@ -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

View file

@ -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() -> _ {

View file

@ -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
)*
}
}

View file

@ -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();

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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() {}

View file

@ -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: &_) {}

View file

@ -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

View file

@ -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;

View file

@ -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
}

View file

@ -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) };

View file

@ -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)
}

View file

@ -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<_> {

View file

@ -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]
}

View file

@ -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;

View file

@ -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!();
}
}

View file

@ -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<_> {

View file

@ -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() -> _ = "";

View file

@ -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() {}

View file

@ -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>) -> _ {

View file

@ -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
}

View file

@ -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;

View file

@ -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: _;

View file

@ -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() {}

View file

@ -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<_> {}

View file

@ -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() {}

View file

@ -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;

View file

@ -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

View file

@ -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;

View file

@ -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() {

View file

@ -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