Auto merge of #146418 - matthiaskrgr:rollup-za0lrux, r=matthiaskrgr

Rollup of 8 pull requests

Successful merges:

 - rust-lang/rust#145327 (std: make address resolution weirdness local to SGX)
 - rust-lang/rust#145879 (default auto traits: use default supertraits instead of `Self: Trait` bounds on associated items)
 - rust-lang/rust#146123 (Suggest examples of format specifiers in error messages)
 - rust-lang/rust#146311 (Minor symbol comment fixes.)
 - rust-lang/rust#146322 (Make Barrier RefUnwindSafe again)
 - rust-lang/rust#146327 (Add tests for deref on pin)
 - rust-lang/rust#146340 (Strip frontmatter in fewer places)
 - rust-lang/rust#146342 (Improve C-variadic error messages: part 2)

r? `@ghost`
`@rustbot` modify labels: rollup
This commit is contained in:
bors 2025-09-10 21:30:05 +00:00
commit f4665ab836
81 changed files with 1607 additions and 858 deletions

View file

@ -2284,6 +2284,54 @@ pub struct FnSig {
pub span: Span, pub span: Span,
} }
impl FnSig {
/// Return a span encompassing the header, or where to insert it if empty.
pub fn header_span(&self) -> Span {
match self.header.ext {
Extern::Implicit(span) | Extern::Explicit(_, span) => {
return self.span.with_hi(span.hi());
}
Extern::None => {}
}
match self.header.safety {
Safety::Unsafe(span) | Safety::Safe(span) => return self.span.with_hi(span.hi()),
Safety::Default => {}
};
if let Some(coroutine_kind) = self.header.coroutine_kind {
return self.span.with_hi(coroutine_kind.span().hi());
}
if let Const::Yes(span) = self.header.constness {
return self.span.with_hi(span.hi());
}
self.span.shrink_to_lo()
}
/// The span of the header's safety, or where to insert it if empty.
pub fn safety_span(&self) -> Span {
match self.header.safety {
Safety::Unsafe(span) | Safety::Safe(span) => span,
Safety::Default => {
// Insert after the `coroutine_kind` if available.
if let Some(extern_span) = self.header.ext.span() {
return extern_span.shrink_to_lo();
}
// Insert right at the front of the signature.
self.header_span().shrink_to_hi()
}
}
}
/// The span of the header's extern, or where to insert it if empty.
pub fn extern_span(&self) -> Span {
self.header.ext.span().unwrap_or(self.safety_span().shrink_to_hi())
}
}
/// A constraint on an associated item. /// A constraint on an associated item.
/// ///
/// ### Examples /// ### Examples
@ -3526,6 +3574,13 @@ impl Extern {
None => Extern::Implicit(span), None => Extern::Implicit(span),
} }
} }
pub fn span(self) -> Option<Span> {
match self {
Extern::None => None,
Extern::Implicit(span) | Extern::Explicit(_, span) => Some(span),
}
}
} }
/// A function header. /// A function header.
@ -3534,12 +3589,12 @@ impl Extern {
/// included in this struct (e.g., `async unsafe fn` or `const extern "C" fn`). /// included in this struct (e.g., `async unsafe fn` or `const extern "C" fn`).
#[derive(Clone, Copy, Encodable, Decodable, Debug, Walkable)] #[derive(Clone, Copy, Encodable, Decodable, Debug, Walkable)]
pub struct FnHeader { pub struct FnHeader {
/// Whether this is `unsafe`, or has a default safety.
pub safety: Safety,
/// Whether this is `async`, `gen`, or nothing.
pub coroutine_kind: Option<CoroutineKind>,
/// The `const` keyword, if any /// The `const` keyword, if any
pub constness: Const, pub constness: Const,
/// Whether this is `async`, `gen`, or nothing.
pub coroutine_kind: Option<CoroutineKind>,
/// Whether this is `unsafe`, or has a default safety.
pub safety: Safety,
/// The `extern` keyword and corresponding ABI string, if any. /// The `extern` keyword and corresponding ABI string, if any.
pub ext: Extern, pub ext: Extern,
} }
@ -3553,38 +3608,6 @@ impl FnHeader {
|| matches!(constness, Const::Yes(_)) || matches!(constness, Const::Yes(_))
|| !matches!(ext, Extern::None) || !matches!(ext, Extern::None)
} }
/// Return a span encompassing the header, or none if all options are default.
pub fn span(&self) -> Option<Span> {
fn append(a: &mut Option<Span>, b: Span) {
*a = match a {
None => Some(b),
Some(x) => Some(x.to(b)),
}
}
let mut full_span = None;
match self.safety {
Safety::Unsafe(span) | Safety::Safe(span) => append(&mut full_span, span),
Safety::Default => {}
};
if let Some(coroutine_kind) = self.coroutine_kind {
append(&mut full_span, coroutine_kind.span());
}
if let Const::Yes(span) = self.constness {
append(&mut full_span, span);
}
match self.ext {
Extern::Implicit(span) | Extern::Explicit(_, span) => append(&mut full_span, span),
Extern::None => {}
}
full_span
}
} }
impl Default for FnHeader { impl Default for FnHeader {

View file

@ -2101,17 +2101,14 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
{ {
return; return;
} }
if self.tcx.features().more_maybe_bounds() {
return;
}
} }
RelaxedBoundPolicy::Forbidden(reason) => { RelaxedBoundPolicy::Forbidden(reason) => {
if self.tcx.features().more_maybe_bounds() {
return;
}
match reason { match reason {
RelaxedBoundForbiddenReason::TraitObjectTy => { RelaxedBoundForbiddenReason::TraitObjectTy => {
if self.tcx.features().more_maybe_bounds() {
return;
}
self.dcx().span_err( self.dcx().span_err(
span, span,
"relaxed bounds are not permitted in trait object types", "relaxed bounds are not permitted in trait object types",
@ -2119,6 +2116,10 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
return; return;
} }
RelaxedBoundForbiddenReason::SuperTrait => { RelaxedBoundForbiddenReason::SuperTrait => {
if self.tcx.features().more_maybe_bounds() {
return;
}
let mut diag = self.dcx().struct_span_err( let mut diag = self.dcx().struct_span_err(
span, span,
"relaxed bounds are not permitted in supertrait bounds", "relaxed bounds are not permitted in supertrait bounds",

View file

@ -57,8 +57,6 @@ ast_passes_auto_super_lifetime = auto traits cannot have super traits or lifetim
.label = {ast_passes_auto_super_lifetime} .label = {ast_passes_auto_super_lifetime}
.suggestion = remove the super traits or lifetime bounds .suggestion = remove the super traits or lifetime bounds
ast_passes_bad_c_variadic = defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention
ast_passes_body_in_extern = incorrect `{$kind}` inside `extern` block ast_passes_body_in_extern = incorrect `{$kind}` inside `extern` block
.cannot_have = cannot have a body .cannot_have = cannot have a body
.invalid = the invalid body .invalid = the invalid body
@ -66,6 +64,19 @@ ast_passes_body_in_extern = incorrect `{$kind}` inside `extern` block
ast_passes_bound_in_context = bounds on `type`s in {$ctx} have no effect ast_passes_bound_in_context = bounds on `type`s in {$ctx} have no effect
ast_passes_c_variadic_associated_function = associated functions cannot have a C variable argument list
ast_passes_c_variadic_bad_extern = `...` is not supported for `extern "{$abi}"` functions
.label = `extern "{$abi}"` because of this
.help = only `extern "C"` and `extern "C-unwind"` functions may have a C variable argument list
ast_passes_c_variadic_must_be_unsafe =
functions with a C variable argument list must be unsafe
.suggestion = add the `unsafe` keyword to this definition
ast_passes_c_variadic_no_extern = `...` is not supported for non-extern functions
.help = only `extern "C"` and `extern "C-unwind"` functions may have a C variable argument list
ast_passes_const_and_c_variadic = functions cannot be both `const` and C-variadic ast_passes_const_and_c_variadic = functions cannot be both `const` and C-variadic
.const = `const` because of this .const = `const` because of this
.variadic = C-variadic because of this .variadic = C-variadic because of this
@ -84,6 +95,10 @@ ast_passes_const_without_body =
ast_passes_constraint_on_negative_bound = ast_passes_constraint_on_negative_bound =
associated type constraints not allowed on negative bounds associated type constraints not allowed on negative bounds
ast_passes_coroutine_and_c_variadic = functions cannot be both `{$coroutine_kind}` and C-variadic
.const = `{$coroutine_kind}` because of this
.variadic = C-variadic because of this
ast_passes_equality_in_where = equality constraints are not yet supported in `where` clauses ast_passes_equality_in_where = equality constraints are not yet supported in `where` clauses
.label = not supported .label = not supported
.suggestion = if `{$ident}` is an associated type you're trying to set, use the associated type binding syntax .suggestion = if `{$ident}` is an associated type you're trying to set, use the associated type binding syntax

View file

@ -492,7 +492,7 @@ impl<'a> AstValidator<'a> {
} }
if !spans.is_empty() { if !spans.is_empty() {
let header_span = sig.header.span().unwrap_or(sig.span.shrink_to_lo()); let header_span = sig.header_span();
let suggestion_span = header_span.shrink_to_hi().to(sig.decl.output.span()); let suggestion_span = header_span.shrink_to_hi().to(sig.decl.output.span());
let padding = if header_span.is_empty() { "" } else { " " }; let padding = if header_span.is_empty() { "" } else { " " };
@ -685,22 +685,53 @@ impl<'a> AstValidator<'a> {
}); });
} }
if let Some(coroutine_kind) = sig.header.coroutine_kind {
self.dcx().emit_err(errors::CoroutineAndCVariadic {
spans: vec![coroutine_kind.span(), variadic_param.span],
coroutine_kind: coroutine_kind.as_str(),
coroutine_span: coroutine_kind.span(),
variadic_span: variadic_param.span,
});
}
match fn_ctxt { match fn_ctxt {
FnCtxt::Foreign => return, FnCtxt::Foreign => return,
FnCtxt::Free => match sig.header.ext { FnCtxt::Free => match sig.header.ext {
Extern::Explicit(StrLit { symbol_unescaped: sym::C, .. }, _) Extern::Implicit(_) => {
| Extern::Explicit(StrLit { symbol_unescaped: sym::C_dash_unwind, .. }, _) if !matches!(sig.header.safety, Safety::Unsafe(_)) {
| Extern::Implicit(_) self.dcx().emit_err(errors::CVariadicMustBeUnsafe {
if matches!(sig.header.safety, Safety::Unsafe(_)) => span: variadic_param.span,
{ unsafe_span: sig.safety_span(),
return; });
}
} }
_ => {} Extern::Explicit(StrLit { symbol_unescaped, .. }, _) => {
}, if !matches!(symbol_unescaped, sym::C | sym::C_dash_unwind) {
FnCtxt::Assoc(_) => {} self.dcx().emit_err(errors::CVariadicBadExtern {
}; span: variadic_param.span,
abi: symbol_unescaped,
extern_span: sig.extern_span(),
});
}
self.dcx().emit_err(errors::BadCVariadic { span: variadic_param.span }); if !matches!(sig.header.safety, Safety::Unsafe(_)) {
self.dcx().emit_err(errors::CVariadicMustBeUnsafe {
span: variadic_param.span,
unsafe_span: sig.safety_span(),
});
}
}
Extern::None => {
let err = errors::CVariadicNoExtern { span: variadic_param.span };
self.dcx().emit_err(err);
}
},
FnCtxt::Assoc(_) => {
// For now, C variable argument lists are unsupported in associated functions.
let err = errors::CVariadicAssociatedFunction { span: variadic_param.span };
self.dcx().emit_err(err);
}
}
} }
fn check_item_named(&self, ident: Ident, kind: &str) { fn check_item_named(&self, ident: Ident, kind: &str) {

View file

@ -319,12 +319,46 @@ pub(crate) struct ExternItemAscii {
} }
#[derive(Diagnostic)] #[derive(Diagnostic)]
#[diag(ast_passes_bad_c_variadic)] #[diag(ast_passes_c_variadic_associated_function)]
pub(crate) struct BadCVariadic { pub(crate) struct CVariadicAssociatedFunction {
#[primary_span] #[primary_span]
pub span: Span, pub span: Span,
} }
#[derive(Diagnostic)]
#[diag(ast_passes_c_variadic_no_extern)]
#[help]
pub(crate) struct CVariadicNoExtern {
#[primary_span]
pub span: Span,
}
#[derive(Diagnostic)]
#[diag(ast_passes_c_variadic_must_be_unsafe)]
pub(crate) struct CVariadicMustBeUnsafe {
#[primary_span]
pub span: Span,
#[suggestion(
ast_passes_suggestion,
applicability = "maybe-incorrect",
code = "unsafe ",
style = "verbose"
)]
pub unsafe_span: Span,
}
#[derive(Diagnostic)]
#[diag(ast_passes_c_variadic_bad_extern)]
#[help]
pub(crate) struct CVariadicBadExtern {
#[primary_span]
pub span: Span,
pub abi: Symbol,
#[label]
pub extern_span: Span,
}
#[derive(Diagnostic)] #[derive(Diagnostic)]
#[diag(ast_passes_item_underscore)] #[diag(ast_passes_item_underscore)]
pub(crate) struct ItemUnderscore<'a> { pub(crate) struct ItemUnderscore<'a> {
@ -659,6 +693,18 @@ pub(crate) struct ConstAndCVariadic {
pub variadic_span: Span, pub variadic_span: Span,
} }
#[derive(Diagnostic)]
#[diag(ast_passes_coroutine_and_c_variadic)]
pub(crate) struct CoroutineAndCVariadic {
#[primary_span]
pub spans: Vec<Span>,
pub coroutine_kind: &'static str,
#[label(ast_passes_const)]
pub coroutine_span: Span,
#[label(ast_passes_variadic)]
pub variadic_span: Span,
}
#[derive(Diagnostic)] #[derive(Diagnostic)]
#[diag(ast_passes_pattern_in_foreign, code = E0130)] #[diag(ast_passes_pattern_in_foreign, code = E0130)]
// FIXME: deduplicate with rustc_lint (`BuiltinLintDiag::PatternsInFnsWithoutBody`) // FIXME: deduplicate with rustc_lint (`BuiltinLintDiag::PatternsInFnsWithoutBody`)

View file

@ -565,6 +565,7 @@ fn make_format_args(
&used, &used,
&args, &args,
&pieces, &pieces,
&invalid_refs,
detect_foreign_fmt, detect_foreign_fmt,
str_style, str_style,
fmt_str, fmt_str,
@ -645,6 +646,7 @@ fn report_missing_placeholders(
used: &[bool], used: &[bool],
args: &FormatArguments, args: &FormatArguments,
pieces: &[parse::Piece<'_>], pieces: &[parse::Piece<'_>],
invalid_refs: &[(usize, Option<Span>, PositionUsedAs, FormatArgPositionKind)],
detect_foreign_fmt: bool, detect_foreign_fmt: bool,
str_style: Option<usize>, str_style: Option<usize>,
fmt_str: &str, fmt_str: &str,
@ -762,6 +764,31 @@ fn report_missing_placeholders(
diag.span_label(fmt_span, "formatting specifier missing"); diag.span_label(fmt_span, "formatting specifier missing");
} }
if !found_foreign && invalid_refs.is_empty() {
// Show example if user didn't use any format specifiers
let show_example = used.iter().all(|used| !used);
if !show_example {
if unused.len() > 1 {
diag.note(format!("consider adding {} format specifiers", unused.len()));
}
} else {
let original_fmt_str =
if fmt_str.len() >= 1 { &fmt_str[..fmt_str.len() - 1] } else { "" };
let msg = if unused.len() == 1 {
"a format specifier".to_string()
} else {
format!("{} format specifiers", unused.len())
};
let sugg = format!("\"{}{}\"", original_fmt_str, "{}".repeat(unused.len()));
let msg = format!("format specifiers use curly braces, consider adding {msg}");
diag.span_suggestion_verbose(fmt_span, msg, sugg, Applicability::MaybeIncorrect);
}
}
diag.emit(); diag.emit();
} }

View file

@ -1,3 +1,5 @@
//! The implementation of built-in macros which relate to the file system.
use std::path::{Path, PathBuf}; use std::path::{Path, PathBuf};
use std::rc::Rc; use std::rc::Rc;
use std::sync::Arc; use std::sync::Arc;
@ -11,9 +13,11 @@ use rustc_expand::base::{
}; };
use rustc_expand::module::DirOwnership; use rustc_expand::module::DirOwnership;
use rustc_lint_defs::BuiltinLintDiag; use rustc_lint_defs::BuiltinLintDiag;
use rustc_parse::parser::{ForceCollect, Parser}; use rustc_parse::lexer::StripTokens;
use rustc_parse::parser::ForceCollect;
use rustc_parse::{new_parser_from_file, unwrap_or_emit_fatal, utf8_error}; use rustc_parse::{new_parser_from_file, unwrap_or_emit_fatal, utf8_error};
use rustc_session::lint::builtin::INCOMPLETE_INCLUDE; use rustc_session::lint::builtin::INCOMPLETE_INCLUDE;
use rustc_session::parse::ParseSess;
use rustc_span::source_map::SourceMap; use rustc_span::source_map::SourceMap;
use rustc_span::{ByteSymbol, Pos, Span, Symbol}; use rustc_span::{ByteSymbol, Pos, Span, Symbol};
use smallvec::SmallVec; use smallvec::SmallVec;
@ -23,11 +27,7 @@ use crate::util::{
check_zero_tts, get_single_str_from_tts, get_single_str_spanned_from_tts, parse_expr, check_zero_tts, get_single_str_from_tts, get_single_str_spanned_from_tts, parse_expr,
}; };
// These macros all relate to the file system; they either return /// Expand `line!()` to the current line number.
// the column/row/filename of the expression, or they include
// a given file into the current one.
/// line!(): expands to the current line number
pub(crate) fn expand_line( pub(crate) fn expand_line(
cx: &mut ExtCtxt<'_>, cx: &mut ExtCtxt<'_>,
sp: Span, sp: Span,
@ -42,7 +42,7 @@ pub(crate) fn expand_line(
ExpandResult::Ready(MacEager::expr(cx.expr_u32(topmost, loc.line as u32))) ExpandResult::Ready(MacEager::expr(cx.expr_u32(topmost, loc.line as u32)))
} }
/* column!(): expands to the current column number */ /// Expand `column!()` to the current column number.
pub(crate) fn expand_column( pub(crate) fn expand_column(
cx: &mut ExtCtxt<'_>, cx: &mut ExtCtxt<'_>,
sp: Span, sp: Span,
@ -57,9 +57,7 @@ pub(crate) fn expand_column(
ExpandResult::Ready(MacEager::expr(cx.expr_u32(topmost, loc.col.to_usize() as u32 + 1))) ExpandResult::Ready(MacEager::expr(cx.expr_u32(topmost, loc.col.to_usize() as u32 + 1)))
} }
/// file!(): expands to the current filename */ /// Expand `file!()` to the current filename.
/// The source_file (`loc.file`) contains a bunch more information we could spit
/// out if we wanted.
pub(crate) fn expand_file( pub(crate) fn expand_file(
cx: &mut ExtCtxt<'_>, cx: &mut ExtCtxt<'_>,
sp: Span, sp: Span,
@ -81,6 +79,7 @@ pub(crate) fn expand_file(
))) )))
} }
/// Expand `stringify!($input)`.
pub(crate) fn expand_stringify( pub(crate) fn expand_stringify(
cx: &mut ExtCtxt<'_>, cx: &mut ExtCtxt<'_>,
sp: Span, sp: Span,
@ -91,6 +90,7 @@ pub(crate) fn expand_stringify(
ExpandResult::Ready(MacEager::expr(cx.expr_str(sp, Symbol::intern(&s)))) ExpandResult::Ready(MacEager::expr(cx.expr_str(sp, Symbol::intern(&s))))
} }
/// Expand `module_path!()` to (a textual representation of) the current module path.
pub(crate) fn expand_mod( pub(crate) fn expand_mod(
cx: &mut ExtCtxt<'_>, cx: &mut ExtCtxt<'_>,
sp: Span, sp: Span,
@ -104,9 +104,9 @@ pub(crate) fn expand_mod(
ExpandResult::Ready(MacEager::expr(cx.expr_str(sp, Symbol::intern(&string)))) ExpandResult::Ready(MacEager::expr(cx.expr_str(sp, Symbol::intern(&string))))
} }
/// include! : parse the given file as an expr /// Expand `include!($input)`.
/// This is generally a bad idea because it's going to behave ///
/// unhygienically. /// This works in item and expression position. Notably, it doesn't work in pattern position.
pub(crate) fn expand_include<'cx>( pub(crate) fn expand_include<'cx>(
cx: &'cx mut ExtCtxt<'_>, cx: &'cx mut ExtCtxt<'_>,
sp: Span, sp: Span,
@ -116,39 +116,48 @@ pub(crate) fn expand_include<'cx>(
let ExpandResult::Ready(mac) = get_single_str_from_tts(cx, sp, tts, "include!") else { let ExpandResult::Ready(mac) = get_single_str_from_tts(cx, sp, tts, "include!") else {
return ExpandResult::Retry(()); return ExpandResult::Retry(());
}; };
let file = match mac { let path = match mac {
Ok(file) => file, Ok(path) => path,
Err(guar) => return ExpandResult::Ready(DummyResult::any(sp, guar)), Err(guar) => return ExpandResult::Ready(DummyResult::any(sp, guar)),
}; };
// The file will be added to the code map by the parser // The file will be added to the code map by the parser
let file = match resolve_path(&cx.sess, file.as_str(), sp) { let path = match resolve_path(&cx.sess, path.as_str(), sp) {
Ok(f) => f, Ok(path) => path,
Err(err) => { Err(err) => {
let guar = err.emit(); let guar = err.emit();
return ExpandResult::Ready(DummyResult::any(sp, guar)); return ExpandResult::Ready(DummyResult::any(sp, guar));
} }
}; };
let p = unwrap_or_emit_fatal(new_parser_from_file(cx.psess(), &file, Some(sp)));
// If in the included file we have e.g., `mod bar;`, // If in the included file we have e.g., `mod bar;`,
// then the path of `bar.rs` should be relative to the directory of `file`. // then the path of `bar.rs` should be relative to the directory of `path`.
// See https://github.com/rust-lang/rust/pull/69838/files#r395217057 for a discussion. // See https://github.com/rust-lang/rust/pull/69838/files#r395217057 for a discussion.
// `MacroExpander::fully_expand_fragment` later restores, so "stack discipline" is maintained. // `MacroExpander::fully_expand_fragment` later restores, so "stack discipline" is maintained.
let dir_path = file.parent().unwrap_or(&file).to_owned(); let dir_path = path.parent().unwrap_or(&path).to_owned();
cx.current_expansion.module = Rc::new(cx.current_expansion.module.with_dir_path(dir_path)); cx.current_expansion.module = Rc::new(cx.current_expansion.module.with_dir_path(dir_path));
cx.current_expansion.dir_ownership = DirOwnership::Owned { relative: None }; cx.current_expansion.dir_ownership = DirOwnership::Owned { relative: None };
struct ExpandInclude<'a> { struct ExpandInclude<'a> {
p: Parser<'a>, psess: &'a ParseSess,
path: PathBuf,
node_id: ast::NodeId, node_id: ast::NodeId,
span: Span,
} }
impl<'a> MacResult for ExpandInclude<'a> { impl<'a> MacResult for ExpandInclude<'a> {
fn make_expr(mut self: Box<ExpandInclude<'a>>) -> Option<Box<ast::Expr>> { fn make_expr(self: Box<ExpandInclude<'a>>) -> Option<Box<ast::Expr>> {
let expr = parse_expr(&mut self.p).ok()?; let mut p = unwrap_or_emit_fatal(new_parser_from_file(
if self.p.token != token::Eof { self.psess,
self.p.psess.buffer_lint( &self.path,
// Don't strip frontmatter for backward compatibility, `---` may be the start of a
// manifold negation. FIXME: Ideally, we wouldn't strip shebangs here either.
StripTokens::Shebang,
Some(self.span),
));
let expr = parse_expr(&mut p).ok()?;
if p.token != token::Eof {
p.psess.buffer_lint(
INCOMPLETE_INCLUDE, INCOMPLETE_INCLUDE,
self.p.token.span, p.token.span,
self.node_id, self.node_id,
BuiltinLintDiag::IncompleteInclude, BuiltinLintDiag::IncompleteInclude,
); );
@ -156,24 +165,27 @@ pub(crate) fn expand_include<'cx>(
Some(expr) Some(expr)
} }
fn make_items(mut self: Box<ExpandInclude<'a>>) -> Option<SmallVec<[Box<ast::Item>; 1]>> { fn make_items(self: Box<ExpandInclude<'a>>) -> Option<SmallVec<[Box<ast::Item>; 1]>> {
let mut p = unwrap_or_emit_fatal(new_parser_from_file(
self.psess,
&self.path,
StripTokens::ShebangAndFrontmatter,
Some(self.span),
));
let mut ret = SmallVec::new(); let mut ret = SmallVec::new();
loop { loop {
match self.p.parse_item(ForceCollect::No) { match p.parse_item(ForceCollect::No) {
Err(err) => { Err(err) => {
err.emit(); err.emit();
break; break;
} }
Ok(Some(item)) => ret.push(item), Ok(Some(item)) => ret.push(item),
Ok(None) => { Ok(None) => {
if self.p.token != token::Eof { if p.token != token::Eof {
self.p p.dcx().emit_err(errors::ExpectedItem {
.dcx() span: p.token.span,
.create_err(errors::ExpectedItem { token: &pprust::token_to_string(&p.token),
span: self.p.token.span, });
token: &pprust::token_to_string(&self.p.token),
})
.emit();
} }
break; break;
@ -184,10 +196,17 @@ pub(crate) fn expand_include<'cx>(
} }
} }
ExpandResult::Ready(Box::new(ExpandInclude { p, node_id: cx.current_expansion.lint_node_id })) ExpandResult::Ready(Box::new(ExpandInclude {
psess: cx.psess(),
path,
node_id: cx.current_expansion.lint_node_id,
span: sp,
}))
} }
/// `include_str!`: read the given file, insert it as a literal string expr /// Expand `include_str!($input)` to the content of the UTF-8-encoded file given by path `$input` as a string literal.
///
/// This works in expression, pattern and statement position.
pub(crate) fn expand_include_str( pub(crate) fn expand_include_str(
cx: &mut ExtCtxt<'_>, cx: &mut ExtCtxt<'_>,
sp: Span, sp: Span,
@ -206,6 +225,7 @@ pub(crate) fn expand_include_str(
Ok((bytes, bsp)) => match std::str::from_utf8(&bytes) { Ok((bytes, bsp)) => match std::str::from_utf8(&bytes) {
Ok(src) => { Ok(src) => {
let interned_src = Symbol::intern(src); let interned_src = Symbol::intern(src);
// MacEager converts the expr into a pat if need be.
MacEager::expr(cx.expr_str(cx.with_def_site_ctxt(bsp), interned_src)) MacEager::expr(cx.expr_str(cx.with_def_site_ctxt(bsp), interned_src))
} }
Err(utf8err) => { Err(utf8err) => {
@ -218,6 +238,9 @@ pub(crate) fn expand_include_str(
}) })
} }
/// Expand `include_bytes!($input)` to the content of the file given by path `$input`.
///
/// This works in expression, pattern and statement position.
pub(crate) fn expand_include_bytes( pub(crate) fn expand_include_bytes(
cx: &mut ExtCtxt<'_>, cx: &mut ExtCtxt<'_>,
sp: Span, sp: Span,
@ -237,6 +260,7 @@ pub(crate) fn expand_include_bytes(
// Don't care about getting the span for the raw bytes, // Don't care about getting the span for the raw bytes,
// because the console can't really show them anyway. // because the console can't really show them anyway.
let expr = cx.expr(sp, ast::ExprKind::IncludedBytes(ByteSymbol::intern(&bytes))); let expr = cx.expr(sp, ast::ExprKind::IncludedBytes(ByteSymbol::intern(&bytes)));
// MacEager converts the expr into a pat if need be.
MacEager::expr(expr) MacEager::expr(expr)
} }
Err(dummy) => dummy, Err(dummy) => dummy,

View file

@ -51,6 +51,7 @@ use rustc_lint::unerased_lint_store;
use rustc_metadata::creader::MetadataLoader; use rustc_metadata::creader::MetadataLoader;
use rustc_metadata::locator; use rustc_metadata::locator;
use rustc_middle::ty::TyCtxt; use rustc_middle::ty::TyCtxt;
use rustc_parse::lexer::StripTokens;
use rustc_parse::{new_parser_from_file, new_parser_from_source_str, unwrap_or_emit_fatal}; use rustc_parse::{new_parser_from_file, new_parser_from_source_str, unwrap_or_emit_fatal};
use rustc_session::config::{ use rustc_session::config::{
CG_OPTIONS, CrateType, ErrorOutputType, Input, OptionDesc, OutFileName, OutputType, Sysroot, CG_OPTIONS, CrateType, ErrorOutputType, Input, OptionDesc, OutFileName, OutputType, Sysroot,
@ -1288,10 +1289,15 @@ fn warn_on_confusing_output_filename_flag(
fn parse_crate_attrs<'a>(sess: &'a Session) -> PResult<'a, ast::AttrVec> { fn parse_crate_attrs<'a>(sess: &'a Session) -> PResult<'a, ast::AttrVec> {
let mut parser = unwrap_or_emit_fatal(match &sess.io.input { let mut parser = unwrap_or_emit_fatal(match &sess.io.input {
Input::File(file) => new_parser_from_file(&sess.psess, file, None), Input::File(file) => {
Input::Str { name, input } => { new_parser_from_file(&sess.psess, file, StripTokens::ShebangAndFrontmatter, None)
new_parser_from_source_str(&sess.psess, name.clone(), input.clone())
} }
Input::Str { name, input } => new_parser_from_source_str(
&sess.psess,
name.clone(),
input.clone(),
StripTokens::ShebangAndFrontmatter,
),
}); });
parser.parse_inner_attributes() parser.parse_inner_attributes()
} }

View file

@ -4,6 +4,7 @@ use std::path::{self, Path, PathBuf};
use rustc_ast::{AttrVec, Attribute, Inline, Item, ModSpans}; use rustc_ast::{AttrVec, Attribute, Inline, Item, ModSpans};
use rustc_attr_parsing::validate_attr; use rustc_attr_parsing::validate_attr;
use rustc_errors::{Diag, ErrorGuaranteed}; use rustc_errors::{Diag, ErrorGuaranteed};
use rustc_parse::lexer::StripTokens;
use rustc_parse::{exp, new_parser_from_file, unwrap_or_emit_fatal}; use rustc_parse::{exp, new_parser_from_file, unwrap_or_emit_fatal};
use rustc_session::Session; use rustc_session::Session;
use rustc_session::parse::ParseSess; use rustc_session::parse::ParseSess;
@ -67,8 +68,12 @@ pub(crate) fn parse_external_mod(
} }
// Actually parse the external file as a module. // Actually parse the external file as a module.
let mut parser = let mut parser = unwrap_or_emit_fatal(new_parser_from_file(
unwrap_or_emit_fatal(new_parser_from_file(&sess.psess, &mp.file_path, Some(span))); &sess.psess,
&mp.file_path,
StripTokens::ShebangAndFrontmatter,
Some(span),
));
let (inner_attrs, items, inner_span) = let (inner_attrs, items, inner_span) =
parser.parse_mod(exp!(Eof)).map_err(|err| ModError::ParserError(err))?; parser.parse_mod(exp!(Eof)).map_err(|err| ModError::ParserError(err))?;
attrs.extend(inner_attrs); attrs.extend(inner_attrs);

View file

@ -8,7 +8,7 @@ use rustc_ast::util::literal::escape_byte_str_symbol;
use rustc_ast_pretty::pprust; use rustc_ast_pretty::pprust;
use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::fx::FxHashMap;
use rustc_errors::{Diag, ErrorGuaranteed, MultiSpan, PResult}; use rustc_errors::{Diag, ErrorGuaranteed, MultiSpan, PResult};
use rustc_parse::lexer::nfc_normalize; use rustc_parse::lexer::{StripTokens, nfc_normalize};
use rustc_parse::parser::Parser; use rustc_parse::parser::Parser;
use rustc_parse::{exp, new_parser_from_source_str, source_str_to_stream, unwrap_or_emit_fatal}; use rustc_parse::{exp, new_parser_from_source_str, source_str_to_stream, unwrap_or_emit_fatal};
use rustc_proc_macro::bridge::{ use rustc_proc_macro::bridge::{
@ -485,8 +485,13 @@ impl server::FreeFunctions for Rustc<'_, '_> {
fn literal_from_str(&mut self, s: &str) -> Result<Literal<Self::Span, Self::Symbol>, ()> { fn literal_from_str(&mut self, s: &str) -> Result<Literal<Self::Span, Self::Symbol>, ()> {
let name = FileName::proc_macro_source_code(s); let name = FileName::proc_macro_source_code(s);
let mut parser =
unwrap_or_emit_fatal(new_parser_from_source_str(self.psess(), name, s.to_owned())); let mut parser = unwrap_or_emit_fatal(new_parser_from_source_str(
self.psess(),
name,
s.to_owned(),
StripTokens::Nothing,
));
let first_span = parser.token.span.data(); let first_span = parser.token.span.data();
let minus_present = parser.eat(exp!(Minus)); let minus_present = parser.eat(exp!(Minus));

View file

@ -174,12 +174,6 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen
} }
}; };
if let Node::TraitItem(item) = node {
let mut bounds = Vec::new();
icx.lowerer().add_default_trait_item_bounds(item, &mut bounds);
predicates.extend(bounds);
}
let generics = tcx.generics_of(def_id); let generics = tcx.generics_of(def_id);
// Below we'll consider the bounds on the type parameters (including `Self`) // Below we'll consider the bounds on the type parameters (including `Self`)

View file

@ -1,12 +1,13 @@
use std::assert_matches::assert_matches;
use std::ops::ControlFlow; use std::ops::ControlFlow;
use rustc_data_structures::fx::{FxIndexMap, FxIndexSet}; use rustc_data_structures::fx::{FxIndexMap, FxIndexSet};
use rustc_errors::codes::*; use rustc_errors::codes::*;
use rustc_errors::struct_span_code_err; use rustc_errors::struct_span_code_err;
use rustc_hir as hir; use rustc_hir as hir;
use rustc_hir::PolyTraitRef;
use rustc_hir::def::{DefKind, Res}; use rustc_hir::def::{DefKind, Res};
use rustc_hir::def_id::{CRATE_DEF_ID, DefId, LocalDefId}; use rustc_hir::def_id::{CRATE_DEF_ID, DefId, LocalDefId};
use rustc_hir::{AmbigArg, PolyTraitRef};
use rustc_middle::bug; use rustc_middle::bug;
use rustc_middle::ty::{ use rustc_middle::ty::{
self as ty, IsSuggestable, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, self as ty, IsSuggestable, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitableExt,
@ -230,122 +231,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
} }
} }
/// Checks whether `Self: DefaultAutoTrait` bounds should be added on trait super bounds /// Adds `experimental_default_bounds` bounds to the supertrait bounds.
/// or associated items.
///
/// To keep backward compatibility with existing code, `experimental_default_bounds` bounds
/// should be added everywhere, including super bounds. However this causes a huge performance
/// costs. For optimization purposes instead of adding default supertraits, bounds
/// are added to the associated items:
///
/// ```ignore(illustrative)
/// // Default bounds are generated in the following way:
/// trait Trait {
/// fn foo(&self) where Self: Leak {}
/// }
///
/// // instead of this:
/// trait Trait: Leak {
/// fn foo(&self) {}
/// }
/// ```
/// It is not always possible to do this because of backward compatibility:
///
/// ```ignore(illustrative)
/// pub trait Trait<Rhs = Self> {}
/// pub trait Trait1 : Trait {}
/// //~^ ERROR: `Rhs` requires `DefaultAutoTrait`, but `Self` is not `DefaultAutoTrait`
/// ```
///
/// or:
///
/// ```ignore(illustrative)
/// trait Trait {
/// type Type where Self: Sized;
/// }
/// trait Trait2<T> : Trait<Type = T> {}
/// //~^ ERROR: `DefaultAutoTrait` required for `Trait2`, by implicit `Self: DefaultAutoTrait` in `Trait::Type`
/// ```
///
/// Therefore, `experimental_default_bounds` are still being added to supertraits if
/// the `SelfTyParam` or `AssocItemConstraint` were found in a trait header.
fn requires_default_supertraits(
&self,
hir_bounds: &'tcx [hir::GenericBound<'tcx>],
hir_generics: &'tcx hir::Generics<'tcx>,
) -> bool {
struct TraitInfoCollector;
impl<'tcx> hir::intravisit::Visitor<'tcx> for TraitInfoCollector {
type Result = ControlFlow<()>;
fn visit_assoc_item_constraint(
&mut self,
_constraint: &'tcx hir::AssocItemConstraint<'tcx>,
) -> Self::Result {
ControlFlow::Break(())
}
fn visit_ty(&mut self, t: &'tcx hir::Ty<'tcx, AmbigArg>) -> Self::Result {
if matches!(
&t.kind,
hir::TyKind::Path(hir::QPath::Resolved(
_,
hir::Path { res: hir::def::Res::SelfTyParam { .. }, .. },
))
) {
return ControlFlow::Break(());
}
hir::intravisit::walk_ty(self, t)
}
}
let mut found = false;
for bound in hir_bounds {
found |= hir::intravisit::walk_param_bound(&mut TraitInfoCollector, bound).is_break();
}
found |= hir::intravisit::walk_generics(&mut TraitInfoCollector, hir_generics).is_break();
found
}
/// Implicitly add `Self: DefaultAutoTrait` clauses on trait associated items if
/// they are not added as super trait bounds to the trait itself. See
/// `requires_default_supertraits` for more information.
pub(crate) fn add_default_trait_item_bounds(
&self,
trait_item: &hir::TraitItem<'tcx>,
bounds: &mut Vec<(ty::Clause<'tcx>, Span)>,
) {
let tcx = self.tcx();
if !tcx.sess.opts.unstable_opts.experimental_default_bounds {
return;
}
let parent = tcx.local_parent(trait_item.hir_id().owner.def_id);
let hir::Node::Item(parent_trait) = tcx.hir_node_by_def_id(parent) else {
unreachable!();
};
let (trait_generics, trait_bounds) = match parent_trait.kind {
hir::ItemKind::Trait(_, _, _, _, generics, supertraits, _) => (generics, supertraits),
hir::ItemKind::TraitAlias(_, generics, supertraits) => (generics, supertraits),
_ => unreachable!(),
};
if !self.requires_default_supertraits(trait_bounds, trait_generics) {
let self_ty_where_predicates = (parent, trait_item.generics.predicates);
self.add_default_traits(
bounds,
tcx.types.self_param,
&[],
Some(self_ty_where_predicates),
trait_item.span,
);
}
}
/// Lazily sets `experimental_default_bounds` to true on trait super bounds.
/// See `requires_default_supertraits` for more information.
pub(crate) fn add_default_super_traits( pub(crate) fn add_default_super_traits(
&self, &self,
trait_def_id: LocalDefId, trait_def_id: LocalDefId,
@ -354,21 +240,21 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
hir_generics: &'tcx hir::Generics<'tcx>, hir_generics: &'tcx hir::Generics<'tcx>,
span: Span, span: Span,
) { ) {
if !self.tcx().sess.opts.unstable_opts.experimental_default_bounds { assert_matches!(self.tcx().def_kind(trait_def_id), DefKind::Trait | DefKind::TraitAlias);
// Supertraits for auto trait are unsound according to the unstable book:
// https://doc.rust-lang.org/beta/unstable-book/language-features/auto-traits.html#supertraits
if self.tcx().trait_is_auto(trait_def_id.to_def_id()) {
return; return;
} }
assert!(matches!(self.tcx().def_kind(trait_def_id), DefKind::Trait | DefKind::TraitAlias)); self.add_default_traits(
if self.requires_default_supertraits(hir_bounds, hir_generics) { bounds,
let self_ty_where_predicates = (trait_def_id, hir_generics.predicates); self.tcx().types.self_param,
self.add_default_traits( hir_bounds,
bounds, Some((trait_def_id, hir_generics.predicates)),
self.tcx().types.self_param, span,
hir_bounds, );
Some(self_ty_where_predicates),
span,
);
}
} }
pub(crate) fn add_default_traits( pub(crate) fn add_default_traits(

View file

@ -13,7 +13,8 @@ use rustc_lint::LintStore;
use rustc_middle::ty; use rustc_middle::ty;
use rustc_middle::ty::CurrentGcx; use rustc_middle::ty::CurrentGcx;
use rustc_middle::util::Providers; use rustc_middle::util::Providers;
use rustc_parse::new_parser_from_simple_source_str; use rustc_parse::lexer::StripTokens;
use rustc_parse::new_parser_from_source_str;
use rustc_parse::parser::attr::AllowLeadingUnsafe; use rustc_parse::parser::attr::AllowLeadingUnsafe;
use rustc_query_impl::QueryCtxt; use rustc_query_impl::QueryCtxt;
use rustc_query_system::query::print_query_stack; use rustc_query_system::query::print_query_stack;
@ -68,7 +69,8 @@ pub(crate) fn parse_cfg(dcx: DiagCtxtHandle<'_>, cfgs: Vec<String>) -> Cfg {
}; };
} }
match new_parser_from_simple_source_str(&psess, filename, s.to_string()) { match new_parser_from_source_str(&psess, filename, s.to_string(), StripTokens::Nothing)
{
Ok(mut parser) => match parser.parse_meta_item(AllowLeadingUnsafe::No) { Ok(mut parser) => match parser.parse_meta_item(AllowLeadingUnsafe::No) {
Ok(meta_item) if parser.token == token::Eof => { Ok(meta_item) if parser.token == token::Eof => {
if meta_item.path.segments.len() != 1 { if meta_item.path.segments.len() != 1 {
@ -166,13 +168,15 @@ pub(crate) fn parse_check_cfg(dcx: DiagCtxtHandle<'_>, specs: Vec<String>) -> Ch
error!("expected `cfg(name, values(\"value1\", \"value2\", ... \"valueN\"))`") error!("expected `cfg(name, values(\"value1\", \"value2\", ... \"valueN\"))`")
}; };
let mut parser = match new_parser_from_simple_source_str(&psess, filename, s.to_string()) { let mut parser =
Ok(parser) => parser, match new_parser_from_source_str(&psess, filename, s.to_string(), StripTokens::Nothing)
Err(errs) => { {
errs.into_iter().for_each(|err| err.cancel()); Ok(parser) => parser,
expected_error(); Err(errs) => {
} errs.into_iter().for_each(|err| err.cancel());
}; expected_error();
}
};
let meta_item = match parser.parse_meta_item(AllowLeadingUnsafe::No) { let meta_item = match parser.parse_meta_item(AllowLeadingUnsafe::No) {
Ok(meta_item) if parser.token == token::Eof => meta_item, Ok(meta_item) if parser.token == token::Eof => meta_item,

View file

@ -28,6 +28,7 @@ use rustc_middle::arena::Arena;
use rustc_middle::dep_graph::DepsType; use rustc_middle::dep_graph::DepsType;
use rustc_middle::ty::{self, CurrentGcx, GlobalCtxt, RegisteredTools, TyCtxt}; use rustc_middle::ty::{self, CurrentGcx, GlobalCtxt, RegisteredTools, TyCtxt};
use rustc_middle::util::Providers; use rustc_middle::util::Providers;
use rustc_parse::lexer::StripTokens;
use rustc_parse::{new_parser_from_file, new_parser_from_source_str, unwrap_or_emit_fatal}; use rustc_parse::{new_parser_from_file, new_parser_from_source_str, unwrap_or_emit_fatal};
use rustc_passes::{abi_test, input_stats, layout_test}; use rustc_passes::{abi_test, input_stats, layout_test};
use rustc_resolve::{Resolver, ResolverOutputs}; use rustc_resolve::{Resolver, ResolverOutputs};
@ -52,10 +53,18 @@ pub fn parse<'a>(sess: &'a Session) -> ast::Crate {
let mut krate = sess let mut krate = sess
.time("parse_crate", || { .time("parse_crate", || {
let mut parser = unwrap_or_emit_fatal(match &sess.io.input { let mut parser = unwrap_or_emit_fatal(match &sess.io.input {
Input::File(file) => new_parser_from_file(&sess.psess, file, None), Input::File(file) => new_parser_from_file(
Input::Str { input, name } => { &sess.psess,
new_parser_from_source_str(&sess.psess, name.clone(), input.clone()) file,
} StripTokens::ShebangAndFrontmatter,
None,
),
Input::Str { input, name } => new_parser_from_source_str(
&sess.psess,
name.clone(),
input.clone(),
StripTokens::ShebangAndFrontmatter,
),
}); });
parser.parse_crate_mod() parser.parse_crate_mod()
}) })

View file

@ -47,7 +47,8 @@ impl<'tcx> LateLintPass<'tcx> for MultipleSupertraitUpcastable {
.explicit_super_predicates_of(def_id) .explicit_super_predicates_of(def_id)
.iter_identity_copied() .iter_identity_copied()
.filter_map(|(pred, _)| pred.as_trait_clause()) .filter_map(|(pred, _)| pred.as_trait_clause())
.filter(|pred| !cx.tcx.is_lang_item(pred.def_id(), hir::LangItem::MetaSized)); .filter(|pred| !cx.tcx.is_lang_item(pred.def_id(), hir::LangItem::MetaSized))
.filter(|pred| !cx.tcx.is_default_trait(pred.def_id()));
if direct_super_traits_iter.count() > 1 { if direct_super_traits_iter.count() > 1 {
cx.emit_span_lint( cx.emit_span_lint(
MULTIPLE_SUPERTRAIT_UPCASTABLE, MULTIPLE_SUPERTRAIT_UPCASTABLE,

View file

@ -45,7 +45,7 @@ pub(crate) struct UnmatchedDelim {
} }
/// Which tokens should be stripped before lexing the tokens. /// Which tokens should be stripped before lexing the tokens.
pub(crate) enum StripTokens { pub enum StripTokens {
/// Strip both shebang and frontmatter. /// Strip both shebang and frontmatter.
ShebangAndFrontmatter, ShebangAndFrontmatter,
/// Strip the shebang but not frontmatter. /// Strip the shebang but not frontmatter.

View file

@ -54,29 +54,18 @@ pub fn unwrap_or_emit_fatal<T>(expr: Result<T, Vec<Diag<'_>>>) -> T {
} }
} }
/// Creates a new parser from a source string. On failure, the errors must be consumed via /// Creates a new parser from a source string.
/// `unwrap_or_emit_fatal`, `emit`, `cancel`, etc., otherwise a panic will occur when they are ///
/// dropped. /// On failure, the errors must be consumed via `unwrap_or_emit_fatal`, `emit`, `cancel`,
/// etc., otherwise a panic will occur when they are dropped.
pub fn new_parser_from_source_str( pub fn new_parser_from_source_str(
psess: &ParseSess, psess: &ParseSess,
name: FileName, name: FileName,
source: String, source: String,
strip_tokens: StripTokens,
) -> Result<Parser<'_>, Vec<Diag<'_>>> { ) -> Result<Parser<'_>, Vec<Diag<'_>>> {
let source_file = psess.source_map().new_source_file(name, source); let source_file = psess.source_map().new_source_file(name, source);
new_parser_from_source_file(psess, source_file, StripTokens::ShebangAndFrontmatter) new_parser_from_source_file(psess, source_file, strip_tokens)
}
/// Creates a new parser from a simple (no shebang, no frontmatter) source string.
///
/// On failure, the errors must be consumed via `unwrap_or_emit_fatal`, `emit`, `cancel`,
/// etc., otherwise a panic will occur when they are dropped.
pub fn new_parser_from_simple_source_str(
psess: &ParseSess,
name: FileName,
source: String,
) -> Result<Parser<'_>, Vec<Diag<'_>>> {
let source_file = psess.source_map().new_source_file(name, source);
new_parser_from_source_file(psess, source_file, StripTokens::Nothing)
} }
/// Creates a new parser from a filename. On failure, the errors must be consumed via /// Creates a new parser from a filename. On failure, the errors must be consumed via
@ -87,6 +76,7 @@ pub fn new_parser_from_simple_source_str(
pub fn new_parser_from_file<'a>( pub fn new_parser_from_file<'a>(
psess: &'a ParseSess, psess: &'a ParseSess,
path: &Path, path: &Path,
strip_tokens: StripTokens,
sp: Option<Span>, sp: Option<Span>,
) -> Result<Parser<'a>, Vec<Diag<'a>>> { ) -> Result<Parser<'a>, Vec<Diag<'a>>> {
let sm = psess.source_map(); let sm = psess.source_map();
@ -110,7 +100,7 @@ pub fn new_parser_from_file<'a>(
} }
err.emit(); err.emit();
}); });
new_parser_from_source_file(psess, source_file, StripTokens::ShebangAndFrontmatter) new_parser_from_source_file(psess, source_file, strip_tokens)
} }
pub fn utf8_error<E: EmissionGuarantee>( pub fn utf8_error<E: EmissionGuarantee>(
@ -172,6 +162,9 @@ fn new_parser_from_source_file(
Ok(parser) Ok(parser)
} }
/// Given a source string, produces a sequence of token trees.
///
/// NOTE: This only strips shebangs, not frontmatter!
pub fn source_str_to_stream( pub fn source_str_to_stream(
psess: &ParseSess, psess: &ParseSess,
name: FileName, name: FileName,
@ -179,13 +172,16 @@ pub fn source_str_to_stream(
override_span: Option<Span>, override_span: Option<Span>,
) -> Result<TokenStream, Vec<Diag<'_>>> { ) -> Result<TokenStream, Vec<Diag<'_>>> {
let source_file = psess.source_map().new_source_file(name, source); let source_file = psess.source_map().new_source_file(name, source);
// used mainly for `proc_macro` and the likes, not for our parsing purposes, so don't parse // FIXME(frontmatter): Consider stripping frontmatter in a future edition. We can't strip them
// frontmatters as frontmatters, but for compatibility reason still strip the shebang // in the current edition since that would be breaking.
// See also <https://github.com/rust-lang/rust/issues/145520>.
// Alternatively, stop stripping shebangs here, too, if T-lang and crater approve.
source_file_to_stream(psess, source_file, override_span, StripTokens::Shebang) source_file_to_stream(psess, source_file, override_span, StripTokens::Shebang)
} }
/// Given a source file, produces a sequence of token trees. Returns any buffered errors from /// Given a source file, produces a sequence of token trees.
/// parsing the token stream. ///
/// Returns any buffered errors from parsing the token stream.
fn source_file_to_stream<'psess>( fn source_file_to_stream<'psess>(
psess: &'psess ParseSess, psess: &'psess ParseSess,
source_file: Arc<SourceFile>, source_file: Arc<SourceFile>,

View file

@ -22,6 +22,7 @@ use rustc_span::{
}; };
use termcolor::WriteColor; use termcolor::WriteColor;
use crate::lexer::StripTokens;
use crate::parser::{ForceCollect, Parser}; use crate::parser::{ForceCollect, Parser};
use crate::{new_parser_from_source_str, source_str_to_stream, unwrap_or_emit_fatal}; use crate::{new_parser_from_source_str, source_str_to_stream, unwrap_or_emit_fatal};
@ -35,6 +36,7 @@ fn string_to_parser(psess: &ParseSess, source_str: String) -> Parser<'_> {
psess, psess,
PathBuf::from("bogofile").into(), PathBuf::from("bogofile").into(),
source_str, source_str,
StripTokens::Nothing,
)) ))
} }
@ -2240,7 +2242,7 @@ fn parse_item_from_source_str(
source: String, source: String,
psess: &ParseSess, psess: &ParseSess,
) -> PResult<'_, Option<Box<ast::Item>>> { ) -> PResult<'_, Option<Box<ast::Item>>> {
unwrap_or_emit_fatal(new_parser_from_source_str(psess, name, source)) unwrap_or_emit_fatal(new_parser_from_source_str(psess, name, source, StripTokens::Nothing))
.parse_item(ForceCollect::No) .parse_item(ForceCollect::No)
} }
@ -2520,7 +2522,8 @@ fn ttdelim_span() {
source: String, source: String,
psess: &ParseSess, psess: &ParseSess,
) -> PResult<'_, Box<ast::Expr>> { ) -> PResult<'_, Box<ast::Expr>> {
unwrap_or_emit_fatal(new_parser_from_source_str(psess, name, source)).parse_expr() unwrap_or_emit_fatal(new_parser_from_source_str(psess, name, source, StripTokens::Nothing))
.parse_expr()
} }
create_default_session_globals_then(|| { create_default_session_globals_then(|| {

View file

@ -21,18 +21,17 @@ mod tests;
// The proc macro code for this is in `compiler/rustc_macros/src/symbols.rs`. // The proc macro code for this is in `compiler/rustc_macros/src/symbols.rs`.
symbols! { symbols! {
// This list includes things that are definitely keywords (e.g. `if`), // This list includes things that are definitely keywords (e.g. `if`), a
// a few things that are definitely not keywords (e.g. the empty symbol, // few things that are definitely not keywords (e.g. `{{root}}`) and things
// `{{root}}`) and things where there is disagreement between people and/or // where there is disagreement between people and/or documents (such as the
// documents (such as the Rust Reference) about whether it is a keyword // Rust Reference) about whether it is a keyword (e.g. `_`).
// (e.g. `_`).
// //
// If you modify this list, adjust any relevant `Symbol::{is,can_be}_*` // If you modify this list, adjust any relevant `Symbol::{is,can_be}_*`
// predicates and `used_keywords`. Also consider adding new keywords to the // predicates and `used_keywords`. Also consider adding new keywords to the
// `ui/parser/raw/raw-idents.rs` test. // `ui/parser/raw/raw-idents.rs` test.
Keywords { Keywords {
// Special reserved identifiers used internally for elided lifetimes, // Special reserved identifiers used internally for unnamed method
// unnamed method parameters, crate root module, error recovery etc. // parameters, crate root module, etc.
// Matching predicates: `is_special`/`is_reserved` // Matching predicates: `is_special`/`is_reserved`
// //
// tidy-alphabetical-start // tidy-alphabetical-start

View file

@ -95,6 +95,9 @@ impl Error {
pub(crate) const ZERO_TIMEOUT: Self = pub(crate) const ZERO_TIMEOUT: Self =
const_error!(ErrorKind::InvalidInput, "cannot set a 0 duration timeout"); const_error!(ErrorKind::InvalidInput, "cannot set a 0 duration timeout");
pub(crate) const NO_ADDRESSES: Self =
const_error!(ErrorKind::InvalidInput, "could not resolve to any addresses");
} }
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]

View file

@ -34,7 +34,6 @@ pub use self::tcp::IntoIncoming;
pub use self::tcp::{Incoming, TcpListener, TcpStream}; pub use self::tcp::{Incoming, TcpListener, TcpStream};
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
pub use self::udp::UdpSocket; pub use self::udp::UdpSocket;
use crate::io::{self, ErrorKind};
mod ip_addr; mod ip_addr;
mod socket_addr; mod socket_addr;
@ -67,23 +66,3 @@ pub enum Shutdown {
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
Both, Both,
} }
fn each_addr<A: ToSocketAddrs, F, T>(addr: A, mut f: F) -> io::Result<T>
where
F: FnMut(io::Result<&SocketAddr>) -> io::Result<T>,
{
let addrs = match addr.to_socket_addrs() {
Ok(addrs) => addrs,
Err(e) => return f(Err(e)),
};
let mut last_err = None;
for addr in addrs {
match f(Ok(&addr)) {
Ok(l) => return Ok(l),
Err(e) => last_err = Some(e),
}
}
Err(last_err.unwrap_or_else(|| {
io::const_error!(ErrorKind::InvalidInput, "could not resolve to any addresses")
}))
}

View file

@ -167,7 +167,7 @@ impl TcpStream {
/// ``` /// ```
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
pub fn connect<A: ToSocketAddrs>(addr: A) -> io::Result<TcpStream> { pub fn connect<A: ToSocketAddrs>(addr: A) -> io::Result<TcpStream> {
super::each_addr(addr, net_imp::TcpStream::connect).map(TcpStream) net_imp::TcpStream::connect(addr).map(TcpStream)
} }
/// Opens a TCP connection to a remote host with a timeout. /// Opens a TCP connection to a remote host with a timeout.
@ -782,7 +782,7 @@ impl TcpListener {
/// ``` /// ```
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
pub fn bind<A: ToSocketAddrs>(addr: A) -> io::Result<TcpListener> { pub fn bind<A: ToSocketAddrs>(addr: A) -> io::Result<TcpListener> {
super::each_addr(addr, net_imp::TcpListener::bind).map(TcpListener) net_imp::TcpListener::bind(addr).map(TcpListener)
} }
/// Returns the local socket address of this listener. /// Returns the local socket address of this listener.

View file

@ -1,5 +1,5 @@
use crate::io::prelude::*; use crate::io::prelude::*;
use crate::io::{BorrowedBuf, IoSlice, IoSliceMut}; use crate::io::{BorrowedBuf, ErrorKind, IoSlice, IoSliceMut};
use crate::mem::MaybeUninit; use crate::mem::MaybeUninit;
use crate::net::test::{next_test_ip4, next_test_ip6}; use crate::net::test::{next_test_ip4, next_test_ip6};
use crate::net::*; use crate::net::*;

View file

@ -120,7 +120,7 @@ impl UdpSocket {
/// [`Ipv4Addr::UNSPECIFIED`] or [`Ipv6Addr::UNSPECIFIED`]. /// [`Ipv4Addr::UNSPECIFIED`] or [`Ipv6Addr::UNSPECIFIED`].
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
pub fn bind<A: ToSocketAddrs>(addr: A) -> io::Result<UdpSocket> { pub fn bind<A: ToSocketAddrs>(addr: A) -> io::Result<UdpSocket> {
super::each_addr(addr, net_imp::UdpSocket::bind).map(UdpSocket) net_imp::UdpSocket::bind(addr).map(UdpSocket)
} }
/// Receives a single datagram message on the socket. On success, returns the number /// Receives a single datagram message on the socket. On success, returns the number
@ -677,7 +677,7 @@ impl UdpSocket {
/// on the platform. /// on the platform.
#[stable(feature = "net2_mutators", since = "1.9.0")] #[stable(feature = "net2_mutators", since = "1.9.0")]
pub fn connect<A: ToSocketAddrs>(&self, addr: A) -> io::Result<()> { pub fn connect<A: ToSocketAddrs>(&self, addr: A) -> io::Result<()> {
super::each_addr(addr, |addr| self.0.connect(addr)) self.0.connect(addr)
} }
/// Sends data on the socket to the remote address to which it is connected. /// Sends data on the socket to the remote address to which it is connected.

View file

@ -1,3 +1,4 @@
use crate::io::ErrorKind;
use crate::net::test::{compare_ignore_zoneid, next_test_ip4, next_test_ip6}; use crate::net::test::{compare_ignore_zoneid, next_test_ip4, next_test_ip6};
use crate::net::*; use crate::net::*;
use crate::sync::mpsc::channel; use crate::sync::mpsc::channel;

View file

@ -1,4 +1,5 @@
use crate::fmt; use crate::fmt;
use crate::panic::RefUnwindSafe;
use crate::sync::nonpoison::{Condvar, Mutex}; use crate::sync::nonpoison::{Condvar, Mutex};
/// A barrier enables multiple threads to synchronize the beginning /// A barrier enables multiple threads to synchronize the beginning
@ -31,6 +32,9 @@ pub struct Barrier {
num_threads: usize, num_threads: usize,
} }
#[stable(feature = "unwind_safe_lock_refs", since = "1.12.0")]
impl RefUnwindSafe for Barrier {}
// The inner state of a double barrier // The inner state of a double barrier
struct BarrierState { struct BarrierState {
count: usize, count: usize,

View file

@ -0,0 +1,57 @@
cfg_select! {
any(
all(target_family = "unix", not(target_os = "l4re")),
target_os = "windows",
target_os = "hermit",
all(target_os = "wasi", target_env = "p2"),
target_os = "solid_asp3",
) => {
mod socket;
pub use socket::*;
}
all(target_vendor = "fortanix", target_env = "sgx") => {
mod sgx;
pub use sgx::*;
}
all(target_os = "wasi", target_env = "p1") => {
mod wasip1;
pub use wasip1::*;
}
target_os = "xous" => {
mod xous;
pub use xous::*;
}
target_os = "uefi" => {
mod uefi;
pub use uefi::*;
}
_ => {
mod unsupported;
pub use unsupported::*;
}
}
#[cfg_attr(
// Make sure that this is used on some platforms at least.
not(any(target_os = "linux", target_os = "windows")),
allow(dead_code)
)]
fn each_addr<A: crate::net::ToSocketAddrs, F, T>(addr: A, mut f: F) -> crate::io::Result<T>
where
F: FnMut(&crate::net::SocketAddr) -> crate::io::Result<T>,
{
use crate::io::Error;
let mut last_err = None;
for addr in addr.to_socket_addrs()? {
match f(&addr) {
Ok(l) => return Ok(l),
Err(e) => last_err = Some(e),
}
}
match last_err {
Some(err) => Err(err),
None => Err(Error::NO_ADDRESSES),
}
}

View file

@ -1,3 +1,5 @@
use crate::error;
use crate::fmt::{self, Write};
use crate::io::{self, BorrowedCursor, IoSlice, IoSliceMut}; use crate::io::{self, BorrowedCursor, IoSlice, IoSliceMut};
use crate::net::{Ipv4Addr, Ipv6Addr, Shutdown, SocketAddr, ToSocketAddrs}; use crate::net::{Ipv4Addr, Ipv6Addr, Shutdown, SocketAddr, ToSocketAddrs};
use crate::sync::Arc; use crate::sync::Arc;
@ -5,7 +7,6 @@ use crate::sys::abi::usercalls;
use crate::sys::fd::FileDesc; use crate::sys::fd::FileDesc;
use crate::sys::{AsInner, FromInner, IntoInner, TryIntoInner, sgx_ineffective, unsupported}; use crate::sys::{AsInner, FromInner, IntoInner, TryIntoInner, sgx_ineffective, unsupported};
use crate::time::Duration; use crate::time::Duration;
use crate::{error, fmt};
const DEFAULT_FAKE_TTL: u32 = 64; const DEFAULT_FAKE_TTL: u32 = 64;
@ -63,18 +64,52 @@ impl fmt::Debug for TcpStream {
} }
} }
fn io_err_to_addr(result: io::Result<&SocketAddr>) -> io::Result<String> { /// Converts each address in `addr` into a hostname.
match result { ///
Ok(saddr) => Ok(saddr.to_string()), /// SGX doesn't support DNS resolution but rather accepts hostnames in
// need to downcast twice because io::Error::into_inner doesn't return the original /// the same place as socket addresses. So, to make e.g.
// value if the conversion fails /// ```rust
Err(e) => { /// TcpStream::connect("example.com:80")`
if e.get_ref().and_then(|e| e.downcast_ref::<NonIpSockAddr>()).is_some() { /// ```
Ok(e.into_inner().unwrap().downcast::<NonIpSockAddr>().unwrap().host) /// work, the DNS lookup returns a special error (`NonIpSockAddr`) instead,
} else { /// which contains the hostname being looked up. When `.to_socket_addrs()`
Err(e) /// fails, we inspect the error and try recover the hostname from it. If that
/// succeeds, we thus continue with the hostname.
///
/// This is a terrible hack and leads to buggy code. For instance, when users
/// use the result of `.to_socket_addrs()` in their own `ToSocketAddrs`
/// implementation to select from a list of possible URLs, the only URL used
/// will be that of the last item tried.
// FIXME: This is a terrible, terrible hack. Fixing this requires Fortanix to
// add a method for resolving addresses.
fn each_addr<A: ToSocketAddrs, F, T>(addr: A, mut f: F) -> io::Result<T>
where
F: FnMut(&str) -> io::Result<T>,
{
match addr.to_socket_addrs() {
Ok(addrs) => {
let mut last_err = None;
let mut encoded = String::new();
for addr in addrs {
// Format the IP address as a string, reusing the buffer.
encoded.clear();
write!(encoded, "{}", &addr).unwrap();
match f(&encoded) {
Ok(val) => return Ok(val),
Err(err) => last_err = Some(err),
}
}
match last_err {
Some(err) => Err(err),
None => Err(io::Error::NO_ADDRESSES),
} }
} }
Err(err) => match err.get_ref().and_then(|e| e.downcast_ref::<NonIpSockAddr>()) {
Some(NonIpSockAddr { host }) => f(host),
None => Err(err),
},
} }
} }
@ -86,17 +121,18 @@ fn addr_to_sockaddr(addr: Option<&str>) -> io::Result<SocketAddr> {
} }
impl TcpStream { impl TcpStream {
pub fn connect(addr: io::Result<&SocketAddr>) -> io::Result<TcpStream> { pub fn connect<A: ToSocketAddrs>(addr: A) -> io::Result<TcpStream> {
let addr = io_err_to_addr(addr)?; each_addr(addr, |addr| {
let (fd, local_addr, peer_addr) = usercalls::connect_stream(&addr)?; let (fd, local_addr, peer_addr) = usercalls::connect_stream(addr)?;
Ok(TcpStream { inner: Socket::new(fd, local_addr), peer_addr: Some(peer_addr) }) Ok(TcpStream { inner: Socket::new(fd, local_addr), peer_addr: Some(peer_addr) })
})
} }
pub fn connect_timeout(addr: &SocketAddr, dur: Duration) -> io::Result<TcpStream> { pub fn connect_timeout(addr: &SocketAddr, dur: Duration) -> io::Result<TcpStream> {
if dur == Duration::default() { if dur == Duration::default() {
return Err(io::Error::ZERO_TIMEOUT); return Err(io::Error::ZERO_TIMEOUT);
} }
Self::connect(Ok(addr)) // FIXME: ignoring timeout Self::connect(addr) // FIXME: ignoring timeout
} }
pub fn set_read_timeout(&self, dur: Option<Duration>) -> io::Result<()> { pub fn set_read_timeout(&self, dur: Option<Duration>) -> io::Result<()> {
@ -247,10 +283,11 @@ impl fmt::Debug for TcpListener {
} }
impl TcpListener { impl TcpListener {
pub fn bind(addr: io::Result<&SocketAddr>) -> io::Result<TcpListener> { pub fn bind<A: ToSocketAddrs>(addr: A) -> io::Result<TcpListener> {
let addr = io_err_to_addr(addr)?; each_addr(addr, |addr| {
let (fd, local_addr) = usercalls::bind_stream(&addr)?; let (fd, local_addr) = usercalls::bind_stream(addr)?;
Ok(TcpListener { inner: Socket::new(fd, local_addr) }) Ok(TcpListener { inner: Socket::new(fd, local_addr) })
})
} }
pub fn socket_addr(&self) -> io::Result<SocketAddr> { pub fn socket_addr(&self) -> io::Result<SocketAddr> {
@ -316,7 +353,7 @@ impl FromInner<Socket> for TcpListener {
pub struct UdpSocket(!); pub struct UdpSocket(!);
impl UdpSocket { impl UdpSocket {
pub fn bind(_: io::Result<&SocketAddr>) -> io::Result<UdpSocket> { pub fn bind<A: ToSocketAddrs>(_: A) -> io::Result<UdpSocket> {
unsupported() unsupported()
} }
@ -436,7 +473,7 @@ impl UdpSocket {
self.0 self.0
} }
pub fn connect(&self, _: io::Result<&SocketAddr>) -> io::Result<()> { pub fn connect<A: ToSocketAddrs>(&self, _: A) -> io::Result<()> {
self.0 self.0
} }
} }

View file

@ -3,8 +3,11 @@ mod tests;
use crate::ffi::{c_int, c_void}; use crate::ffi::{c_int, c_void};
use crate::io::{self, BorrowedCursor, ErrorKind, IoSlice, IoSliceMut}; use crate::io::{self, BorrowedCursor, ErrorKind, IoSlice, IoSliceMut};
use crate::net::{Ipv4Addr, Ipv6Addr, Shutdown, SocketAddr, SocketAddrV4, SocketAddrV6}; use crate::net::{
Ipv4Addr, Ipv6Addr, Shutdown, SocketAddr, SocketAddrV4, SocketAddrV6, ToSocketAddrs,
};
use crate::sys::common::small_c_string::run_with_cstr; use crate::sys::common::small_c_string::run_with_cstr;
use crate::sys::net::connection::each_addr;
use crate::sys_common::{AsInner, FromInner}; use crate::sys_common::{AsInner, FromInner};
use crate::time::Duration; use crate::time::Duration;
use crate::{cmp, fmt, mem, ptr}; use crate::{cmp, fmt, mem, ptr};
@ -342,14 +345,15 @@ pub struct TcpStream {
} }
impl TcpStream { impl TcpStream {
pub fn connect(addr: io::Result<&SocketAddr>) -> io::Result<TcpStream> { pub fn connect<A: ToSocketAddrs>(addr: A) -> io::Result<TcpStream> {
let addr = addr?;
init(); init();
return each_addr(addr, inner);
let sock = Socket::new(addr, c::SOCK_STREAM)?; fn inner(addr: &SocketAddr) -> io::Result<TcpStream> {
sock.connect(addr)?; let sock = Socket::new(addr, c::SOCK_STREAM)?;
Ok(TcpStream { inner: sock }) sock.connect(addr)?;
Ok(TcpStream { inner: sock })
}
} }
pub fn connect_timeout(addr: &SocketAddr, timeout: Duration) -> io::Result<TcpStream> { pub fn connect_timeout(addr: &SocketAddr, timeout: Duration) -> io::Result<TcpStream> {
@ -512,48 +516,45 @@ pub struct TcpListener {
} }
impl TcpListener { impl TcpListener {
pub fn bind(addr: io::Result<&SocketAddr>) -> io::Result<TcpListener> { pub fn bind<A: ToSocketAddrs>(addr: A) -> io::Result<TcpListener> {
let addr = addr?;
init(); init();
return each_addr(addr, inner);
let sock = Socket::new(addr, c::SOCK_STREAM)?; fn inner(addr: &SocketAddr) -> io::Result<TcpListener> {
let sock = Socket::new(addr, c::SOCK_STREAM)?;
// On platforms with Berkeley-derived sockets, this allows to quickly // On platforms with Berkeley-derived sockets, this allows to quickly
// rebind a socket, without needing to wait for the OS to clean up the // rebind a socket, without needing to wait for the OS to clean up the
// previous one. // previous one.
// //
// On Windows, this allows rebinding sockets which are actively in use, // On Windows, this allows rebinding sockets which are actively in use,
// which allows “socket hijacking”, so we explicitly don't set it here. // which allows “socket hijacking”, so we explicitly don't set it here.
// https://docs.microsoft.com/en-us/windows/win32/winsock/using-so-reuseaddr-and-so-exclusiveaddruse // https://docs.microsoft.com/en-us/windows/win32/winsock/using-so-reuseaddr-and-so-exclusiveaddruse
#[cfg(not(windows))] #[cfg(not(windows))]
setsockopt(&sock, c::SOL_SOCKET, c::SO_REUSEADDR, 1 as c_int)?; setsockopt(&sock, c::SOL_SOCKET, c::SO_REUSEADDR, 1 as c_int)?;
// Bind our new socket // Bind our new socket
let (addr, len) = socket_addr_to_c(addr); let (addr, len) = socket_addr_to_c(addr);
cvt(unsafe { c::bind(sock.as_raw(), addr.as_ptr(), len as _) })?; cvt(unsafe { c::bind(sock.as_raw(), addr.as_ptr(), len as _) })?;
cfg_select! { let backlog = if cfg!(target_os = "horizon") {
target_os = "horizon" => {
// The 3DS doesn't support a big connection backlog. Sometimes // The 3DS doesn't support a big connection backlog. Sometimes
// it allows up to about 37, but other times it doesn't even // it allows up to about 37, but other times it doesn't even
// accept 32. There may be a global limitation causing this. // accept 32. There may be a global limitation causing this.
let backlog = 20; 20
} } else if cfg!(target_os = "haiku") {
target_os = "haiku" => {
// Haiku does not support a queue length > 32 // Haiku does not support a queue length > 32
// https://github.com/haiku/haiku/blob/979a0bc487864675517fb2fab28f87dc8bf43041/headers/posix/sys/socket.h#L81 // https://github.com/haiku/haiku/blob/979a0bc487864675517fb2fab28f87dc8bf43041/headers/posix/sys/socket.h#L81
let backlog = 32; 32
} } else {
_ => {
// The default for all other platforms // The default for all other platforms
let backlog = 128; 128
} };
}
// Start listening // Start listening
cvt(unsafe { c::listen(sock.as_raw(), backlog) })?; cvt(unsafe { c::listen(sock.as_raw(), backlog) })?;
Ok(TcpListener { inner: sock }) Ok(TcpListener { inner: sock })
}
} }
#[inline] #[inline]
@ -639,15 +640,16 @@ pub struct UdpSocket {
} }
impl UdpSocket { impl UdpSocket {
pub fn bind(addr: io::Result<&SocketAddr>) -> io::Result<UdpSocket> { pub fn bind<A: ToSocketAddrs>(addr: A) -> io::Result<UdpSocket> {
let addr = addr?;
init(); init();
return each_addr(addr, inner);
let sock = Socket::new(addr, c::SOCK_DGRAM)?; fn inner(addr: &SocketAddr) -> io::Result<UdpSocket> {
let (addr, len) = socket_addr_to_c(addr); let sock = Socket::new(addr, c::SOCK_DGRAM)?;
cvt(unsafe { c::bind(sock.as_raw(), addr.as_ptr(), len as _) })?; let (addr, len) = socket_addr_to_c(addr);
Ok(UdpSocket { inner: sock }) cvt(unsafe { c::bind(sock.as_raw(), addr.as_ptr(), len as _) })?;
Ok(UdpSocket { inner: sock })
}
} }
#[inline] #[inline]
@ -822,9 +824,13 @@ impl UdpSocket {
Ok(ret as usize) Ok(ret as usize)
} }
pub fn connect(&self, addr: io::Result<&SocketAddr>) -> io::Result<()> { pub fn connect<A: ToSocketAddrs>(&self, addr: A) -> io::Result<()> {
let (addr, len) = socket_addr_to_c(addr?); return each_addr(addr, |addr| inner(self, addr));
cvt_r(|| unsafe { c::connect(self.inner.as_raw(), addr.as_ptr(), len) }).map(drop)
fn inner(this: &UdpSocket, addr: &SocketAddr) -> io::Result<()> {
let (addr, len) = socket_addr_to_c(addr);
cvt_r(|| unsafe { c::connect(this.inner.as_raw(), addr.as_ptr(), len) }).map(drop)
}
} }
} }

View file

@ -1,6 +1,7 @@
use super::each_addr;
use crate::fmt; use crate::fmt;
use crate::io::{self, BorrowedCursor, IoSlice, IoSliceMut}; use crate::io::{self, BorrowedCursor, IoSlice, IoSliceMut};
use crate::net::{Ipv4Addr, Ipv6Addr, Shutdown, SocketAddr}; use crate::net::{Ipv4Addr, Ipv6Addr, Shutdown, SocketAddr, ToSocketAddrs};
use crate::sync::{Arc, Mutex}; use crate::sync::{Arc, Mutex};
use crate::sys::unsupported; use crate::sys::unsupported;
use crate::time::Duration; use crate::time::Duration;
@ -15,13 +16,17 @@ pub struct TcpStream {
} }
impl TcpStream { impl TcpStream {
pub fn connect(addr: io::Result<&SocketAddr>) -> io::Result<TcpStream> { pub fn connect<A: ToSocketAddrs>(addr: A) -> io::Result<TcpStream> {
let inner = tcp::Tcp::connect(addr?, None)?; return each_addr(addr, inner);
Ok(Self {
inner, fn inner(addr: &SocketAddr) -> io::Result<TcpStream> {
read_timeout: Arc::new(Mutex::new(None)), let inner = tcp::Tcp::connect(addr, None)?;
write_timeout: Arc::new(Mutex::new(None)), Ok(TcpStream {
}) inner,
read_timeout: Arc::new(Mutex::new(None)),
write_timeout: Arc::new(Mutex::new(None)),
})
}
} }
pub fn connect_timeout(addr: &SocketAddr, timeout: Duration) -> io::Result<TcpStream> { pub fn connect_timeout(addr: &SocketAddr, timeout: Duration) -> io::Result<TcpStream> {
@ -145,7 +150,7 @@ pub struct TcpListener {
} }
impl TcpListener { impl TcpListener {
pub fn bind(_: io::Result<&SocketAddr>) -> io::Result<TcpListener> { pub fn bind<A: ToSocketAddrs>(_: A) -> io::Result<TcpListener> {
unsupported() unsupported()
} }
@ -195,7 +200,7 @@ impl fmt::Debug for TcpListener {
pub struct UdpSocket(!); pub struct UdpSocket(!);
impl UdpSocket { impl UdpSocket {
pub fn bind(_: io::Result<&SocketAddr>) -> io::Result<UdpSocket> { pub fn bind<A: ToSocketAddrs>(_: A) -> io::Result<UdpSocket> {
unsupported() unsupported()
} }
@ -315,7 +320,7 @@ impl UdpSocket {
self.0 self.0
} }
pub fn connect(&self, _: io::Result<&SocketAddr>) -> io::Result<()> { pub fn connect<A: ToSocketAddrs>(&self, _: A) -> io::Result<()> {
self.0 self.0
} }
} }

View file

@ -1,13 +1,13 @@
use crate::fmt; use crate::fmt;
use crate::io::{self, BorrowedCursor, IoSlice, IoSliceMut}; use crate::io::{self, BorrowedCursor, IoSlice, IoSliceMut};
use crate::net::{Ipv4Addr, Ipv6Addr, Shutdown, SocketAddr}; use crate::net::{Ipv4Addr, Ipv6Addr, Shutdown, SocketAddr, ToSocketAddrs};
use crate::sys::unsupported; use crate::sys::unsupported;
use crate::time::Duration; use crate::time::Duration;
pub struct TcpStream(!); pub struct TcpStream(!);
impl TcpStream { impl TcpStream {
pub fn connect(_: io::Result<&SocketAddr>) -> io::Result<TcpStream> { pub fn connect<A: ToSocketAddrs>(_: A) -> io::Result<TcpStream> {
unsupported() unsupported()
} }
@ -121,7 +121,7 @@ impl fmt::Debug for TcpStream {
pub struct TcpListener(!); pub struct TcpListener(!);
impl TcpListener { impl TcpListener {
pub fn bind(_: io::Result<&SocketAddr>) -> io::Result<TcpListener> { pub fn bind<A: ToSocketAddrs>(_: A) -> io::Result<TcpListener> {
unsupported() unsupported()
} }
@ -171,7 +171,7 @@ impl fmt::Debug for TcpListener {
pub struct UdpSocket(!); pub struct UdpSocket(!);
impl UdpSocket { impl UdpSocket {
pub fn bind(_: io::Result<&SocketAddr>) -> io::Result<UdpSocket> { pub fn bind<A: ToSocketAddrs>(_: A) -> io::Result<UdpSocket> {
unsupported() unsupported()
} }
@ -291,7 +291,7 @@ impl UdpSocket {
self.0 self.0
} }
pub fn connect(&self, _: io::Result<&SocketAddr>) -> io::Result<()> { pub fn connect<A: ToSocketAddrs>(&self, _: A) -> io::Result<()> {
self.0 self.0
} }
} }

View file

@ -2,7 +2,7 @@
use crate::fmt; use crate::fmt;
use crate::io::{self, BorrowedCursor, IoSlice, IoSliceMut}; use crate::io::{self, BorrowedCursor, IoSlice, IoSliceMut};
use crate::net::{Ipv4Addr, Ipv6Addr, Shutdown, SocketAddr}; use crate::net::{Ipv4Addr, Ipv6Addr, Shutdown, SocketAddr, ToSocketAddrs};
use crate::os::wasi::io::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, RawFd}; use crate::os::wasi::io::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, RawFd};
use crate::sys::fd::WasiFd; use crate::sys::fd::WasiFd;
use crate::sys::{err2io, unsupported}; use crate::sys::{err2io, unsupported};
@ -60,7 +60,7 @@ impl FromRawFd for Socket {
} }
impl TcpStream { impl TcpStream {
pub fn connect(_: io::Result<&SocketAddr>) -> io::Result<TcpStream> { pub fn connect<A: ToSocketAddrs>(_: A) -> io::Result<TcpStream> {
unsupported() unsupported()
} }
@ -212,7 +212,7 @@ pub struct TcpListener {
} }
impl TcpListener { impl TcpListener {
pub fn bind(_: io::Result<&SocketAddr>) -> io::Result<TcpListener> { pub fn bind<A: ToSocketAddrs>(_: A) -> io::Result<TcpListener> {
unsupported() unsupported()
} }
@ -316,7 +316,7 @@ pub struct UdpSocket {
} }
impl UdpSocket { impl UdpSocket {
pub fn bind(_: io::Result<&SocketAddr>) -> io::Result<UdpSocket> { pub fn bind<A: ToSocketAddrs>(_: A) -> io::Result<UdpSocket> {
unsupported() unsupported()
} }
@ -436,7 +436,7 @@ impl UdpSocket {
unsupported() unsupported()
} }
pub fn connect(&self, _: io::Result<&SocketAddr>) -> io::Result<()> { pub fn connect<A: ToSocketAddrs>(&self, _: A) -> io::Result<()> {
unsupported() unsupported()
} }

View file

@ -2,9 +2,10 @@ use core::convert::TryInto;
use core::sync::atomic::{Atomic, AtomicBool, AtomicU16, AtomicUsize, Ordering}; use core::sync::atomic::{Atomic, AtomicBool, AtomicU16, AtomicUsize, Ordering};
use super::*; use super::*;
use crate::net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr}; use crate::net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr, ToSocketAddrs};
use crate::os::xous::services; use crate::os::xous::services;
use crate::sync::Arc; use crate::sync::Arc;
use crate::sys::net::connection::each_addr;
use crate::{fmt, io}; use crate::{fmt, io};
macro_rules! unimpl { macro_rules! unimpl {
@ -25,16 +26,19 @@ pub struct TcpListener {
} }
impl TcpListener { impl TcpListener {
pub fn bind(socketaddr: io::Result<&SocketAddr>) -> io::Result<TcpListener> { pub fn bind<A: ToSocketAddrs>(addr: A) -> io::Result<TcpListener> {
let mut addr = *socketaddr?; return each_addr(addr, inner);
let fd = TcpListener::bind_inner(&mut addr)?; fn inner(addr: &SocketAddr) -> io::Result<TcpListener> {
return Ok(TcpListener { let mut addr = *addr;
fd: Arc::new(AtomicU16::new(fd)), let fd = TcpListener::bind_inner(&mut addr)?;
local: addr, Ok(TcpListener {
handle_count: Arc::new(AtomicUsize::new(1)), fd: Arc::new(AtomicU16::new(fd)),
nonblocking: Arc::new(AtomicBool::new(false)), local: addr,
}); handle_count: Arc::new(AtomicUsize::new(1)),
nonblocking: Arc::new(AtomicBool::new(false)),
})
}
} }
/// This returns the raw fd of a Listener, so that it can also be used by the /// This returns the raw fd of a Listener, so that it can also be used by the

View file

@ -3,9 +3,12 @@ use core::sync::atomic::{Atomic, AtomicBool, AtomicU32, AtomicUsize, Ordering};
use super::*; use super::*;
use crate::fmt; use crate::fmt;
use crate::io::{self, BorrowedCursor, IoSlice, IoSliceMut}; use crate::io::{self, BorrowedCursor, IoSlice, IoSliceMut};
use crate::net::{IpAddr, Ipv4Addr, Shutdown, SocketAddr, SocketAddrV4, SocketAddrV6}; use crate::net::{
IpAddr, Ipv4Addr, Shutdown, SocketAddr, SocketAddrV4, SocketAddrV6, ToSocketAddrs,
};
use crate::os::xous::services; use crate::os::xous::services;
use crate::sync::Arc; use crate::sync::Arc;
use crate::sys::net::connection::each_addr;
use crate::time::Duration; use crate::time::Duration;
macro_rules! unimpl { macro_rules! unimpl {
@ -79,8 +82,8 @@ impl TcpStream {
} }
} }
pub fn connect(socketaddr: io::Result<&SocketAddr>) -> io::Result<TcpStream> { pub fn connect<A: ToSocketAddrs>(addr: A) -> io::Result<TcpStream> {
Self::connect_timeout(socketaddr?, Duration::ZERO) each_addr(addr, |addr| Self::connect_timeout(addr, Duration::ZERO))
} }
pub fn connect_timeout(addr: &SocketAddr, duration: Duration) -> io::Result<TcpStream> { pub fn connect_timeout(addr: &SocketAddr, duration: Duration) -> io::Result<TcpStream> {

View file

@ -3,9 +3,10 @@ use core::sync::atomic::{Atomic, AtomicUsize, Ordering};
use super::*; use super::*;
use crate::cell::Cell; use crate::cell::Cell;
use crate::net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr}; use crate::net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr, ToSocketAddrs};
use crate::os::xous::services; use crate::os::xous::services;
use crate::sync::Arc; use crate::sync::Arc;
use crate::sys::net::connection::each_addr;
use crate::time::Duration; use crate::time::Duration;
use crate::{fmt, io}; use crate::{fmt, io};
@ -32,40 +33,45 @@ pub struct UdpSocket {
} }
impl UdpSocket { impl UdpSocket {
pub fn bind(socketaddr: io::Result<&SocketAddr>) -> io::Result<UdpSocket> { pub fn bind<A: ToSocketAddrs>(addr: A) -> io::Result<UdpSocket> {
let addr = socketaddr?; return each_addr(addr, inner);
// Construct the request
let mut connect_request = ConnectRequest { raw: [0u8; 4096] };
// Serialize the StdUdpBind structure. This is done "manually" because we don't want to fn inner(addr: &SocketAddr) -> io::Result<UdpSocket> {
// make an auto-serdes (like bincode or rkyv) crate a dependency of Xous. // Construct the request
let port_bytes = addr.port().to_le_bytes(); let mut connect_request = ConnectRequest { raw: [0u8; 4096] };
connect_request.raw[0] = port_bytes[0];
connect_request.raw[1] = port_bytes[1]; // Serialize the StdUdpBind structure. This is done "manually" because we don't want to
match addr.ip() { // make an auto-serdes (like bincode or rkyv) crate a dependency of Xous.
IpAddr::V4(addr) => { let port_bytes = addr.port().to_le_bytes();
connect_request.raw[2] = 4; connect_request.raw[0] = port_bytes[0];
for (dest, src) in connect_request.raw[3..].iter_mut().zip(addr.octets()) { connect_request.raw[1] = port_bytes[1];
*dest = src; match addr.ip() {
IpAddr::V4(addr) => {
connect_request.raw[2] = 4;
for (dest, src) in connect_request.raw[3..].iter_mut().zip(addr.octets()) {
*dest = src;
}
}
IpAddr::V6(addr) => {
connect_request.raw[2] = 6;
for (dest, src) in connect_request.raw[3..].iter_mut().zip(addr.octets()) {
*dest = src;
}
} }
} }
IpAddr::V6(addr) => {
connect_request.raw[2] = 6;
for (dest, src) in connect_request.raw[3..].iter_mut().zip(addr.octets()) {
*dest = src;
}
}
}
let response = crate::os::xous::ffi::lend_mut( let response = crate::os::xous::ffi::lend_mut(
services::net_server(), services::net_server(),
services::NetLendMut::StdUdpBind.into(), services::NetLendMut::StdUdpBind.into(),
&mut connect_request.raw, &mut connect_request.raw,
0, 0,
4096, 4096,
); );
let Ok((_, valid)) = response else {
return Err(io::const_error!(io::ErrorKind::InvalidInput, "invalid response"));
};
if let Ok((_, valid)) = response {
// The first four bytes should be zero upon success, and will be nonzero // The first four bytes should be zero upon success, and will be nonzero
// for an error. // for an error.
let response = connect_request.raw; let response = connect_request.raw;
@ -87,8 +93,9 @@ impl UdpSocket {
)); ));
} }
} }
let fd = response[1] as u16; let fd = response[1] as u16;
return Ok(UdpSocket { Ok(UdpSocket {
fd, fd,
local: *addr, local: *addr,
remote: Cell::new(None), remote: Cell::new(None),
@ -96,9 +103,8 @@ impl UdpSocket {
write_timeout: Cell::new(0), write_timeout: Cell::new(0),
handle_count: Arc::new(AtomicUsize::new(1)), handle_count: Arc::new(AtomicUsize::new(1)),
nonblocking: Cell::new(false), nonblocking: Cell::new(false),
}); })
} }
Err(io::const_error!(io::ErrorKind::InvalidInput, "invalid response"))
} }
pub fn peer_addr(&self) -> io::Result<SocketAddr> { pub fn peer_addr(&self) -> io::Result<SocketAddr> {
@ -198,10 +204,11 @@ impl UdpSocket {
self.peek_from(buf).map(|(len, _addr)| len) self.peek_from(buf).map(|(len, _addr)| len)
} }
pub fn connect(&self, maybe_addr: io::Result<&SocketAddr>) -> io::Result<()> { pub fn connect<A: ToSocketAddrs>(&self, addr: A) -> io::Result<()> {
let addr = maybe_addr?; each_addr(addr, |addr| {
self.remote.set(Some(*addr)); self.remote.set(Some(*addr));
Ok(()) Ok(())
})
} }
pub fn send(&self, buf: &[u8]) -> io::Result<usize> { pub fn send(&self, buf: &[u8]) -> io::Result<usize> {

View file

@ -1,46 +1,4 @@
cfg_select! { /// This module contains the implementations of `TcpStream`, `TcpListener` and
any( /// `UdpSocket` as well as related functionality like DNS resolving.
all(target_family = "unix", not(target_os = "l4re")), mod connection;
target_os = "windows",
target_os = "hermit",
all(target_os = "wasi", target_env = "p2"),
target_os = "solid_asp3",
) => {
mod connection {
mod socket;
pub use socket::*;
}
}
all(target_vendor = "fortanix", target_env = "sgx") => {
mod connection {
mod sgx;
pub use sgx::*;
}
}
all(target_os = "wasi", target_env = "p1") => {
mod connection {
mod wasip1;
pub use wasip1::*;
}
}
target_os = "xous" => {
mod connection {
mod xous;
pub use xous::*;
}
}
target_os = "uefi" => {
mod connection {
mod uefi;
pub use uefi::*;
}
}
_ => {
mod connection {
mod unsupported;
pub use unsupported::*;
}
}
}
pub use connection::*; pub use connection::*;

View file

@ -1,3 +1,4 @@
use std::panic::RefUnwindSafe;
use std::sync::mpsc::{TryRecvError, channel}; use std::sync::mpsc::{TryRecvError, channel};
use std::sync::{Arc, Barrier}; use std::sync::{Arc, Barrier};
use std::thread; use std::thread;
@ -33,3 +34,11 @@ fn test_barrier() {
} }
assert!(leader_found); assert!(leader_found);
} }
/// Asserts that `Barrier` is ref unwind safe.
///
/// See <https://github.com/rust-lang/rust/issues/146087>.
const _: () = {
const fn check_ref_unwind_safe<T: RefUnwindSafe>() {}
check_ref_unwind_safe::<Barrier>();
};

View file

@ -3,6 +3,7 @@ use rustc_ast::tokenstream::{TokenStream, TokenTree};
use rustc_ast_pretty::pprust::PrintState; use rustc_ast_pretty::pprust::PrintState;
use rustc_ast_pretty::pprust::state::State as Printer; use rustc_ast_pretty::pprust::state::State as Printer;
use rustc_middle::ty::TyCtxt; use rustc_middle::ty::TyCtxt;
use rustc_parse::lexer::StripTokens;
use rustc_session::parse::ParseSess; use rustc_session::parse::ParseSess;
use rustc_span::symbol::{Ident, Symbol, kw}; use rustc_span::symbol::{Ident, Symbol, kw};
use rustc_span::{FileName, Span}; use rustc_span::{FileName, Span};
@ -64,14 +65,18 @@ fn snippet_equal_to_token(tcx: TyCtxt<'_>, matcher: &TokenTree) -> Option<String
// Create a Parser. // Create a Parser.
let psess = ParseSess::new(rustc_driver::DEFAULT_LOCALE_RESOURCES.to_vec()); let psess = ParseSess::new(rustc_driver::DEFAULT_LOCALE_RESOURCES.to_vec());
let file_name = FileName::macro_expansion_source_code(&snippet); let file_name = FileName::macro_expansion_source_code(&snippet);
let mut parser = let mut parser = match rustc_parse::new_parser_from_source_str(
match rustc_parse::new_parser_from_source_str(&psess, file_name, snippet.clone()) { &psess,
Ok(parser) => parser, file_name,
Err(errs) => { snippet.clone(),
errs.into_iter().for_each(|err| err.cancel()); StripTokens::Nothing,
return None; ) {
} Ok(parser) => parser,
}; Err(errs) => {
errs.into_iter().for_each(|err| err.cancel());
return None;
}
};
// Reparse a single token tree. // Reparse a single token tree.
if parser.token == token::Eof { if parser.token == token::Eof {

View file

@ -10,6 +10,7 @@ use rustc_ast::tokenstream::TokenTree;
use rustc_ast::{self as ast, AttrStyle, HasAttrs, StmtKind}; use rustc_ast::{self as ast, AttrStyle, HasAttrs, StmtKind};
use rustc_errors::emitter::stderr_destination; use rustc_errors::emitter::stderr_destination;
use rustc_errors::{ColorConfig, DiagCtxtHandle}; use rustc_errors::{ColorConfig, DiagCtxtHandle};
use rustc_parse::lexer::StripTokens;
use rustc_parse::new_parser_from_source_str; use rustc_parse::new_parser_from_source_str;
use rustc_session::parse::ParseSess; use rustc_session::parse::ParseSess;
use rustc_span::edition::{DEFAULT_EDITION, Edition}; use rustc_span::edition::{DEFAULT_EDITION, Edition};
@ -468,14 +469,16 @@ fn parse_source(
let dcx = DiagCtxt::new(Box::new(emitter)).disable_warnings(); let dcx = DiagCtxt::new(Box::new(emitter)).disable_warnings();
let psess = ParseSess::with_dcx(dcx, sm); let psess = ParseSess::with_dcx(dcx, sm);
let mut parser = match new_parser_from_source_str(&psess, filename, wrapped_source) { // Don't strip any tokens; it wouldn't matter anyway because the source is wrapped in a function.
Ok(p) => p, let mut parser =
Err(errs) => { match new_parser_from_source_str(&psess, filename, wrapped_source, StripTokens::Nothing) {
errs.into_iter().for_each(|err| err.cancel()); Ok(p) => p,
reset_error_count(&psess); Err(errs) => {
return Err(()); errs.into_iter().for_each(|err| err.cancel());
} reset_error_count(&psess);
}; return Err(());
}
};
fn push_to_s(s: &mut String, source: &str, span: rustc_span::Span, prev_span_hi: &mut usize) { fn push_to_s(s: &mut String, source: &str, span: rustc_span::Span, prev_span_hi: &mut usize) {
let extra_len = DOCTEST_CODE_WRAPPER.len(); let extra_len = DOCTEST_CODE_WRAPPER.len();

View file

@ -8,6 +8,7 @@ use rustc_ast::{CoroutineKind, Fn, FnRetTy, Item, ItemKind};
use rustc_errors::emitter::HumanEmitter; use rustc_errors::emitter::HumanEmitter;
use rustc_errors::{Diag, DiagCtxt}; use rustc_errors::{Diag, DiagCtxt};
use rustc_lint::LateContext; use rustc_lint::LateContext;
use rustc_parse::lexer::StripTokens;
use rustc_parse::new_parser_from_source_str; use rustc_parse::new_parser_from_source_str;
use rustc_parse::parser::ForceCollect; use rustc_parse::parser::ForceCollect;
use rustc_session::parse::ParseSess; use rustc_session::parse::ParseSess;
@ -49,13 +50,14 @@ pub fn check(
let sm = Arc::new(SourceMap::new(FilePathMapping::empty())); let sm = Arc::new(SourceMap::new(FilePathMapping::empty()));
let psess = ParseSess::with_dcx(dcx, sm); let psess = ParseSess::with_dcx(dcx, sm);
let mut parser = match new_parser_from_source_str(&psess, filename, code) { let mut parser =
Ok(p) => p, match new_parser_from_source_str(&psess, filename, code, StripTokens::ShebangAndFrontmatter) {
Err(errs) => { Ok(p) => p,
errs.into_iter().for_each(Diag::cancel); Err(errs) => {
return (false, test_attr_spans); errs.into_iter().for_each(Diag::cancel);
}, return (false, test_attr_spans);
}; },
};
let mut relevant_main_found = false; let mut relevant_main_found = false;
let mut eligible = true; let mut eligible = true;

View file

@ -3,6 +3,7 @@ use std::path::{Path, PathBuf};
use rustc_ast::{ast, attr}; use rustc_ast::{ast, attr};
use rustc_errors::Diag; use rustc_errors::Diag;
use rustc_parse::lexer::StripTokens;
use rustc_parse::parser::Parser as RawParser; use rustc_parse::parser::Parser as RawParser;
use rustc_parse::{exp, new_parser_from_file, new_parser_from_source_str, unwrap_or_emit_fatal}; use rustc_parse::{exp, new_parser_from_file, new_parser_from_source_str, unwrap_or_emit_fatal};
use rustc_span::{Span, sym}; use rustc_span::{Span, sym};
@ -64,11 +65,14 @@ impl<'a> ParserBuilder<'a> {
input: Input, input: Input,
) -> Result<RawParser<'a>, Vec<Diag<'a>>> { ) -> Result<RawParser<'a>, Vec<Diag<'a>>> {
match input { match input {
Input::File(ref file) => new_parser_from_file(psess, file, None), Input::File(ref file) => {
new_parser_from_file(psess, file, StripTokens::ShebangAndFrontmatter, None)
}
Input::Text(text) => new_parser_from_source_str( Input::Text(text) => new_parser_from_source_str(
psess, psess,
rustc_span::FileName::Custom("stdin".to_owned()), rustc_span::FileName::Custom("stdin".to_owned()),
text, text,
StripTokens::ShebangAndFrontmatter,
), ),
} }
} }
@ -104,8 +108,12 @@ impl<'a> Parser<'a> {
span: Span, span: Span,
) -> Result<(ast::AttrVec, ThinVec<Box<ast::Item>>, Span), ParserError> { ) -> Result<(ast::AttrVec, ThinVec<Box<ast::Item>>, Span), ParserError> {
let result = catch_unwind(AssertUnwindSafe(|| { let result = catch_unwind(AssertUnwindSafe(|| {
let mut parser = let mut parser = unwrap_or_emit_fatal(new_parser_from_file(
unwrap_or_emit_fatal(new_parser_from_file(psess.inner(), path, Some(span))); psess.inner(),
path,
StripTokens::ShebangAndFrontmatter,
Some(span),
));
match parser.parse_mod(exp!(Eof)) { match parser.parse_mod(exp!(Eof)) {
Ok((a, i, spans)) => Some((a, i, spans.inner_span)), Ok((a, i, spans)) => Some((a, i, spans.inner_span)),
Err(e) => { Err(e) => {

View file

@ -10,7 +10,7 @@ extern crate rustc_span;
use rustc_ast::ast::{AttrKind, Attribute, DUMMY_NODE_ID, Expr}; use rustc_ast::ast::{AttrKind, Attribute, DUMMY_NODE_ID, Expr};
use rustc_ast::mut_visit::{self, MutVisitor}; use rustc_ast::mut_visit::{self, MutVisitor};
use rustc_ast::node_id::NodeId; use rustc_ast::node_id::NodeId;
use rustc_ast::token::{self, Token}; use rustc_ast::token;
use rustc_ast::tokenstream::{AttrTokenStream, AttrTokenTree, LazyAttrTokenStream}; use rustc_ast::tokenstream::{AttrTokenStream, AttrTokenTree, LazyAttrTokenStream};
use rustc_errors::Diag; use rustc_errors::Diag;
use rustc_parse::parser::Recovery; use rustc_parse::parser::Recovery;
@ -23,6 +23,7 @@ pub fn parse_expr(psess: &ParseSess, source_code: &str) -> Option<Box<Expr>> {
psess, psess,
FileName::anon_source_code(source_code), FileName::anon_source_code(source_code),
source_code.to_owned(), source_code.to_owned(),
rustc_parse::lexer::StripTokens::Nothing,
)); ));
let mut parser = parser.recovery(Recovery::Forbidden); let mut parser = parser.recovery(Recovery::Forbidden);

View file

@ -16,7 +16,7 @@ extern crate rustc_span;
#[allow(unused_extern_crates)] #[allow(unused_extern_crates)]
extern crate rustc_driver; extern crate rustc_driver;
use rustc_parse::{new_parser_from_file, unwrap_or_emit_fatal}; use rustc_parse::{lexer::StripTokens, new_parser_from_file, unwrap_or_emit_fatal};
use rustc_session::parse::ParseSess; use rustc_session::parse::ParseSess;
use std::path::Path; use std::path::Path;
@ -34,6 +34,11 @@ fn parse() {
let path = Path::new(file!()); let path = Path::new(file!());
let path = path.canonicalize().unwrap(); let path = path.canonicalize().unwrap();
let mut parser = unwrap_or_emit_fatal(new_parser_from_file(&psess, &path, None)); let mut parser = unwrap_or_emit_fatal(new_parser_from_file(
&psess,
&path,
StripTokens::ShebangAndFrontmatter,
None,
));
let _ = parser.parse_crate_mod(); let _ = parser.parse_crate_mod();
} }

View file

@ -13,6 +13,6 @@ fn ordering4 < 'a , 'b > ( a : , self , self , self ,
//~| ERROR unexpected `self` parameter in function //~| ERROR unexpected `self` parameter in function
//~| ERROR unexpected `self` parameter in function //~| ERROR unexpected `self` parameter in function
//~| ERROR `...` must be the last argument of a C-variadic function //~| ERROR `...` must be the last argument of a C-variadic function
//~| ERROR defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention //~| ERROR `...` is not supported for non-extern functions
//~| ERROR cannot find type `F` in this scope //~| ERROR cannot find type `F` in this scope
} }

View file

@ -46,11 +46,13 @@ error: `...` must be the last argument of a C-variadic function
LL | self , ... , self , self , ... ) where F : FnOnce ( & 'a & 'b usize ) { LL | self , ... , self , self , ... ) where F : FnOnce ( & 'a & 'b usize ) {
| ^^^ | ^^^
error: defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention error: `...` is not supported for non-extern functions
--> $DIR/issue-86053-1.rs:11:36 --> $DIR/issue-86053-1.rs:11:36
| |
LL | self , ... , self , self , ... ) where F : FnOnce ( & 'a & 'b usize ) { LL | self , ... , self , self , ... ) where F : FnOnce ( & 'a & 'b usize ) {
| ^^^ | ^^^
|
= help: only `extern "C"` and `extern "C-unwind"` functions may have a C variable argument list
error[E0412]: cannot find type `F` in this scope error[E0412]: cannot find type `F` in this scope
--> $DIR/issue-86053-1.rs:11:48 --> $DIR/issue-86053-1.rs:11:48

View file

@ -0,0 +1,7 @@
//@ edition: 2021
#![feature(c_variadic)]
#![crate_type = "lib"]
async unsafe extern "C" fn cannot_be_async(x: isize, ...) {}
//~^ ERROR functions cannot be both `async` and C-variadic
//~| ERROR hidden type for `impl Future<Output = ()>` captures lifetime that does not appear in bounds

View file

@ -0,0 +1,19 @@
error: functions cannot be both `async` and C-variadic
--> $DIR/not-async.rs:5:1
|
LL | async unsafe extern "C" fn cannot_be_async(x: isize, ...) {}
| ^^^^^ `async` because of this ^^^ C-variadic because of this
error[E0700]: hidden type for `impl Future<Output = ()>` captures lifetime that does not appear in bounds
--> $DIR/not-async.rs:5:59
|
LL | async unsafe extern "C" fn cannot_be_async(x: isize, ...) {}
| --------------------------------------------------------- ^^
| |
| opaque type defined here
|
= note: hidden type `{async fn body of cannot_be_async()}` captures lifetime `'_`
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0700`.

View file

@ -53,9 +53,7 @@ extern "cmse-nonsecure-entry" fn trait_object(x: &dyn Trait) -> &dyn Trait {
x x
} }
extern "cmse-nonsecure-entry" fn static_trait_object( extern "cmse-nonsecure-entry" fn static_trait_object(x: &'static dyn Trait) -> &'static dyn Trait {
x: &'static dyn Trait,
) -> &'static dyn Trait {
//~^ ERROR return value of `"cmse-nonsecure-entry"` function too large to pass via registers [E0798] //~^ ERROR return value of `"cmse-nonsecure-entry"` function too large to pass via registers [E0798]
x x
} }
@ -63,14 +61,12 @@ extern "cmse-nonsecure-entry" fn static_trait_object(
#[repr(transparent)] #[repr(transparent)]
struct WrapperTransparent<'a>(&'a dyn Trait); struct WrapperTransparent<'a>(&'a dyn Trait);
extern "cmse-nonsecure-entry" fn wrapped_trait_object( extern "cmse-nonsecure-entry" fn wrapped_trait_object(x: WrapperTransparent) -> WrapperTransparent {
x: WrapperTransparent,
) -> WrapperTransparent {
//~^ ERROR return value of `"cmse-nonsecure-entry"` function too large to pass via registers [E0798] //~^ ERROR return value of `"cmse-nonsecure-entry"` function too large to pass via registers [E0798]
x x
} }
extern "cmse-nonsecure-entry" fn c_variadic(_: u32, _: ...) { unsafe extern "cmse-nonsecure-entry" fn c_variadic(_: u32, _: ...) {
//~^ ERROR defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention //~^ ERROR `...` is not supported for `extern "cmse-nonsecure-entry"` functions
//~| ERROR requires `va_list` lang_item //~| ERROR requires `va_list` lang_item
} }

View file

@ -1,8 +1,12 @@
error: defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention error: `...` is not supported for `extern "cmse-nonsecure-entry"` functions
--> $DIR/generics.rs:73:53 --> $DIR/generics.rs:69:60
| |
LL | extern "cmse-nonsecure-entry" fn c_variadic(_: u32, _: ...) { LL | unsafe extern "cmse-nonsecure-entry" fn c_variadic(_: u32, _: ...) {
| ^^^^^^ | ----------------------------- ^^^^^^
| |
| `extern "cmse-nonsecure-entry"` because of this
|
= help: only `extern "C"` and `extern "C-unwind"` functions may have a C variable argument list
error[E0798]: functions with the `"cmse-nonsecure-entry"` ABI cannot contain generics in their type error[E0798]: functions with the `"cmse-nonsecure-entry"` ABI cannot contain generics in their type
--> $DIR/generics.rs:30:1 --> $DIR/generics.rs:30:1
@ -50,28 +54,28 @@ LL | extern "cmse-nonsecure-entry" fn trait_object(x: &dyn Trait) -> &dyn Trait
= note: the result must either be a (transparently wrapped) i64, u64 or f64, or be at most 4 bytes in size = note: the result must either be a (transparently wrapped) i64, u64 or f64, or be at most 4 bytes in size
error[E0798]: return value of `"cmse-nonsecure-entry"` function too large to pass via registers error[E0798]: return value of `"cmse-nonsecure-entry"` function too large to pass via registers
--> $DIR/generics.rs:58:6 --> $DIR/generics.rs:56:80
| |
LL | ) -> &'static dyn Trait { LL | extern "cmse-nonsecure-entry" fn static_trait_object(x: &'static dyn Trait) -> &'static dyn Trait {
| ^^^^^^^^^^^^^^^^^^ this type doesn't fit in the available registers | ^^^^^^^^^^^^^^^^^^ this type doesn't fit in the available registers
| |
= note: functions with the `"cmse-nonsecure-entry"` ABI must pass their result via the available return registers = note: functions with the `"cmse-nonsecure-entry"` ABI must pass their result via the available return registers
= note: the result must either be a (transparently wrapped) i64, u64 or f64, or be at most 4 bytes in size = note: the result must either be a (transparently wrapped) i64, u64 or f64, or be at most 4 bytes in size
error[E0798]: return value of `"cmse-nonsecure-entry"` function too large to pass via registers error[E0798]: return value of `"cmse-nonsecure-entry"` function too large to pass via registers
--> $DIR/generics.rs:68:6 --> $DIR/generics.rs:64:81
| |
LL | ) -> WrapperTransparent { LL | extern "cmse-nonsecure-entry" fn wrapped_trait_object(x: WrapperTransparent) -> WrapperTransparent {
| ^^^^^^^^^^^^^^^^^^ this type doesn't fit in the available registers | ^^^^^^^^^^^^^^^^^^ this type doesn't fit in the available registers
| |
= note: functions with the `"cmse-nonsecure-entry"` ABI must pass their result via the available return registers = note: functions with the `"cmse-nonsecure-entry"` ABI must pass their result via the available return registers
= note: the result must either be a (transparently wrapped) i64, u64 or f64, or be at most 4 bytes in size = note: the result must either be a (transparently wrapped) i64, u64 or f64, or be at most 4 bytes in size
error: requires `va_list` lang_item error: requires `va_list` lang_item
--> $DIR/generics.rs:73:53 --> $DIR/generics.rs:69:60
| |
LL | extern "cmse-nonsecure-entry" fn c_variadic(_: u32, _: ...) { LL | unsafe extern "cmse-nonsecure-entry" fn c_variadic(_: u32, _: ...) {
| ^^^^^^ | ^^^^^^
error: aborting due to 9 previous errors error: aborting due to 9 previous errors

View file

@ -0,0 +1,79 @@
// The purpose of this file is to track the error messages from Pin and DerefMut interacting.
//
// Identical to `pin-deref.rs` except for using unstable `const fn`.
//@ check-fail
#![feature(const_convert)]
#![feature(const_trait_impl)]
use std::ops::DerefMut;
use std::pin::Pin;
struct MyUnpinType {}
impl MyUnpinType {
const fn at_self(&self) {}
const fn at_mut_self(&mut self) {}
}
struct MyPinType(core::marker::PhantomPinned);
impl MyPinType {
const fn at_self(&self) {}
const fn at_mut_self(&mut self) {}
}
const fn call_mut_ref_unpin(mut r_unpin: Pin<&mut MyUnpinType>) {
r_unpin.at_self();
r_unpin.at_mut_self();
}
const fn call_ref_unpin(mut r_unpin: Pin<&MyUnpinType>) {
r_unpin.at_self();
r_unpin.at_mut_self(); //~ ERROR: cannot borrow data in dereference of `Pin<&MyUnpinType>` as mutable
}
const fn call_mut_ref_pin(mut r_pin: Pin<&mut MyPinType>) {
r_pin.at_self();
r_pin.at_mut_self(); //~ ERROR: cannot borrow data in dereference of `Pin<&mut MyPinType>` as mutable
}
const fn call_ref_pin(mut r_pin: Pin<&MyPinType>) {
r_pin.at_self();
r_pin.at_mut_self(); //~ ERROR: cannot borrow data in dereference of `Pin<&MyPinType>` as mutable
}
const fn coerce_unpin_rr<'a>(mut r_unpin: &'a mut Pin<&MyUnpinType>) -> &'a MyUnpinType {
r_unpin
}
const fn coerce_unpin_rm<'a>(mut r_unpin: &'a mut Pin<&MyUnpinType>) -> &'a mut MyUnpinType {
r_unpin //~ ERROR: cannot borrow data in dereference of `Pin<&MyUnpinType>` as mutable
}
const fn coerce_unpin_mr<'a>(mut r_unpin: &'a mut Pin<&mut MyUnpinType>) -> &'a MyUnpinType {
r_unpin
}
const fn coerce_unpin_mm<'a>(mut r_unpin: &'a mut Pin<&mut MyUnpinType>) -> &'a mut MyUnpinType {
r_unpin
}
const fn coerce_pin_rr<'a>(mut r_pin: &'a mut Pin<&MyPinType>) -> &'a MyPinType {
r_pin
}
const fn coerce_pin_rm<'a>(mut r_pin: &'a mut Pin<&MyPinType>) -> &'a mut MyPinType {
r_pin //~ ERROR: cannot borrow data in dereference of `Pin<&MyPinType>` as mutable
}
const fn coerce_pin_mr<'a>(mut r_pin: &'a mut Pin<&mut MyPinType>) -> &'a MyPinType {
r_pin
}
const fn coerce_pin_mm<'a>(mut r_pin: &'a mut Pin<&mut MyPinType>) -> &'a mut MyPinType {
r_pin //~ ERROR: cannot borrow data in dereference of `Pin<&mut MyPinType>` as mutable
}
fn main() {}

View file

@ -0,0 +1,51 @@
error[E0596]: cannot borrow data in dereference of `Pin<&MyUnpinType>` as mutable
--> $DIR/pin-deref-const.rs:34:5
|
LL | r_unpin.at_mut_self();
| ^^^^^^^ cannot borrow as mutable
|
= help: trait `DerefMut` is required to modify through a dereference, but it is not implemented for `Pin<&MyUnpinType>`
error[E0596]: cannot borrow data in dereference of `Pin<&mut MyPinType>` as mutable
--> $DIR/pin-deref-const.rs:39:5
|
LL | r_pin.at_mut_self();
| ^^^^^ cannot borrow as mutable
|
= help: trait `DerefMut` is required to modify through a dereference, but it is not implemented for `Pin<&mut MyPinType>`
error[E0596]: cannot borrow data in dereference of `Pin<&MyPinType>` as mutable
--> $DIR/pin-deref-const.rs:44:5
|
LL | r_pin.at_mut_self();
| ^^^^^ cannot borrow as mutable
|
= help: trait `DerefMut` is required to modify through a dereference, but it is not implemented for `Pin<&MyPinType>`
error[E0596]: cannot borrow data in dereference of `Pin<&MyUnpinType>` as mutable
--> $DIR/pin-deref-const.rs:52:5
|
LL | r_unpin
| ^^^^^^^ cannot borrow as mutable
|
= help: trait `DerefMut` is required to modify through a dereference, but it is not implemented for `Pin<&MyUnpinType>`
error[E0596]: cannot borrow data in dereference of `Pin<&MyPinType>` as mutable
--> $DIR/pin-deref-const.rs:68:5
|
LL | r_pin
| ^^^^^ cannot borrow as mutable
|
= help: trait `DerefMut` is required to modify through a dereference, but it is not implemented for `Pin<&MyPinType>`
error[E0596]: cannot borrow data in dereference of `Pin<&mut MyPinType>` as mutable
--> $DIR/pin-deref-const.rs:76:5
|
LL | r_pin
| ^^^^^ cannot borrow as mutable
|
= help: trait `DerefMut` is required to modify through a dereference, but it is not implemented for `Pin<&mut MyPinType>`
error: aborting due to 6 previous errors
For more information about this error, try `rustc --explain E0596`.

View file

@ -0,0 +1,76 @@
// The purpose of this file is to track the error messages from Pin and DerefMut interacting.
//
// Identical to `pin-deref-const.rs` except for being stable and not using `const fn`.
//@ check-fail
use std::ops::DerefMut;
use std::pin::Pin;
struct MyUnpinType {}
impl MyUnpinType {
fn at_self(&self) {}
fn at_mut_self(&mut self) {}
}
struct MyPinType(core::marker::PhantomPinned);
impl MyPinType {
fn at_self(&self) {}
fn at_mut_self(&mut self) {}
}
fn call_mut_ref_unpin(mut r_unpin: Pin<&mut MyUnpinType>) {
r_unpin.at_self();
r_unpin.at_mut_self();
}
fn call_ref_unpin(mut r_unpin: Pin<&MyUnpinType>) {
r_unpin.at_self();
r_unpin.at_mut_self(); //~ ERROR: cannot borrow data in dereference of `Pin<&MyUnpinType>` as mutable
}
fn call_mut_ref_pin(mut r_pin: Pin<&mut MyPinType>) {
r_pin.at_self();
r_pin.at_mut_self(); //~ ERROR: cannot borrow data in dereference of `Pin<&mut MyPinType>` as mutable
}
fn call_ref_pin(mut r_pin: Pin<&MyPinType>) {
r_pin.at_self();
r_pin.at_mut_self(); //~ ERROR: cannot borrow data in dereference of `Pin<&MyPinType>` as mutable
}
fn coerce_unpin_rr<'a>(mut r_unpin: &'a mut Pin<&MyUnpinType>) -> &'a MyUnpinType {
r_unpin
}
fn coerce_unpin_rm<'a>(mut r_unpin: &'a mut Pin<&MyUnpinType>) -> &'a mut MyUnpinType {
r_unpin //~ ERROR: cannot borrow data in dereference of `Pin<&MyUnpinType>` as mutable
}
fn coerce_unpin_mr<'a>(mut r_unpin: &'a mut Pin<&mut MyUnpinType>) -> &'a MyUnpinType {
r_unpin
}
fn coerce_unpin_mm<'a>(mut r_unpin: &'a mut Pin<&mut MyUnpinType>) -> &'a mut MyUnpinType {
r_unpin
}
fn coerce_pin_rr<'a>(mut r_pin: &'a mut Pin<&MyPinType>) -> &'a MyPinType {
r_pin
}
fn coerce_pin_rm<'a>(mut r_pin: &'a mut Pin<&MyPinType>) -> &'a mut MyPinType {
r_pin //~ ERROR: cannot borrow data in dereference of `Pin<&MyPinType>` as mutable
}
fn coerce_pin_mr<'a>(mut r_pin: &'a mut Pin<&mut MyPinType>) -> &'a MyPinType {
r_pin
}
fn coerce_pin_mm<'a>(mut r_pin: &'a mut Pin<&mut MyPinType>) -> &'a mut MyPinType {
r_pin //~ ERROR: cannot borrow data in dereference of `Pin<&mut MyPinType>` as mutable
}
fn main() {}

View file

@ -0,0 +1,51 @@
error[E0596]: cannot borrow data in dereference of `Pin<&MyUnpinType>` as mutable
--> $DIR/pin-deref.rs:31:5
|
LL | r_unpin.at_mut_self();
| ^^^^^^^ cannot borrow as mutable
|
= help: trait `DerefMut` is required to modify through a dereference, but it is not implemented for `Pin<&MyUnpinType>`
error[E0596]: cannot borrow data in dereference of `Pin<&mut MyPinType>` as mutable
--> $DIR/pin-deref.rs:36:5
|
LL | r_pin.at_mut_self();
| ^^^^^ cannot borrow as mutable
|
= help: trait `DerefMut` is required to modify through a dereference, but it is not implemented for `Pin<&mut MyPinType>`
error[E0596]: cannot borrow data in dereference of `Pin<&MyPinType>` as mutable
--> $DIR/pin-deref.rs:41:5
|
LL | r_pin.at_mut_self();
| ^^^^^ cannot borrow as mutable
|
= help: trait `DerefMut` is required to modify through a dereference, but it is not implemented for `Pin<&MyPinType>`
error[E0596]: cannot borrow data in dereference of `Pin<&MyUnpinType>` as mutable
--> $DIR/pin-deref.rs:49:5
|
LL | r_unpin
| ^^^^^^^ cannot borrow as mutable
|
= help: trait `DerefMut` is required to modify through a dereference, but it is not implemented for `Pin<&MyUnpinType>`
error[E0596]: cannot borrow data in dereference of `Pin<&MyPinType>` as mutable
--> $DIR/pin-deref.rs:65:5
|
LL | r_pin
| ^^^^^ cannot borrow as mutable
|
= help: trait `DerefMut` is required to modify through a dereference, but it is not implemented for `Pin<&MyPinType>`
error[E0596]: cannot borrow data in dereference of `Pin<&mut MyPinType>` as mutable
--> $DIR/pin-deref.rs:73:5
|
LL | r_pin
| ^^^^^ cannot borrow as mutable
|
= help: trait `DerefMut` is required to modify through a dereference, but it is not implemented for `Pin<&mut MyPinType>`
error: aborting due to 6 previous errors
For more information about this error, try `rustc --explain E0596`.

View file

@ -0,0 +1,40 @@
// The purpose of this file is to track the error messages from Pin and DerefMut interacting.
//@ check-fail
use std::ops::DerefMut;
use std::pin::Pin;
struct MyUnpinType {}
impl MyUnpinType {
fn at_self(&self) {}
fn at_mut_self(&mut self) {}
}
struct MyPinType(core::marker::PhantomPinned);
impl MyPinType {
fn at_self(&self) {}
fn at_mut_self(&mut self) {}
}
fn impl_deref_mut(_: impl DerefMut) {}
fn unpin_impl_ref(r_unpin: Pin<&MyUnpinType>) {
impl_deref_mut(r_unpin)
//~^ ERROR: the trait bound `Pin<&MyUnpinType>: DerefMut` is not satisfied
}
fn unpin_impl_mut(r_unpin: Pin<&mut MyUnpinType>) {
impl_deref_mut(r_unpin)
}
fn pin_impl_ref(r_pin: Pin<&MyPinType>) {
impl_deref_mut(r_pin)
//~^ ERROR: `PhantomPinned` cannot be unpinned
//~| ERROR: the trait bound `Pin<&MyPinType>: DerefMut` is not satisfied
}
fn pin_impl_mut(r_pin: Pin<&mut MyPinType>) {
impl_deref_mut(r_pin)
//~^ ERROR: `PhantomPinned` cannot be unpinned
}
fn main() {}

View file

@ -0,0 +1,85 @@
error[E0277]: the trait bound `Pin<&MyUnpinType>: DerefMut` is not satisfied
--> $DIR/pin-impl-deref.rs:24:20
|
LL | impl_deref_mut(r_unpin)
| -------------- ^^^^^^^ the trait `DerefMut` is not implemented for `Pin<&MyUnpinType>`
| |
| required by a bound introduced by this call
|
= note: required for `Pin<&MyUnpinType>` to implement `DerefMut`
note: required by a bound in `impl_deref_mut`
--> $DIR/pin-impl-deref.rs:22:27
|
LL | fn impl_deref_mut(_: impl DerefMut) {}
| ^^^^^^^^ required by this bound in `impl_deref_mut`
help: consider mutably borrowing here
|
LL | impl_deref_mut(&mut r_unpin)
| ++++
error[E0277]: the trait bound `Pin<&MyPinType>: DerefMut` is not satisfied
--> $DIR/pin-impl-deref.rs:31:20
|
LL | impl_deref_mut(r_pin)
| -------------- ^^^^^ the trait `DerefMut` is not implemented for `Pin<&MyPinType>`
| |
| required by a bound introduced by this call
|
= note: required for `Pin<&MyPinType>` to implement `DerefMut`
note: required by a bound in `impl_deref_mut`
--> $DIR/pin-impl-deref.rs:22:27
|
LL | fn impl_deref_mut(_: impl DerefMut) {}
| ^^^^^^^^ required by this bound in `impl_deref_mut`
help: consider mutably borrowing here
|
LL | impl_deref_mut(&mut r_pin)
| ++++
error[E0277]: `PhantomPinned` cannot be unpinned
--> $DIR/pin-impl-deref.rs:31:20
|
LL | impl_deref_mut(r_pin)
| -------------- ^^^^^ within `MyPinType`, the trait `Unpin` is not implemented for `PhantomPinned`
| |
| required by a bound introduced by this call
|
= note: consider using the `pin!` macro
consider using `Box::pin` if you need to access the pinned value outside of the current scope
note: required because it appears within the type `MyPinType`
--> $DIR/pin-impl-deref.rs:15:8
|
LL | struct MyPinType(core::marker::PhantomPinned);
| ^^^^^^^^^
= note: required for `Pin<&MyPinType>` to implement `DerefMut`
note: required by a bound in `impl_deref_mut`
--> $DIR/pin-impl-deref.rs:22:27
|
LL | fn impl_deref_mut(_: impl DerefMut) {}
| ^^^^^^^^ required by this bound in `impl_deref_mut`
error[E0277]: `PhantomPinned` cannot be unpinned
--> $DIR/pin-impl-deref.rs:36:20
|
LL | impl_deref_mut(r_pin)
| -------------- ^^^^^ within `MyPinType`, the trait `Unpin` is not implemented for `PhantomPinned`
| |
| required by a bound introduced by this call
|
= note: consider using the `pin!` macro
consider using `Box::pin` if you need to access the pinned value outside of the current scope
note: required because it appears within the type `MyPinType`
--> $DIR/pin-impl-deref.rs:15:8
|
LL | struct MyPinType(core::marker::PhantomPinned);
| ^^^^^^^^^
= note: required for `Pin<&mut MyPinType>` to implement `DerefMut`
note: required by a bound in `impl_deref_mut`
--> $DIR/pin-impl-deref.rs:22:27
|
LL | fn impl_deref_mut(_: impl DerefMut) {}
| ^^^^^^^^ required by this bound in `impl_deref_mut`
error: aborting due to 4 previous errors
For more information about this error, try `rustc --explain E0277`.

View file

@ -1,10 +1,10 @@
#![crate_type="lib"] #![crate_type = "lib"]
pub unsafe extern "C" fn test(_: i32, ap: ...) { } pub unsafe extern "C" fn test(_: i32, ap: ...) {}
//~^ ERROR C-variadic functions are unstable //~^ ERROR C-variadic functions are unstable
trait Trait { trait Trait {
unsafe extern "C" fn trait_test(_: i32, ap: ...) { } unsafe extern "C" fn trait_test(_: i32, ap: ...) {}
//~^ ERROR C-variadic functions are unstable //~^ ERROR C-variadic functions are unstable
//~| ERROR defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention //~| ERROR associated functions cannot have a C variable argument list
} }

View file

@ -1,14 +1,14 @@
error: defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention error: associated functions cannot have a C variable argument list
--> $DIR/feature-gate-c_variadic.rs:7:45 --> $DIR/feature-gate-c_variadic.rs:7:45
| |
LL | unsafe extern "C" fn trait_test(_: i32, ap: ...) { } LL | unsafe extern "C" fn trait_test(_: i32, ap: ...) {}
| ^^^^^^^ | ^^^^^^^
error[E0658]: C-variadic functions are unstable error[E0658]: C-variadic functions are unstable
--> $DIR/feature-gate-c_variadic.rs:3:1 --> $DIR/feature-gate-c_variadic.rs:3:1
| |
LL | pub unsafe extern "C" fn test(_: i32, ap: ...) { } LL | pub unsafe extern "C" fn test(_: i32, ap: ...) {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| |
= note: see issue #44930 <https://github.com/rust-lang/rust/issues/44930> for more information = note: see issue #44930 <https://github.com/rust-lang/rust/issues/44930> for more information
= help: add `#![feature(c_variadic)]` to the crate attributes to enable = help: add `#![feature(c_variadic)]` to the crate attributes to enable
@ -17,8 +17,8 @@ LL | pub unsafe extern "C" fn test(_: i32, ap: ...) { }
error[E0658]: C-variadic functions are unstable error[E0658]: C-variadic functions are unstable
--> $DIR/feature-gate-c_variadic.rs:7:5 --> $DIR/feature-gate-c_variadic.rs:7:5
| |
LL | unsafe extern "C" fn trait_test(_: i32, ap: ...) { } LL | unsafe extern "C" fn trait_test(_: i32, ap: ...) {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| |
= note: see issue #44930 <https://github.com/rust-lang/rust/issues/44930> for more information = note: see issue #44930 <https://github.com/rust-lang/rust/issues/44930> for more information
= help: add `#![feature(c_variadic)]` to the crate attributes to enable = help: add `#![feature(c_variadic)]` to the crate attributes to enable

View file

@ -62,6 +62,11 @@ LL | format!("", 1, 2);
| | | | | |
| | argument never used | | argument never used
| multiple missing formatting specifiers | multiple missing formatting specifiers
|
help: format specifiers use curly braces, consider adding 2 format specifiers
|
LL | format!("{}{}", 1, 2);
| ++++
error: argument never used error: argument never used
--> $DIR/ifmt-bad-arg.rs:33:22 --> $DIR/ifmt-bad-arg.rs:33:22
@ -102,6 +107,11 @@ LL | format!("", foo=2);
| -- ^ named argument never used | -- ^ named argument never used
| | | |
| formatting specifier missing | formatting specifier missing
|
help: format specifiers use curly braces, consider adding a format specifier
|
LL | format!("{}", foo=2);
| ++
error: multiple unused formatting arguments error: multiple unused formatting arguments
--> $DIR/ifmt-bad-arg.rs:38:32 --> $DIR/ifmt-bad-arg.rs:38:32
@ -111,6 +121,8 @@ LL | format!("{} {}", 1, 2, foo=1, bar=2);
| | | | | |
| | named argument never used | | named argument never used
| multiple missing formatting specifiers | multiple missing formatting specifiers
|
= note: consider adding 2 format specifiers
error: duplicate argument named `foo` error: duplicate argument named `foo`
--> $DIR/ifmt-bad-arg.rs:40:29 --> $DIR/ifmt-bad-arg.rs:40:29

View file

@ -0,0 +1,4 @@
---
-
---
1

View file

@ -1,8 +1,20 @@
extern crate proc_macro; extern crate proc_macro;
use proc_macro::TokenStream; use proc_macro::{Literal, TokenStream};
#[proc_macro] #[proc_macro]
pub fn check(_: TokenStream) -> TokenStream { pub fn check(_: TokenStream) -> TokenStream {
// In the following test cases, the `---` may look like the start of frontmatter but it is not!
// That's because it would be backward incompatible to interpret them as such in the latest
// stable edition. That's not only the case due to the feature gate error but also due to the
// fact that we "eagerly" emit errors on malformed frontmatter.
// issue: <https://github.com/rust-lang/rust/issues/145520>
_ = "---".parse::<TokenStream>();
// Just a sequence of regular Rust punctuation tokens.
assert_eq!(6, "---\n---".parse::<TokenStream>().unwrap().into_iter().count()); assert_eq!(6, "---\n---".parse::<TokenStream>().unwrap().into_iter().count());
// issue: <https://github.com/rust-lang/rust/issues/146132>
assert!("---".parse::<Literal>().is_err());
Default::default() Default::default()
} }

View file

@ -0,0 +1,9 @@
// Check that an expr-ctxt `include` doesn't try to parse frontmatter and instead
// treats it as a regular Rust token sequence.
//@ check-pass
#![expect(double_negations)]
fn main() {
// issue: <https://github.com/rust-lang/rust/issues/145945>
const _: () = assert!(-1 == include!("auxiliary/expr.rs"));
}

View file

@ -0,0 +1,10 @@
// Ensure that in item ctxts we can `include` files that contain frontmatter.
//@ check-pass
#![feature(frontmatter)]
include!("auxiliary/lib.rs");
fn main() {
foo(1);
}

View file

@ -1,12 +0,0 @@
#![feature(frontmatter)]
//@ check-pass
include!("auxiliary/lib.rs");
// auxiliary/lib.rs contains a frontmatter. Ensure that we can use them in an
// `include!` macro.
fn main() {
foo(1);
}

View file

@ -2,10 +2,9 @@
//@ proc-macro: makro.rs //@ proc-macro: makro.rs
//@ edition: 2021 //@ edition: 2021
// Check that a proc-macro doesn't try to parse frontmatter and instead treats
// it as a regular Rust token sequence. See `auxiliary/makro.rs` for details.
makro::check!(); makro::check!();
// checks that a proc-macro doesn't know or parse frontmatters at all and instead treats
// it as normal Rust code.
// see auxiliary/makro.rs for how it is tested.
fn main() {} fn main() {}

View file

@ -3,6 +3,7 @@
#![feature(c_variadic)] #![feature(c_variadic)]
async unsafe extern "C" fn multiple_named_lifetimes<'a, 'b>(_: u8, ...) {} async unsafe extern "C" fn multiple_named_lifetimes<'a, 'b>(_: u8, ...) {}
//~^ ERROR hidden type for `impl Future<Output = ()>` captures lifetime that does not appear in bounds //~^ ERROR functions cannot be both `async` and C-variadic
//~| ERROR hidden type for `impl Future<Output = ()>` captures lifetime that does not appear in bounds
fn main() {} fn main() {}

View file

@ -1,3 +1,9 @@
error: functions cannot be both `async` and C-variadic
--> $DIR/note-and-explain-ReVar-124973.rs:5:1
|
LL | async unsafe extern "C" fn multiple_named_lifetimes<'a, 'b>(_: u8, ...) {}
| ^^^^^ `async` because of this ^^^ C-variadic because of this
error[E0700]: hidden type for `impl Future<Output = ()>` captures lifetime that does not appear in bounds error[E0700]: hidden type for `impl Future<Output = ()>` captures lifetime that does not appear in bounds
--> $DIR/note-and-explain-ReVar-124973.rs:5:73 --> $DIR/note-and-explain-ReVar-124973.rs:5:73
| |
@ -8,6 +14,6 @@ LL | async unsafe extern "C" fn multiple_named_lifetimes<'a, 'b>(_: u8, ...) {}
| |
= note: hidden type `{async fn body of multiple_named_lifetimes<'a, 'b>()}` captures lifetime `'_` = note: hidden type `{async fn body of multiple_named_lifetimes<'a, 'b>()}` captures lifetime `'_`
error: aborting due to 1 previous error error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0700`. For more information about this error, try `rustc --explain E0700`.

View file

@ -7,6 +7,11 @@ LL | println!("Test", 123, 456, 789);
| | | argument never used | | | argument never used
| | argument never used | | argument never used
| multiple missing formatting specifiers | multiple missing formatting specifiers
|
help: format specifiers use curly braces, consider adding 3 format specifiers
|
LL | println!("Test{}{}{}", 123, 456, 789);
| ++++++
error: multiple unused formatting arguments error: multiple unused formatting arguments
--> $DIR/format-unused-lables.rs:6:9 --> $DIR/format-unused-lables.rs:6:9
@ -19,6 +24,11 @@ LL | 456,
| ^^^ argument never used | ^^^ argument never used
LL | 789 LL | 789
| ^^^ argument never used | ^^^ argument never used
|
help: format specifiers use curly braces, consider adding 3 format specifiers
|
LL | println!("Test2{}{}{}",
| ++++++
error: named argument never used error: named argument never used
--> $DIR/format-unused-lables.rs:11:35 --> $DIR/format-unused-lables.rs:11:35
@ -27,6 +37,11 @@ LL | println!("Some stuff", UNUSED="args");
| ------------ ^^^^^^ named argument never used | ------------ ^^^^^^ named argument never used
| | | |
| formatting specifier missing | formatting specifier missing
|
help: format specifiers use curly braces, consider adding a format specifier
|
LL | println!("Some stuff{}", UNUSED="args");
| ++
error: multiple unused formatting arguments error: multiple unused formatting arguments
--> $DIR/format-unused-lables.rs:14:9 --> $DIR/format-unused-lables.rs:14:9

View file

@ -4,7 +4,6 @@
fn main() {} fn main() {}
fn foo(_: Bar, ...) -> impl {} unsafe extern "C" fn foo(_: Bar, ...) -> impl {}
//~^ ERROR defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention //~^ ERROR cannot find type `Bar` in this scope
//~| ERROR cannot find type `Bar` in this scope
//~| ERROR at least one trait must be specified //~| ERROR at least one trait must be specified

View file

@ -1,21 +1,15 @@
error: defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention
--> $DIR/issue-83499-input-output-iteration-ice.rs:7:16
|
LL | fn foo(_: Bar, ...) -> impl {}
| ^^^
error: at least one trait must be specified error: at least one trait must be specified
--> $DIR/issue-83499-input-output-iteration-ice.rs:7:24 --> $DIR/issue-83499-input-output-iteration-ice.rs:7:42
| |
LL | fn foo(_: Bar, ...) -> impl {} LL | unsafe extern "C" fn foo(_: Bar, ...) -> impl {}
| ^^^^ | ^^^^
error[E0412]: cannot find type `Bar` in this scope error[E0412]: cannot find type `Bar` in this scope
--> $DIR/issue-83499-input-output-iteration-ice.rs:7:11 --> $DIR/issue-83499-input-output-iteration-ice.rs:7:29
| |
LL | fn foo(_: Bar, ...) -> impl {} LL | unsafe extern "C" fn foo(_: Bar, ...) -> impl {}
| ^^^ not found in this scope | ^^^ not found in this scope
error: aborting due to 3 previous errors error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0412`. For more information about this error, try `rustc --explain E0412`.

View file

@ -5,6 +5,11 @@ LL | println!("C", unsafe { &symbol });
| --- ^^^^^^^^^^^^^^^^^^ argument never used | --- ^^^^^^^^^^^^^^^^^^ argument never used
| | | |
| formatting specifier missing | formatting specifier missing
|
help: format specifiers use curly braces, consider adding a format specifier
|
LL | println!("C{}", unsafe { &symbol });
| ++
error[E0277]: the size for values of type `[i8]` cannot be known at compilation time error[E0277]: the size for values of type `[i8]` cannot be known at compilation time
--> $DIR/unsized-extern-static.rs:6:5 --> $DIR/unsized-extern-static.rs:6:5

View file

@ -4,25 +4,28 @@
fn main() {} fn main() {}
fn f1_1(x: isize, ...) {} fn f1_1(x: isize, ...) {}
//~^ ERROR defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention //~^ ERROR `...` is not supported for non-extern functions
fn f1_2(...) {} fn f1_2(...) {}
//~^ ERROR defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention //~^ ERROR `...` is not supported for non-extern functions
unsafe extern "Rust" fn f1_3(...) {}
//~^ ERROR `...` is not supported for `extern "Rust"` functions
extern "C" fn f2_1(x: isize, ...) {} extern "C" fn f2_1(x: isize, ...) {}
//~^ ERROR defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention //~^ ERROR functions with a C variable argument list must be unsafe
extern "C" fn f2_2(...) {} extern "C" fn f2_2(...) {}
//~^ ERROR defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention //~^ ERROR functions with a C variable argument list must be unsafe
extern "C" fn f2_3(..., x: isize) {} extern "C" fn f2_3(..., x: isize) {}
//~^ ERROR `...` must be the last argument of a C-variadic function //~^ ERROR `...` must be the last argument of a C-variadic function
extern "C" fn f3_1(x: isize, ...) {} extern "C" fn f3_1(x: isize, ...) {}
//~^ ERROR defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention //~^ ERROR functions with a C variable argument list must be unsafe
extern "C" fn f3_2(...) {} extern "C" fn f3_2(...) {}
//~^ ERROR defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention //~^ ERROR functions with a C variable argument list must be unsafe
extern "C" fn f3_3(..., x: isize) {} extern "C" fn f3_3(..., x: isize) {}
//~^ ERROR `...` must be the last argument of a C-variadic function //~^ ERROR `...` must be the last argument of a C-variadic function
@ -33,12 +36,12 @@ const unsafe extern "C" fn f4_1(x: isize, ...) {}
const extern "C" fn f4_2(x: isize, ...) {} const extern "C" fn f4_2(x: isize, ...) {}
//~^ ERROR functions cannot be both `const` and C-variadic //~^ ERROR functions cannot be both `const` and C-variadic
//~| ERROR defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention //~| ERROR functions with a C variable argument list must be unsafe
//~| ERROR destructor of `VaListImpl<'_>` cannot be evaluated at compile-time //~| ERROR destructor of `VaListImpl<'_>` cannot be evaluated at compile-time
const extern "C" fn f4_3(..., x: isize, ...) {} const extern "C" fn f4_3(..., x: isize, ...) {}
//~^ ERROR functions cannot be both `const` and C-variadic //~^ ERROR functions cannot be both `const` and C-variadic
//~| ERROR defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention //~| ERROR functions with a C variable argument list must be unsafe
//~| ERROR `...` must be the last argument of a C-variadic function //~| ERROR `...` must be the last argument of a C-variadic function
extern "C" { extern "C" {
@ -50,30 +53,30 @@ struct X;
impl X { impl X {
fn i_f1(x: isize, ...) {} fn i_f1(x: isize, ...) {}
//~^ ERROR defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention //~^ ERROR associated functions cannot have a C variable argument list
fn i_f2(...) {} fn i_f2(...) {}
//~^ ERROR defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention //~^ ERROR associated functions cannot have a C variable argument list
fn i_f3(..., x: isize, ...) {} fn i_f3(..., x: isize, ...) {}
//~^ ERROR defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention //~^ ERROR associated functions cannot have a C variable argument list
//~| ERROR `...` must be the last argument of a C-variadic function //~| ERROR `...` must be the last argument of a C-variadic function
fn i_f4(..., x: isize, ...) {} fn i_f4(..., x: isize, ...) {}
//~^ ERROR defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention //~^ ERROR associated functions cannot have a C variable argument list
//~| ERROR `...` must be the last argument of a C-variadic function //~| ERROR `...` must be the last argument of a C-variadic function
const fn i_f5(x: isize, ...) {} const fn i_f5(x: isize, ...) {}
//~^ ERROR defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention //~^ ERROR associated functions cannot have a C variable argument list
//~| ERROR functions cannot be both `const` and C-variadic //~| ERROR functions cannot be both `const` and C-variadic
//~| ERROR destructor of `VaListImpl<'_>` cannot be evaluated at compile-time //~| ERROR destructor of `VaListImpl<'_>` cannot be evaluated at compile-time
} }
trait T { trait T {
fn t_f1(x: isize, ...) {} fn t_f1(x: isize, ...) {}
//~^ ERROR defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention //~^ ERROR associated functions cannot have a C variable argument list
fn t_f2(x: isize, ...); fn t_f2(x: isize, ...);
//~^ ERROR defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention //~^ ERROR associated functions cannot have a C variable argument list
fn t_f3(...) {} fn t_f3(...) {}
//~^ ERROR defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention //~^ ERROR associated functions cannot have a C variable argument list
fn t_f4(...); fn t_f4(...);
//~^ ERROR defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention //~^ ERROR associated functions cannot have a C variable argument list
fn t_f5(..., x: isize) {} fn t_f5(..., x: isize) {}
//~^ ERROR `...` must be the last argument of a C-variadic function //~^ ERROR `...` must be the last argument of a C-variadic function
fn t_f6(..., x: isize); fn t_f6(..., x: isize);

View file

@ -1,181 +1,225 @@
error: defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention error: `...` is not supported for non-extern functions
--> $DIR/variadic-ffi-semantic-restrictions.rs:6:19 --> $DIR/variadic-ffi-semantic-restrictions.rs:6:19
| |
LL | fn f1_1(x: isize, ...) {} LL | fn f1_1(x: isize, ...) {}
| ^^^ | ^^^
|
= help: only `extern "C"` and `extern "C-unwind"` functions may have a C variable argument list
error: defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention error: `...` is not supported for non-extern functions
--> $DIR/variadic-ffi-semantic-restrictions.rs:9:9 --> $DIR/variadic-ffi-semantic-restrictions.rs:9:9
| |
LL | fn f1_2(...) {} LL | fn f1_2(...) {}
| ^^^ | ^^^
|
= help: only `extern "C"` and `extern "C-unwind"` functions may have a C variable argument list
error: defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention error: `...` is not supported for `extern "Rust"` functions
--> $DIR/variadic-ffi-semantic-restrictions.rs:12:30 --> $DIR/variadic-ffi-semantic-restrictions.rs:12:30
| |
LL | unsafe extern "Rust" fn f1_3(...) {}
| ------------- ^^^
| |
| `extern "Rust"` because of this
|
= help: only `extern "C"` and `extern "C-unwind"` functions may have a C variable argument list
error: functions with a C variable argument list must be unsafe
--> $DIR/variadic-ffi-semantic-restrictions.rs:15:30
|
LL | extern "C" fn f2_1(x: isize, ...) {} LL | extern "C" fn f2_1(x: isize, ...) {}
| ^^^ | ^^^
|
help: add the `unsafe` keyword to this definition
|
LL | unsafe extern "C" fn f2_1(x: isize, ...) {}
| ++++++
error: defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention error: functions with a C variable argument list must be unsafe
--> $DIR/variadic-ffi-semantic-restrictions.rs:15:20 --> $DIR/variadic-ffi-semantic-restrictions.rs:18:20
| |
LL | extern "C" fn f2_2(...) {} LL | extern "C" fn f2_2(...) {}
| ^^^ | ^^^
|
help: add the `unsafe` keyword to this definition
|
LL | unsafe extern "C" fn f2_2(...) {}
| ++++++
error: `...` must be the last argument of a C-variadic function error: `...` must be the last argument of a C-variadic function
--> $DIR/variadic-ffi-semantic-restrictions.rs:18:20 --> $DIR/variadic-ffi-semantic-restrictions.rs:21:20
| |
LL | extern "C" fn f2_3(..., x: isize) {} LL | extern "C" fn f2_3(..., x: isize) {}
| ^^^ | ^^^
error: defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention error: functions with a C variable argument list must be unsafe
--> $DIR/variadic-ffi-semantic-restrictions.rs:21:30 --> $DIR/variadic-ffi-semantic-restrictions.rs:24:30
| |
LL | extern "C" fn f3_1(x: isize, ...) {} LL | extern "C" fn f3_1(x: isize, ...) {}
| ^^^ | ^^^
|
help: add the `unsafe` keyword to this definition
|
LL | unsafe extern "C" fn f3_1(x: isize, ...) {}
| ++++++
error: defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention error: functions with a C variable argument list must be unsafe
--> $DIR/variadic-ffi-semantic-restrictions.rs:24:20 --> $DIR/variadic-ffi-semantic-restrictions.rs:27:20
| |
LL | extern "C" fn f3_2(...) {} LL | extern "C" fn f3_2(...) {}
| ^^^ | ^^^
|
help: add the `unsafe` keyword to this definition
|
LL | unsafe extern "C" fn f3_2(...) {}
| ++++++
error: `...` must be the last argument of a C-variadic function error: `...` must be the last argument of a C-variadic function
--> $DIR/variadic-ffi-semantic-restrictions.rs:27:20 --> $DIR/variadic-ffi-semantic-restrictions.rs:30:20
| |
LL | extern "C" fn f3_3(..., x: isize) {} LL | extern "C" fn f3_3(..., x: isize) {}
| ^^^ | ^^^
error: functions cannot be both `const` and C-variadic error: functions cannot be both `const` and C-variadic
--> $DIR/variadic-ffi-semantic-restrictions.rs:30:1 --> $DIR/variadic-ffi-semantic-restrictions.rs:33:1
| |
LL | const unsafe extern "C" fn f4_1(x: isize, ...) {} LL | const unsafe extern "C" fn f4_1(x: isize, ...) {}
| ^^^^^ `const` because of this ^^^ C-variadic because of this | ^^^^^ `const` because of this ^^^ C-variadic because of this
error: functions cannot be both `const` and C-variadic error: functions cannot be both `const` and C-variadic
--> $DIR/variadic-ffi-semantic-restrictions.rs:34:1 --> $DIR/variadic-ffi-semantic-restrictions.rs:37:1
| |
LL | const extern "C" fn f4_2(x: isize, ...) {} LL | const extern "C" fn f4_2(x: isize, ...) {}
| ^^^^^ `const` because of this ^^^ C-variadic because of this | ^^^^^ `const` because of this ^^^ C-variadic because of this
error: defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention error: functions with a C variable argument list must be unsafe
--> $DIR/variadic-ffi-semantic-restrictions.rs:34:36 --> $DIR/variadic-ffi-semantic-restrictions.rs:37:36
| |
LL | const extern "C" fn f4_2(x: isize, ...) {} LL | const extern "C" fn f4_2(x: isize, ...) {}
| ^^^ | ^^^
|
help: add the `unsafe` keyword to this definition
|
LL | const unsafe extern "C" fn f4_2(x: isize, ...) {}
| ++++++
error: `...` must be the last argument of a C-variadic function error: `...` must be the last argument of a C-variadic function
--> $DIR/variadic-ffi-semantic-restrictions.rs:39:26 --> $DIR/variadic-ffi-semantic-restrictions.rs:42:26
| |
LL | const extern "C" fn f4_3(..., x: isize, ...) {} LL | const extern "C" fn f4_3(..., x: isize, ...) {}
| ^^^ | ^^^
error: functions cannot be both `const` and C-variadic error: functions cannot be both `const` and C-variadic
--> $DIR/variadic-ffi-semantic-restrictions.rs:39:1 --> $DIR/variadic-ffi-semantic-restrictions.rs:42:1
| |
LL | const extern "C" fn f4_3(..., x: isize, ...) {} LL | const extern "C" fn f4_3(..., x: isize, ...) {}
| ^^^^^ `const` because of this ^^^ C-variadic because of this | ^^^^^ `const` because of this ^^^ C-variadic because of this
error: defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention error: functions with a C variable argument list must be unsafe
--> $DIR/variadic-ffi-semantic-restrictions.rs:39:41 --> $DIR/variadic-ffi-semantic-restrictions.rs:42:41
| |
LL | const extern "C" fn f4_3(..., x: isize, ...) {} LL | const extern "C" fn f4_3(..., x: isize, ...) {}
| ^^^ | ^^^
|
help: add the `unsafe` keyword to this definition
|
LL | const unsafe extern "C" fn f4_3(..., x: isize, ...) {}
| ++++++
error: `...` must be the last argument of a C-variadic function error: `...` must be the last argument of a C-variadic function
--> $DIR/variadic-ffi-semantic-restrictions.rs:45:13 --> $DIR/variadic-ffi-semantic-restrictions.rs:48:13
| |
LL | fn e_f2(..., x: isize); LL | fn e_f2(..., x: isize);
| ^^^ | ^^^
error: defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention error: associated functions cannot have a C variable argument list
--> $DIR/variadic-ffi-semantic-restrictions.rs:52:23 --> $DIR/variadic-ffi-semantic-restrictions.rs:55:23
| |
LL | fn i_f1(x: isize, ...) {} LL | fn i_f1(x: isize, ...) {}
| ^^^ | ^^^
error: defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention error: associated functions cannot have a C variable argument list
--> $DIR/variadic-ffi-semantic-restrictions.rs:54:13 --> $DIR/variadic-ffi-semantic-restrictions.rs:57:13
| |
LL | fn i_f2(...) {} LL | fn i_f2(...) {}
| ^^^ | ^^^
error: `...` must be the last argument of a C-variadic function error: `...` must be the last argument of a C-variadic function
--> $DIR/variadic-ffi-semantic-restrictions.rs:56:13 --> $DIR/variadic-ffi-semantic-restrictions.rs:59:13
| |
LL | fn i_f3(..., x: isize, ...) {} LL | fn i_f3(..., x: isize, ...) {}
| ^^^ | ^^^
error: defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention error: associated functions cannot have a C variable argument list
--> $DIR/variadic-ffi-semantic-restrictions.rs:56:28 --> $DIR/variadic-ffi-semantic-restrictions.rs:59:28
| |
LL | fn i_f3(..., x: isize, ...) {} LL | fn i_f3(..., x: isize, ...) {}
| ^^^ | ^^^
error: `...` must be the last argument of a C-variadic function error: `...` must be the last argument of a C-variadic function
--> $DIR/variadic-ffi-semantic-restrictions.rs:59:13 --> $DIR/variadic-ffi-semantic-restrictions.rs:62:13
| |
LL | fn i_f4(..., x: isize, ...) {} LL | fn i_f4(..., x: isize, ...) {}
| ^^^ | ^^^
error: defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention error: associated functions cannot have a C variable argument list
--> $DIR/variadic-ffi-semantic-restrictions.rs:59:28 --> $DIR/variadic-ffi-semantic-restrictions.rs:62:28
| |
LL | fn i_f4(..., x: isize, ...) {} LL | fn i_f4(..., x: isize, ...) {}
| ^^^ | ^^^
error: functions cannot be both `const` and C-variadic error: functions cannot be both `const` and C-variadic
--> $DIR/variadic-ffi-semantic-restrictions.rs:62:5 --> $DIR/variadic-ffi-semantic-restrictions.rs:65:5
| |
LL | const fn i_f5(x: isize, ...) {} LL | const fn i_f5(x: isize, ...) {}
| ^^^^^ ^^^ C-variadic because of this | ^^^^^ ^^^ C-variadic because of this
| | | |
| `const` because of this | `const` because of this
error: defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention error: associated functions cannot have a C variable argument list
--> $DIR/variadic-ffi-semantic-restrictions.rs:62:29 --> $DIR/variadic-ffi-semantic-restrictions.rs:65:29
| |
LL | const fn i_f5(x: isize, ...) {} LL | const fn i_f5(x: isize, ...) {}
| ^^^ | ^^^
error: defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention error: associated functions cannot have a C variable argument list
--> $DIR/variadic-ffi-semantic-restrictions.rs:69:23 --> $DIR/variadic-ffi-semantic-restrictions.rs:72:23
| |
LL | fn t_f1(x: isize, ...) {} LL | fn t_f1(x: isize, ...) {}
| ^^^ | ^^^
error: defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention error: associated functions cannot have a C variable argument list
--> $DIR/variadic-ffi-semantic-restrictions.rs:71:23 --> $DIR/variadic-ffi-semantic-restrictions.rs:74:23
| |
LL | fn t_f2(x: isize, ...); LL | fn t_f2(x: isize, ...);
| ^^^ | ^^^
error: defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention error: associated functions cannot have a C variable argument list
--> $DIR/variadic-ffi-semantic-restrictions.rs:73:13 --> $DIR/variadic-ffi-semantic-restrictions.rs:76:13
| |
LL | fn t_f3(...) {} LL | fn t_f3(...) {}
| ^^^ | ^^^
error: defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention error: associated functions cannot have a C variable argument list
--> $DIR/variadic-ffi-semantic-restrictions.rs:75:13 --> $DIR/variadic-ffi-semantic-restrictions.rs:78:13
| |
LL | fn t_f4(...); LL | fn t_f4(...);
| ^^^ | ^^^
error: `...` must be the last argument of a C-variadic function error: `...` must be the last argument of a C-variadic function
--> $DIR/variadic-ffi-semantic-restrictions.rs:77:13 --> $DIR/variadic-ffi-semantic-restrictions.rs:80:13
| |
LL | fn t_f5(..., x: isize) {} LL | fn t_f5(..., x: isize) {}
| ^^^ | ^^^
error: `...` must be the last argument of a C-variadic function error: `...` must be the last argument of a C-variadic function
--> $DIR/variadic-ffi-semantic-restrictions.rs:79:13 --> $DIR/variadic-ffi-semantic-restrictions.rs:82:13
| |
LL | fn t_f6(..., x: isize); LL | fn t_f6(..., x: isize);
| ^^^ | ^^^
error[E0493]: destructor of `VaListImpl<'_>` cannot be evaluated at compile-time error[E0493]: destructor of `VaListImpl<'_>` cannot be evaluated at compile-time
--> $DIR/variadic-ffi-semantic-restrictions.rs:30:43 --> $DIR/variadic-ffi-semantic-restrictions.rs:33:43
| |
LL | const unsafe extern "C" fn f4_1(x: isize, ...) {} LL | const unsafe extern "C" fn f4_1(x: isize, ...) {}
| ^^^ - value is dropped here | ^^^ - value is dropped here
@ -183,7 +227,7 @@ LL | const unsafe extern "C" fn f4_1(x: isize, ...) {}
| the destructor for this type cannot be evaluated in constant functions | the destructor for this type cannot be evaluated in constant functions
error[E0493]: destructor of `VaListImpl<'_>` cannot be evaluated at compile-time error[E0493]: destructor of `VaListImpl<'_>` cannot be evaluated at compile-time
--> $DIR/variadic-ffi-semantic-restrictions.rs:34:36 --> $DIR/variadic-ffi-semantic-restrictions.rs:37:36
| |
LL | const extern "C" fn f4_2(x: isize, ...) {} LL | const extern "C" fn f4_2(x: isize, ...) {}
| ^^^ - value is dropped here | ^^^ - value is dropped here
@ -191,13 +235,13 @@ LL | const extern "C" fn f4_2(x: isize, ...) {}
| the destructor for this type cannot be evaluated in constant functions | the destructor for this type cannot be evaluated in constant functions
error[E0493]: destructor of `VaListImpl<'_>` cannot be evaluated at compile-time error[E0493]: destructor of `VaListImpl<'_>` cannot be evaluated at compile-time
--> $DIR/variadic-ffi-semantic-restrictions.rs:62:29 --> $DIR/variadic-ffi-semantic-restrictions.rs:65:29
| |
LL | const fn i_f5(x: isize, ...) {} LL | const fn i_f5(x: isize, ...) {}
| ^^^ - value is dropped here | ^^^ - value is dropped here
| | | |
| the destructor for this type cannot be evaluated in constant functions | the destructor for this type cannot be evaluated in constant functions
error: aborting due to 32 previous errors error: aborting due to 33 previous errors
For more information about this error, try `rustc --explain E0493`. For more information about this error, try `rustc --explain E0493`.

View file

@ -0,0 +1,35 @@
fn no_format_specifier_two_unused_args() {
println!("Hello", "World");
//~^ ERROR argument never used
//~| NOTE formatting specifier missing
//~| NOTE argument never used
//~| HELP format specifiers use curly braces, consider adding a format specifier
}
fn no_format_specifier_multiple_unused_args() {
println!("list: ", 1, 2, 3);
//~^ ERROR multiple unused formatting arguments
//~| NOTE multiple missing formatting specifiers
//~| NOTE argument never used
//~| NOTE argument never used
//~| NOTE argument never used
//~| HELP format specifiers use curly braces, consider adding 3 format specifiers
}
fn missing_format_specifiers_one_unused_arg() {
println!("list: {}, {}", 1, 2, 3);
//~^ ERROR argument never used
//~| NOTE formatting specifier missing
//~| NOTE argument never used
}
fn missing_format_specifiers_multiple_unused_args() {
println!("list: {}", 1, 2, 3);
//~^ ERROR multiple unused formatting arguments
//~| NOTE multiple missing formatting specifiers
//~| NOTE argument never used
//~| NOTE argument never used
//~| NOTE consider adding 2 format specifiers
}
fn main() { }

View file

@ -0,0 +1,49 @@
error: argument never used
--> $DIR/missing-format-specifiers-issue-68293.rs:2:23
|
LL | println!("Hello", "World");
| ------- ^^^^^^^ argument never used
| |
| formatting specifier missing
|
help: format specifiers use curly braces, consider adding a format specifier
|
LL | println!("Hello{}", "World");
| ++
error: multiple unused formatting arguments
--> $DIR/missing-format-specifiers-issue-68293.rs:10:24
|
LL | println!("list: ", 1, 2, 3);
| -------- ^ ^ ^ argument never used
| | | |
| | | argument never used
| | argument never used
| multiple missing formatting specifiers
|
help: format specifiers use curly braces, consider adding 3 format specifiers
|
LL | println!("list: {}{}{}", 1, 2, 3);
| ++++++
error: argument never used
--> $DIR/missing-format-specifiers-issue-68293.rs:20:36
|
LL | println!("list: {}, {}", 1, 2, 3);
| -------------- ^ argument never used
| |
| formatting specifier missing
error: multiple unused formatting arguments
--> $DIR/missing-format-specifiers-issue-68293.rs:27:29
|
LL | println!("list: {}", 1, 2, 3);
| ---------- ^ ^ argument never used
| | |
| | argument never used
| multiple missing formatting specifiers
|
= note: consider adding 2 format specifiers
error: aborting due to 4 previous errors

View file

@ -21,6 +21,20 @@ fn bar<T: ?Sized + ?Trait2 + ?Trait1 + ?Trait4>(_: &T) {}
// FIXME: `?Trait1` should be rejected, `Trait1` isn't marked `#[lang = "default_traitN"]`. // FIXME: `?Trait1` should be rejected, `Trait1` isn't marked `#[lang = "default_traitN"]`.
fn baz<T>() where T: Iterator<Item: ?Trait1> {} fn baz<T>() where T: Iterator<Item: ?Trait1> {}
//~^ ERROR this relaxed bound is not permitted here
struct S1<T>(T);
impl<T> S1<T> {
fn f() where T: ?Trait1 {}
//~^ ERROR this relaxed bound is not permitted here
}
trait Trait5<'a> {}
struct S2<T>(T) where for<'a> T: ?Trait5<'a>;
//~^ ERROR this relaxed bound is not permitted here
//~| ERROR bound modifier `?` can only be applied to default traits like `Sized`
struct S; struct S;
impl !Trait2 for S {} impl !Trait2 for S {}

View file

@ -1,3 +1,27 @@
error: this relaxed bound is not permitted here
--> $DIR/more_maybe_bounds.rs:23:37
|
LL | fn baz<T>() where T: Iterator<Item: ?Trait1> {}
| ^^^^^^^
|
= note: in this context, relaxed bounds are only allowed on type parameters defined by the closest item
error: this relaxed bound is not permitted here
--> $DIR/more_maybe_bounds.rs:29:21
|
LL | fn f() where T: ?Trait1 {}
| ^^^^^^^
|
= note: in this context, relaxed bounds are only allowed on type parameters defined by the closest item
error: this relaxed bound is not permitted here
--> $DIR/more_maybe_bounds.rs:35:34
|
LL | struct S2<T>(T) where for<'a> T: ?Trait5<'a>;
| ^^^^^^^^^^^
|
= note: in this context, relaxed bounds are only allowed on type parameters defined by the closest item
error: bound modifier `?` can only be applied to default traits like `Sized` error: bound modifier `?` can only be applied to default traits like `Sized`
--> $DIR/more_maybe_bounds.rs:17:20 --> $DIR/more_maybe_bounds.rs:17:20
| |
@ -16,5 +40,11 @@ error: bound modifier `?` can only be applied to default traits like `Sized`
LL | fn bar<T: ?Sized + ?Trait2 + ?Trait1 + ?Trait4>(_: &T) {} LL | fn bar<T: ?Sized + ?Trait2 + ?Trait1 + ?Trait4>(_: &T) {}
| ^^^^^^^ | ^^^^^^^
error: aborting due to 3 previous errors error: bound modifier `?` can only be applied to default traits like `Sized`
--> $DIR/more_maybe_bounds.rs:35:34
|
LL | struct S2<T>(T) where for<'a> T: ?Trait5<'a>;
| ^^^^^^^^^^^
error: aborting due to 7 previous errors

View file

@ -1,31 +0,0 @@
//@ check-pass
//@ compile-flags: -Zexperimental-default-bounds
#![feature(auto_traits, lang_items, no_core, rustc_attrs, trait_alias)]
#![no_std]
#![no_core]
#[lang = "pointee_sized"]
trait PointeeSized {}
#[lang = "meta_sized"]
trait MetaSized: PointeeSized {}
#[lang = "sized"]
trait Sized: MetaSized {}
#[lang = "default_trait1"]
auto trait DefaultTrait1 {}
#[lang = "default_trait2"]
auto trait DefaultTrait2 {}
trait Trait<Rhs: ?Sized = Self> {}
trait Trait1 : Trait {}
trait Trait2 {
type Type;
}
trait Trait3<T> = Trait2<Type = T>;
fn main() {}

View file

@ -13,32 +13,37 @@
#![no_core] #![no_core]
#[lang = "pointee_sized"] #[lang = "pointee_sized"]
trait PointeeSized {} trait PointeeSized: ?Leak {}
#[lang = "meta_sized"] #[lang = "meta_sized"]
trait MetaSized: PointeeSized {} trait MetaSized: PointeeSized + ?Leak {}
#[lang = "sized"] #[lang = "sized"]
trait Sized: MetaSized {} trait Sized: MetaSized + ?Leak {}
#[lang = "copy"] #[lang = "copy"]
pub trait Copy {} pub trait Copy: ?Leak {}
impl<'a, T: ?Sized> Copy for &'a T {} impl<'a, T: ?Sized> Copy for &'a T {}
#[lang = "legacy_receiver"] #[lang = "legacy_receiver"]
trait Receiver {} trait Receiver: ?Leak {}
impl<T: ?Sized + ?Leak> Receiver for &T {} impl<T: ?Sized + ?Leak> Receiver for &T {}
impl<T: ?Sized + ?Leak> Receiver for &mut T {}
#[lang = "unsize"] #[lang = "unsize"]
trait Unsize<T: ?Sized + ?Leak> {} trait Unsize<T: ?Sized + ?Leak>: ?Leak {}
#[lang = "coerce_unsized"] #[lang = "coerce_unsized"]
trait CoerceUnsized<T: ?Leak + ?Sized> {} trait CoerceUnsized<T: ?Leak + ?Sized>: ?Leak {}
impl<'a, 'b: 'a, T: ?Sized + ?Leak + Unsize<U>, U: ?Sized + ?Leak> CoerceUnsized<&'a U> for &'b T {} impl<'a, 'b: 'a, T: ?Sized + ?Leak + Unsize<U>, U: ?Sized + ?Leak> CoerceUnsized<&'a U> for &'b T {}
// Omit `T: ?Leak` and `U: ?Leak`.
impl<'a, 'b: 'a, T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<&'a mut U> for &'b mut T {}
#[lang = "dispatch_from_dyn"] #[lang = "dispatch_from_dyn"]
trait DispatchFromDyn<T: ?Leak> {} trait DispatchFromDyn<T: ?Leak>: ?Leak {}
impl<'a, T: ?Sized + ?Leak + Unsize<U>, U: ?Sized + ?Leak> DispatchFromDyn<&'a U> for &'a T {} impl<'a, T: ?Sized + ?Leak + Unsize<U>, U: ?Sized + ?Leak> DispatchFromDyn<&'a U> for &'a T {}
// Omit `T: ?Leak` and `U: ?Leak`.
impl<'a, T: ?Sized + Unsize<U>, U: ?Sized> DispatchFromDyn<&'a mut U> for &'a mut T {}
#[lang = "default_trait1"] #[lang = "default_trait1"]
auto trait Leak {} auto trait Leak {}
@ -47,25 +52,52 @@ struct NonLeakS;
impl !Leak for NonLeakS {} impl !Leak for NonLeakS {}
struct LeakS; struct LeakS;
trait Trait { fn bounds_check() {
fn leak_foo(&self) {} trait LeakTr {}
fn maybe_leak_foo(&self) where Self: ?Leak {}
trait MaybeLeakTr: ?Leak {}
impl MaybeLeakTr for NonLeakS {}
impl LeakTr for LeakS {}
impl MaybeLeakTr for LeakS {}
let _: &dyn LeakTr = &NonLeakS;
//~^ ERROR the trait bound `NonLeakS: bounds_check::LeakTr` is not satisfied
let _: &dyn LeakTr = &LeakS;
let _: &(dyn LeakTr + ?Leak) = &NonLeakS;
let _: &(dyn LeakTr + ?Leak) = &LeakS;
let _: &dyn MaybeLeakTr = &NonLeakS;
let _: &dyn MaybeLeakTr = &LeakS;
} }
impl Trait for NonLeakS {} fn dyn_compat_check() {
impl Trait for LeakS {} trait DynCompatCheck1: ?Leak {
fn foo(&self) {}
}
trait DynCompatCheck2: ?Leak {
fn mut_foo(&mut self) {}
}
impl DynCompatCheck1 for NonLeakS {}
impl DynCompatCheck2 for NonLeakS {}
let _: &(dyn DynCompatCheck1 + ?Leak) = &NonLeakS;
// There is no `?Leak` bound on corresponding `DispatchFromDyn` impl.
let _: &dyn DynCompatCheck2 = &NonLeakS;
//~^ ERROR the trait `DynCompatCheck2` is not dyn compatible
}
fn args_check() {
trait LeakTr {}
fn main() {
let _: &dyn Trait = &NonLeakS;
//~^ ERROR the trait bound `NonLeakS: Leak` is not satisfied
let _: &dyn Trait = &LeakS;
let _: &(dyn Trait + ?Leak) = &LeakS;
let x: &(dyn Trait + ?Leak) = &NonLeakS;
x.leak_foo();
//~^ ERROR the trait bound `dyn Trait: Leak` is not satisfied
x.maybe_leak_foo();
// Ensure that we validate the generic args of relaxed bounds in trait object types. // Ensure that we validate the generic args of relaxed bounds in trait object types.
let _: dyn Trait + ?Leak<(), Undefined = ()>; let _: dyn LeakTr + ?Leak<(), Undefined = ()>;
//~^ ERROR trait takes 0 generic arguments but 1 generic argument was supplied //~^ ERROR trait takes 0 generic arguments but 1 generic argument was supplied
//~| ERROR associated type `Undefined` not found for `Leak` //~| ERROR associated type `Undefined` not found for `Leak`
} }
fn main() {}

View file

@ -1,49 +1,57 @@
error[E0277]: the trait bound `NonLeakS: Leak` is not satisfied error[E0277]: the trait bound `NonLeakS: bounds_check::LeakTr` is not satisfied
--> $DIR/maybe-bounds-in-dyn-traits.rs:59:25 --> $DIR/maybe-bounds-in-dyn-traits.rs:65:26
| |
LL | let _: &dyn Trait = &NonLeakS; LL | let _: &dyn LeakTr = &NonLeakS;
| ^^^^^^^^^ unsatisfied trait bound | ^^^^^^^^^ unsatisfied trait bound
| |
help: the trait `Leak` is not implemented for `NonLeakS` help: the trait `bounds_check::LeakTr` is not implemented for `NonLeakS`
--> $DIR/maybe-bounds-in-dyn-traits.rs:46:1 --> $DIR/maybe-bounds-in-dyn-traits.rs:51:1
| |
LL | struct NonLeakS; LL | struct NonLeakS;
| ^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^
= note: required for the cast from `&NonLeakS` to `&dyn Trait + Leak` = help: the trait `bounds_check::LeakTr` is implemented for `LeakS`
= note: required for the cast from `&NonLeakS` to `&dyn bounds_check::LeakTr + Leak`
error[E0277]: the trait bound `dyn Trait: Leak` is not satisfied error[E0038]: the trait `DynCompatCheck2` is not dyn compatible
--> $DIR/maybe-bounds-in-dyn-traits.rs:64:7 --> $DIR/maybe-bounds-in-dyn-traits.rs:90:17
| |
LL | x.leak_foo(); LL | fn mut_foo(&mut self) {}
| ^^^^^^^^ the trait `Leak` is not implemented for `dyn Trait` | --------- help: consider changing method `mut_foo`'s `self` parameter to be `&self`: `&Self`
...
LL | let _: &dyn DynCompatCheck2 = &NonLeakS;
| ^^^^^^^^^^^^^^^ `DynCompatCheck2` is not dyn compatible
| |
note: required by a bound in `Trait::leak_foo` note: for a trait to be dyn compatible it needs to allow building a vtable
--> $DIR/maybe-bounds-in-dyn-traits.rs:51:5 for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
--> $DIR/maybe-bounds-in-dyn-traits.rs:82:20
| |
LL | fn leak_foo(&self) {} LL | trait DynCompatCheck2: ?Leak {
| ^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Trait::leak_foo` | --------------- this trait is not dyn compatible...
LL | fn mut_foo(&mut self) {}
| ^^^^^^^^^ ...because method `mut_foo`'s `self` parameter cannot be dispatched on
= help: only type `NonLeakS` implements `DynCompatCheck2`; consider using it directly instead.
error[E0107]: trait takes 0 generic arguments but 1 generic argument was supplied error[E0107]: trait takes 0 generic arguments but 1 generic argument was supplied
--> $DIR/maybe-bounds-in-dyn-traits.rs:68:25 --> $DIR/maybe-bounds-in-dyn-traits.rs:98:26
| |
LL | let _: dyn Trait + ?Leak<(), Undefined = ()>; LL | let _: dyn LeakTr + ?Leak<(), Undefined = ()>;
| ^^^^-------------------- help: remove the unnecessary generics | ^^^^-------------------- help: remove the unnecessary generics
| | | |
| expected 0 generic arguments | expected 0 generic arguments
| |
note: trait defined here, with 0 generic parameters note: trait defined here, with 0 generic parameters
--> $DIR/maybe-bounds-in-dyn-traits.rs:44:12 --> $DIR/maybe-bounds-in-dyn-traits.rs:49:12
| |
LL | auto trait Leak {} LL | auto trait Leak {}
| ^^^^ | ^^^^
error[E0220]: associated type `Undefined` not found for `Leak` error[E0220]: associated type `Undefined` not found for `Leak`
--> $DIR/maybe-bounds-in-dyn-traits.rs:68:34 --> $DIR/maybe-bounds-in-dyn-traits.rs:98:35
| |
LL | let _: dyn Trait + ?Leak<(), Undefined = ()>; LL | let _: dyn LeakTr + ?Leak<(), Undefined = ()>;
| ^^^^^^^^^ associated type `Undefined` not found | ^^^^^^^^^ associated type `Undefined` not found
error: aborting due to 4 previous errors error: aborting due to 4 previous errors
Some errors have detailed explanations: E0107, E0220, E0277. Some errors have detailed explanations: E0038, E0107, E0220, E0277.
For more information about an error, try `rustc --explain E0107`. For more information about an error, try `rustc --explain E0038`.

View file

@ -14,18 +14,22 @@
#![no_std] #![no_std]
#![no_core] #![no_core]
#[lang = "copy"]
pub trait Copy: ?Leak {}
#[lang = "pointee_sized"] #[lang = "pointee_sized"]
trait PointeeSized {} trait PointeeSized: ?Leak {}
#[lang = "meta_sized"] #[lang = "meta_sized"]
trait MetaSized: PointeeSized {} trait MetaSized: PointeeSized + ?Leak {}
#[lang = "sized"] #[lang = "sized"]
trait Sized: MetaSized {} trait Sized: MetaSized + ?Leak {}
#[lang = "legacy_receiver"] #[lang = "legacy_receiver"]
trait LegacyReceiver {} trait LegacyReceiver: ?Leak {}
impl<T: ?Sized + ?Leak> LegacyReceiver for &T {} impl<T: ?Sized + ?Leak> LegacyReceiver for &T {}
// Omit `T: ?Leak`.
impl<T: ?Sized> LegacyReceiver for &mut T {} impl<T: ?Sized> LegacyReceiver for &mut T {}
#[lang = "default_trait1"] #[lang = "default_trait1"]
@ -38,83 +42,40 @@ struct LeakS;
mod supertraits { mod supertraits {
use crate::*; use crate::*;
trait MaybeLeakT1: ?Leak {} trait MaybeLeak: ?Leak {}
trait MaybeLeakT2 where Self: ?Leak {} impl MaybeLeak for NonLeakS {}
impl MaybeLeakT1 for NonLeakS {} trait LeakT {}
impl MaybeLeakT2 for NonLeakS {} impl LeakT for NonLeakS {}
//~^ ERROR the trait bound `NonLeakS: Leak` is not satisfied
} }
mod maybe_self_assoc_type { mod assoc_type_maybe_bounds {
use crate::*; use crate::*;
trait TestBase1<T: ?Sized> {} trait Test1 {
trait TestBase2<T: ?Leak + ?Sized> {}
trait Test1<T> {
type MaybeLeakSelf: TestBase1<Self> where Self: ?Leak;
//~^ ERROR the trait bound `Self: Leak` is not satisfied
type LeakSelf: TestBase1<Self>;
}
trait Test2<T> {
type MaybeLeakSelf: TestBase2<Self> where Self: ?Leak;
type LeakSelf: TestBase2<Self>;
}
trait Test3 {
type Leak1 = LeakS; type Leak1 = LeakS;
type Leak2 = NonLeakS; type Leak2 = NonLeakS;
//~^ ERROR the trait bound `NonLeakS: Leak` is not satisfied //~^ ERROR the trait bound `NonLeakS: Leak` is not satisfied
} }
trait Test4 { trait Test2 {
type MaybeLeak1: ?Leak = LeakS; type MaybeLeak1: ?Leak = LeakS;
type MaybeLeak2: ?Leak = NonLeakS; type MaybeLeak2: ?Leak = NonLeakS;
} }
trait Test5: ?Leak {
// ok, because assoc types have implicit where Self: Leak
type MaybeLeakSelf1: TestBase1<Self>;
type MaybeLeakSelf2: TestBase2<Self>;
}
}
mod maybe_self_assoc_const {
use crate::*;
const fn size_of<T: ?Sized>() -> usize {
0
}
trait Trait {
const CLeak: usize = size_of::<Self>();
const CNonLeak: usize = size_of::<Self>() where Self: ?Leak;
//~^ ERROR the trait bound `Self: Leak` is not satisfied
}
} }
mod methods { mod methods {
use crate::*; use crate::*;
trait Trait { trait ReceiveCheck1: ?Leak {
fn leak_foo(&self) {} fn foo(&self) {}
fn maybe_leak_foo(&self) where Self: ?Leak {}
fn mut_leak_foo(&mut self) {}
// there is no relax bound on corresponding Receiver impl
fn mut_maybe_leak_foo(&mut self) where Self: ?Leak {}
//~^ ERROR `&mut Self` cannot be used as the type of `self` without the `arbitrary_self_types`
} }
impl Trait for NonLeakS {} trait ReceiveCheck2: ?Leak {
impl Trait for LeakS {} // There is no `?Leak` bound on corresponding `LegacyReceiver` impl.
fn mut_foo(&mut self) {}
fn foo() { //~^ ERROR `&mut Self` cannot be used as the type of `self` without the `arbitrary_self_types`
LeakS.leak_foo();
LeakS.maybe_leak_foo();
NonLeakS.leak_foo();
//~^ ERROR the trait bound `NonLeakS: Leak` is not satisfied
NonLeakS.maybe_leak_foo();
} }
} }

View file

@ -1,81 +1,49 @@
error[E0277]: the trait bound `NonLeakS: Leak` is not satisfied error[E0277]: the trait bound `NonLeakS: Leak` is not satisfied
--> $DIR/maybe-bounds-in-traits.rs:67:22 --> $DIR/maybe-bounds-in-traits.rs:49:20
|
LL | impl LeakT for NonLeakS {}
| ^^^^^^^^ unsatisfied trait bound
|
help: the trait `Leak` is not implemented for `NonLeakS`
--> $DIR/maybe-bounds-in-traits.rs:38:1
|
LL | struct NonLeakS;
| ^^^^^^^^^^^^^^^
note: required by a bound in `LeakT`
--> $DIR/maybe-bounds-in-traits.rs:48:5
|
LL | trait LeakT {}
| ^^^^^^^^^^^^^^ required by this bound in `LeakT`
error[E0277]: the trait bound `NonLeakS: Leak` is not satisfied
--> $DIR/maybe-bounds-in-traits.rs:58:22
| |
LL | type Leak2 = NonLeakS; LL | type Leak2 = NonLeakS;
| ^^^^^^^^ unsatisfied trait bound | ^^^^^^^^ unsatisfied trait bound
| |
help: the trait `Leak` is not implemented for `NonLeakS` help: the trait `Leak` is not implemented for `NonLeakS`
--> $DIR/maybe-bounds-in-traits.rs:34:1 --> $DIR/maybe-bounds-in-traits.rs:38:1
| |
LL | struct NonLeakS; LL | struct NonLeakS;
| ^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^
note: required by a bound in `Test3::Leak2` note: required by a bound in `Test1::Leak2`
--> $DIR/maybe-bounds-in-traits.rs:67:9 --> $DIR/maybe-bounds-in-traits.rs:58:9
| |
LL | type Leak2 = NonLeakS; LL | type Leak2 = NonLeakS;
| ^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Test3::Leak2` | ^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Test1::Leak2`
error[E0277]: the trait bound `Self: Leak` is not satisfied
--> $DIR/maybe-bounds-in-traits.rs:55:29
|
LL | type MaybeLeakSelf: TestBase1<Self> where Self: ?Leak;
| ^^^^^^^^^^^^^^^ the trait `Leak` is not implemented for `Self`
|
note: required by a bound in `TestBase1`
--> $DIR/maybe-bounds-in-traits.rs:51:21
|
LL | trait TestBase1<T: ?Sized> {}
| ^ required by this bound in `TestBase1`
help: consider further restricting `Self`
|
LL | trait Test1<T>: Leak {
| ++++++
error[E0658]: `&mut Self` cannot be used as the type of `self` without the `arbitrary_self_types` feature error[E0658]: `&mut Self` cannot be used as the type of `self` without the `arbitrary_self_types` feature
--> $DIR/maybe-bounds-in-traits.rs:105:31 --> $DIR/maybe-bounds-in-traits.rs:77:20
| |
LL | fn mut_maybe_leak_foo(&mut self) where Self: ?Leak {} LL | fn mut_foo(&mut self) {}
| ^^^^^^^^^ | ^^^^^^^^^
| |
= note: see issue #44874 <https://github.com/rust-lang/rust/issues/44874> for more information = note: see issue #44874 <https://github.com/rust-lang/rust/issues/44874> for more information
= help: add `#![feature(arbitrary_self_types)]` to the crate attributes to enable = help: add `#![feature(arbitrary_self_types)]` to the crate attributes to enable
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
= help: consider changing to `self`, `&self`, `&mut self`, or a type implementing `Receiver` such as `self: Box<Self>`, `self: Rc<Self>`, or `self: Arc<Self>` = help: consider changing to `self`, `&self`, `&mut self`, or a type implementing `Receiver` such as `self: Box<Self>`, `self: Rc<Self>`, or `self: Arc<Self>`
error[E0277]: the trait bound `Self: Leak` is not satisfied error: aborting due to 3 previous errors
--> $DIR/maybe-bounds-in-traits.rs:92:43
|
LL | const CNonLeak: usize = size_of::<Self>() where Self: ?Leak;
| ^^^^ the trait `Leak` is not implemented for `Self`
|
note: required by a bound in `size_of`
--> $DIR/maybe-bounds-in-traits.rs:86:22
|
LL | const fn size_of<T: ?Sized>() -> usize {
| ^ required by this bound in `size_of`
help: consider further restricting `Self`
|
LL | trait Trait: Leak {
| ++++++
error[E0277]: the trait bound `NonLeakS: Leak` is not satisfied
--> $DIR/maybe-bounds-in-traits.rs:115:18
|
LL | NonLeakS.leak_foo();
| ^^^^^^^^ unsatisfied trait bound
|
help: the trait `Leak` is not implemented for `NonLeakS`
--> $DIR/maybe-bounds-in-traits.rs:34:1
|
LL | struct NonLeakS;
| ^^^^^^^^^^^^^^^
note: required by a bound in `methods::Trait::leak_foo`
--> $DIR/maybe-bounds-in-traits.rs:101:9
|
LL | fn leak_foo(&self) {}
| ^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Trait::leak_foo`
error: aborting due to 5 previous errors
Some errors have detailed explanations: E0277, E0658. Some errors have detailed explanations: E0277, E0658.
For more information about an error, try `rustc --explain E0277`. For more information about an error, try `rustc --explain E0277`.