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:
commit
f4665ab836
81 changed files with 1607 additions and 858 deletions
|
|
@ -2284,6 +2284,54 @@ pub struct FnSig {
|
|||
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.
|
||||
///
|
||||
/// ### Examples
|
||||
|
|
@ -3526,6 +3574,13 @@ impl Extern {
|
|||
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.
|
||||
|
|
@ -3534,12 +3589,12 @@ impl Extern {
|
|||
/// included in this struct (e.g., `async unsafe fn` or `const extern "C" fn`).
|
||||
#[derive(Clone, Copy, Encodable, Decodable, Debug, Walkable)]
|
||||
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
|
||||
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.
|
||||
pub ext: Extern,
|
||||
}
|
||||
|
|
@ -3553,38 +3608,6 @@ impl FnHeader {
|
|||
|| matches!(constness, Const::Yes(_))
|
||||
|| !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 {
|
||||
|
|
|
|||
|
|
@ -2101,17 +2101,14 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
{
|
||||
return;
|
||||
}
|
||||
if self.tcx.features().more_maybe_bounds() {
|
||||
return;
|
||||
}
|
||||
}
|
||||
RelaxedBoundPolicy::Forbidden(reason) => {
|
||||
if self.tcx.features().more_maybe_bounds() {
|
||||
return;
|
||||
}
|
||||
|
||||
match reason {
|
||||
RelaxedBoundForbiddenReason::TraitObjectTy => {
|
||||
if self.tcx.features().more_maybe_bounds() {
|
||||
return;
|
||||
}
|
||||
|
||||
self.dcx().span_err(
|
||||
span,
|
||||
"relaxed bounds are not permitted in trait object types",
|
||||
|
|
@ -2119,6 +2116,10 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
return;
|
||||
}
|
||||
RelaxedBoundForbiddenReason::SuperTrait => {
|
||||
if self.tcx.features().more_maybe_bounds() {
|
||||
return;
|
||||
}
|
||||
|
||||
let mut diag = self.dcx().struct_span_err(
|
||||
span,
|
||||
"relaxed bounds are not permitted in supertrait bounds",
|
||||
|
|
|
|||
|
|
@ -57,8 +57,6 @@ ast_passes_auto_super_lifetime = auto traits cannot have super traits or lifetim
|
|||
.label = {ast_passes_auto_super_lifetime}
|
||||
.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
|
||||
.cannot_have = cannot have a 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_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
|
||||
.const = `const` because of this
|
||||
.variadic = C-variadic because of this
|
||||
|
|
@ -84,6 +95,10 @@ ast_passes_const_without_body =
|
|||
ast_passes_constraint_on_negative_bound =
|
||||
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
|
||||
.label = not supported
|
||||
.suggestion = if `{$ident}` is an associated type you're trying to set, use the associated type binding syntax
|
||||
|
|
|
|||
|
|
@ -492,7 +492,7 @@ impl<'a> AstValidator<'a> {
|
|||
}
|
||||
|
||||
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 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 {
|
||||
FnCtxt::Foreign => return,
|
||||
FnCtxt::Free => match sig.header.ext {
|
||||
Extern::Explicit(StrLit { symbol_unescaped: sym::C, .. }, _)
|
||||
| Extern::Explicit(StrLit { symbol_unescaped: sym::C_dash_unwind, .. }, _)
|
||||
| Extern::Implicit(_)
|
||||
if matches!(sig.header.safety, Safety::Unsafe(_)) =>
|
||||
{
|
||||
return;
|
||||
Extern::Implicit(_) => {
|
||||
if !matches!(sig.header.safety, Safety::Unsafe(_)) {
|
||||
self.dcx().emit_err(errors::CVariadicMustBeUnsafe {
|
||||
span: variadic_param.span,
|
||||
unsafe_span: sig.safety_span(),
|
||||
});
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
},
|
||||
FnCtxt::Assoc(_) => {}
|
||||
};
|
||||
Extern::Explicit(StrLit { symbol_unescaped, .. }, _) => {
|
||||
if !matches!(symbol_unescaped, sym::C | sym::C_dash_unwind) {
|
||||
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) {
|
||||
|
|
|
|||
|
|
@ -319,12 +319,46 @@ pub(crate) struct ExternItemAscii {
|
|||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(ast_passes_bad_c_variadic)]
|
||||
pub(crate) struct BadCVariadic {
|
||||
#[diag(ast_passes_c_variadic_associated_function)]
|
||||
pub(crate) struct CVariadicAssociatedFunction {
|
||||
#[primary_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)]
|
||||
#[diag(ast_passes_item_underscore)]
|
||||
pub(crate) struct ItemUnderscore<'a> {
|
||||
|
|
@ -659,6 +693,18 @@ pub(crate) struct ConstAndCVariadic {
|
|||
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)]
|
||||
#[diag(ast_passes_pattern_in_foreign, code = E0130)]
|
||||
// FIXME: deduplicate with rustc_lint (`BuiltinLintDiag::PatternsInFnsWithoutBody`)
|
||||
|
|
|
|||
|
|
@ -565,6 +565,7 @@ fn make_format_args(
|
|||
&used,
|
||||
&args,
|
||||
&pieces,
|
||||
&invalid_refs,
|
||||
detect_foreign_fmt,
|
||||
str_style,
|
||||
fmt_str,
|
||||
|
|
@ -645,6 +646,7 @@ fn report_missing_placeholders(
|
|||
used: &[bool],
|
||||
args: &FormatArguments,
|
||||
pieces: &[parse::Piece<'_>],
|
||||
invalid_refs: &[(usize, Option<Span>, PositionUsedAs, FormatArgPositionKind)],
|
||||
detect_foreign_fmt: bool,
|
||||
str_style: Option<usize>,
|
||||
fmt_str: &str,
|
||||
|
|
@ -762,6 +764,31 @@ fn report_missing_placeholders(
|
|||
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();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
//! The implementation of built-in macros which relate to the file system.
|
||||
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::rc::Rc;
|
||||
use std::sync::Arc;
|
||||
|
|
@ -11,9 +13,11 @@ use rustc_expand::base::{
|
|||
};
|
||||
use rustc_expand::module::DirOwnership;
|
||||
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_session::lint::builtin::INCOMPLETE_INCLUDE;
|
||||
use rustc_session::parse::ParseSess;
|
||||
use rustc_span::source_map::SourceMap;
|
||||
use rustc_span::{ByteSymbol, Pos, Span, Symbol};
|
||||
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,
|
||||
};
|
||||
|
||||
// These macros all relate to the file system; they either return
|
||||
// the column/row/filename of the expression, or they include
|
||||
// a given file into the current one.
|
||||
|
||||
/// line!(): expands to the current line number
|
||||
/// Expand `line!()` to the current line number.
|
||||
pub(crate) fn expand_line(
|
||||
cx: &mut ExtCtxt<'_>,
|
||||
sp: Span,
|
||||
|
|
@ -42,7 +42,7 @@ pub(crate) fn expand_line(
|
|||
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(
|
||||
cx: &mut ExtCtxt<'_>,
|
||||
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)))
|
||||
}
|
||||
|
||||
/// file!(): expands to the current filename */
|
||||
/// The source_file (`loc.file`) contains a bunch more information we could spit
|
||||
/// out if we wanted.
|
||||
/// Expand `file!()` to the current filename.
|
||||
pub(crate) fn expand_file(
|
||||
cx: &mut ExtCtxt<'_>,
|
||||
sp: Span,
|
||||
|
|
@ -81,6 +79,7 @@ pub(crate) fn expand_file(
|
|||
)))
|
||||
}
|
||||
|
||||
/// Expand `stringify!($input)`.
|
||||
pub(crate) fn expand_stringify(
|
||||
cx: &mut ExtCtxt<'_>,
|
||||
sp: Span,
|
||||
|
|
@ -91,6 +90,7 @@ pub(crate) fn expand_stringify(
|
|||
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(
|
||||
cx: &mut ExtCtxt<'_>,
|
||||
sp: Span,
|
||||
|
|
@ -104,9 +104,9 @@ pub(crate) fn expand_mod(
|
|||
ExpandResult::Ready(MacEager::expr(cx.expr_str(sp, Symbol::intern(&string))))
|
||||
}
|
||||
|
||||
/// include! : parse the given file as an expr
|
||||
/// This is generally a bad idea because it's going to behave
|
||||
/// unhygienically.
|
||||
/// Expand `include!($input)`.
|
||||
///
|
||||
/// This works in item and expression position. Notably, it doesn't work in pattern position.
|
||||
pub(crate) fn expand_include<'cx>(
|
||||
cx: &'cx mut ExtCtxt<'_>,
|
||||
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 {
|
||||
return ExpandResult::Retry(());
|
||||
};
|
||||
let file = match mac {
|
||||
Ok(file) => file,
|
||||
let path = match mac {
|
||||
Ok(path) => path,
|
||||
Err(guar) => return ExpandResult::Ready(DummyResult::any(sp, guar)),
|
||||
};
|
||||
// The file will be added to the code map by the parser
|
||||
let file = match resolve_path(&cx.sess, file.as_str(), sp) {
|
||||
Ok(f) => f,
|
||||
let path = match resolve_path(&cx.sess, path.as_str(), sp) {
|
||||
Ok(path) => path,
|
||||
Err(err) => {
|
||||
let guar = err.emit();
|
||||
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;`,
|
||||
// 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.
|
||||
// `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.dir_ownership = DirOwnership::Owned { relative: None };
|
||||
|
||||
struct ExpandInclude<'a> {
|
||||
p: Parser<'a>,
|
||||
psess: &'a ParseSess,
|
||||
path: PathBuf,
|
||||
node_id: ast::NodeId,
|
||||
span: Span,
|
||||
}
|
||||
impl<'a> MacResult for ExpandInclude<'a> {
|
||||
fn make_expr(mut self: Box<ExpandInclude<'a>>) -> Option<Box<ast::Expr>> {
|
||||
let expr = parse_expr(&mut self.p).ok()?;
|
||||
if self.p.token != token::Eof {
|
||||
self.p.psess.buffer_lint(
|
||||
fn make_expr(self: Box<ExpandInclude<'a>>) -> Option<Box<ast::Expr>> {
|
||||
let mut p = unwrap_or_emit_fatal(new_parser_from_file(
|
||||
self.psess,
|
||||
&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,
|
||||
self.p.token.span,
|
||||
p.token.span,
|
||||
self.node_id,
|
||||
BuiltinLintDiag::IncompleteInclude,
|
||||
);
|
||||
|
|
@ -156,24 +165,27 @@ pub(crate) fn expand_include<'cx>(
|
|||
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();
|
||||
loop {
|
||||
match self.p.parse_item(ForceCollect::No) {
|
||||
match p.parse_item(ForceCollect::No) {
|
||||
Err(err) => {
|
||||
err.emit();
|
||||
break;
|
||||
}
|
||||
Ok(Some(item)) => ret.push(item),
|
||||
Ok(None) => {
|
||||
if self.p.token != token::Eof {
|
||||
self.p
|
||||
.dcx()
|
||||
.create_err(errors::ExpectedItem {
|
||||
span: self.p.token.span,
|
||||
token: &pprust::token_to_string(&self.p.token),
|
||||
})
|
||||
.emit();
|
||||
if p.token != token::Eof {
|
||||
p.dcx().emit_err(errors::ExpectedItem {
|
||||
span: p.token.span,
|
||||
token: &pprust::token_to_string(&p.token),
|
||||
});
|
||||
}
|
||||
|
||||
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(
|
||||
cx: &mut ExtCtxt<'_>,
|
||||
sp: Span,
|
||||
|
|
@ -206,6 +225,7 @@ pub(crate) fn expand_include_str(
|
|||
Ok((bytes, bsp)) => match std::str::from_utf8(&bytes) {
|
||||
Ok(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))
|
||||
}
|
||||
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(
|
||||
cx: &mut ExtCtxt<'_>,
|
||||
sp: Span,
|
||||
|
|
@ -237,6 +260,7 @@ pub(crate) fn expand_include_bytes(
|
|||
// Don't care about getting the span for the raw bytes,
|
||||
// because the console can't really show them anyway.
|
||||
let expr = cx.expr(sp, ast::ExprKind::IncludedBytes(ByteSymbol::intern(&bytes)));
|
||||
// MacEager converts the expr into a pat if need be.
|
||||
MacEager::expr(expr)
|
||||
}
|
||||
Err(dummy) => dummy,
|
||||
|
|
|
|||
|
|
@ -51,6 +51,7 @@ use rustc_lint::unerased_lint_store;
|
|||
use rustc_metadata::creader::MetadataLoader;
|
||||
use rustc_metadata::locator;
|
||||
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_session::config::{
|
||||
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> {
|
||||
let mut parser = unwrap_or_emit_fatal(match &sess.io.input {
|
||||
Input::File(file) => new_parser_from_file(&sess.psess, file, None),
|
||||
Input::Str { name, input } => {
|
||||
new_parser_from_source_str(&sess.psess, name.clone(), input.clone())
|
||||
Input::File(file) => {
|
||||
new_parser_from_file(&sess.psess, file, StripTokens::ShebangAndFrontmatter, None)
|
||||
}
|
||||
Input::Str { name, input } => new_parser_from_source_str(
|
||||
&sess.psess,
|
||||
name.clone(),
|
||||
input.clone(),
|
||||
StripTokens::ShebangAndFrontmatter,
|
||||
),
|
||||
});
|
||||
parser.parse_inner_attributes()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ use std::path::{self, Path, PathBuf};
|
|||
use rustc_ast::{AttrVec, Attribute, Inline, Item, ModSpans};
|
||||
use rustc_attr_parsing::validate_attr;
|
||||
use rustc_errors::{Diag, ErrorGuaranteed};
|
||||
use rustc_parse::lexer::StripTokens;
|
||||
use rustc_parse::{exp, new_parser_from_file, unwrap_or_emit_fatal};
|
||||
use rustc_session::Session;
|
||||
use rustc_session::parse::ParseSess;
|
||||
|
|
@ -67,8 +68,12 @@ pub(crate) fn parse_external_mod(
|
|||
}
|
||||
|
||||
// Actually parse the external file as a module.
|
||||
let mut parser =
|
||||
unwrap_or_emit_fatal(new_parser_from_file(&sess.psess, &mp.file_path, Some(span)));
|
||||
let mut parser = unwrap_or_emit_fatal(new_parser_from_file(
|
||||
&sess.psess,
|
||||
&mp.file_path,
|
||||
StripTokens::ShebangAndFrontmatter,
|
||||
Some(span),
|
||||
));
|
||||
let (inner_attrs, items, inner_span) =
|
||||
parser.parse_mod(exp!(Eof)).map_err(|err| ModError::ParserError(err))?;
|
||||
attrs.extend(inner_attrs);
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ use rustc_ast::util::literal::escape_byte_str_symbol;
|
|||
use rustc_ast_pretty::pprust;
|
||||
use rustc_data_structures::fx::FxHashMap;
|
||||
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::{exp, new_parser_from_source_str, source_str_to_stream, unwrap_or_emit_fatal};
|
||||
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>, ()> {
|
||||
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 minus_present = parser.eat(exp!(Minus));
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
// Below we'll consider the bounds on the type parameters (including `Self`)
|
||||
|
|
|
|||
|
|
@ -1,12 +1,13 @@
|
|||
use std::assert_matches::assert_matches;
|
||||
use std::ops::ControlFlow;
|
||||
|
||||
use rustc_data_structures::fx::{FxIndexMap, FxIndexSet};
|
||||
use rustc_errors::codes::*;
|
||||
use rustc_errors::struct_span_code_err;
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::PolyTraitRef;
|
||||
use rustc_hir::def::{DefKind, Res};
|
||||
use rustc_hir::def_id::{CRATE_DEF_ID, DefId, LocalDefId};
|
||||
use rustc_hir::{AmbigArg, PolyTraitRef};
|
||||
use rustc_middle::bug;
|
||||
use rustc_middle::ty::{
|
||||
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
|
||||
/// 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.
|
||||
/// Adds `experimental_default_bounds` bounds to the supertrait bounds.
|
||||
pub(crate) fn add_default_super_traits(
|
||||
&self,
|
||||
trait_def_id: LocalDefId,
|
||||
|
|
@ -354,21 +240,21 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
|||
hir_generics: &'tcx hir::Generics<'tcx>,
|
||||
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;
|
||||
}
|
||||
|
||||
assert!(matches!(self.tcx().def_kind(trait_def_id), DefKind::Trait | DefKind::TraitAlias));
|
||||
if self.requires_default_supertraits(hir_bounds, hir_generics) {
|
||||
let self_ty_where_predicates = (trait_def_id, hir_generics.predicates);
|
||||
self.add_default_traits(
|
||||
bounds,
|
||||
self.tcx().types.self_param,
|
||||
hir_bounds,
|
||||
Some(self_ty_where_predicates),
|
||||
span,
|
||||
);
|
||||
}
|
||||
self.add_default_traits(
|
||||
bounds,
|
||||
self.tcx().types.self_param,
|
||||
hir_bounds,
|
||||
Some((trait_def_id, hir_generics.predicates)),
|
||||
span,
|
||||
);
|
||||
}
|
||||
|
||||
pub(crate) fn add_default_traits(
|
||||
|
|
|
|||
|
|
@ -13,7 +13,8 @@ use rustc_lint::LintStore;
|
|||
use rustc_middle::ty;
|
||||
use rustc_middle::ty::CurrentGcx;
|
||||
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_query_impl::QueryCtxt;
|
||||
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(meta_item) if parser.token == token::Eof => {
|
||||
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\"))`")
|
||||
};
|
||||
|
||||
let mut parser = match new_parser_from_simple_source_str(&psess, filename, s.to_string()) {
|
||||
Ok(parser) => parser,
|
||||
Err(errs) => {
|
||||
errs.into_iter().for_each(|err| err.cancel());
|
||||
expected_error();
|
||||
}
|
||||
};
|
||||
let mut parser =
|
||||
match new_parser_from_source_str(&psess, filename, s.to_string(), StripTokens::Nothing)
|
||||
{
|
||||
Ok(parser) => parser,
|
||||
Err(errs) => {
|
||||
errs.into_iter().for_each(|err| err.cancel());
|
||||
expected_error();
|
||||
}
|
||||
};
|
||||
|
||||
let meta_item = match parser.parse_meta_item(AllowLeadingUnsafe::No) {
|
||||
Ok(meta_item) if parser.token == token::Eof => meta_item,
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@ use rustc_middle::arena::Arena;
|
|||
use rustc_middle::dep_graph::DepsType;
|
||||
use rustc_middle::ty::{self, CurrentGcx, GlobalCtxt, RegisteredTools, TyCtxt};
|
||||
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_passes::{abi_test, input_stats, layout_test};
|
||||
use rustc_resolve::{Resolver, ResolverOutputs};
|
||||
|
|
@ -52,10 +53,18 @@ pub fn parse<'a>(sess: &'a Session) -> ast::Crate {
|
|||
let mut krate = sess
|
||||
.time("parse_crate", || {
|
||||
let mut parser = unwrap_or_emit_fatal(match &sess.io.input {
|
||||
Input::File(file) => new_parser_from_file(&sess.psess, file, None),
|
||||
Input::Str { input, name } => {
|
||||
new_parser_from_source_str(&sess.psess, name.clone(), input.clone())
|
||||
}
|
||||
Input::File(file) => new_parser_from_file(
|
||||
&sess.psess,
|
||||
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()
|
||||
})
|
||||
|
|
|
|||
|
|
@ -47,7 +47,8 @@ impl<'tcx> LateLintPass<'tcx> for MultipleSupertraitUpcastable {
|
|||
.explicit_super_predicates_of(def_id)
|
||||
.iter_identity_copied()
|
||||
.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 {
|
||||
cx.emit_span_lint(
|
||||
MULTIPLE_SUPERTRAIT_UPCASTABLE,
|
||||
|
|
|
|||
|
|
@ -45,7 +45,7 @@ pub(crate) struct UnmatchedDelim {
|
|||
}
|
||||
|
||||
/// Which tokens should be stripped before lexing the tokens.
|
||||
pub(crate) enum StripTokens {
|
||||
pub enum StripTokens {
|
||||
/// Strip both shebang and frontmatter.
|
||||
ShebangAndFrontmatter,
|
||||
/// Strip the shebang but not frontmatter.
|
||||
|
|
|
|||
|
|
@ -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
|
||||
/// `unwrap_or_emit_fatal`, `emit`, `cancel`, etc., otherwise a panic will occur when they are
|
||||
/// dropped.
|
||||
/// Creates a new parser from a 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_source_str(
|
||||
psess: &ParseSess,
|
||||
name: FileName,
|
||||
source: String,
|
||||
strip_tokens: StripTokens,
|
||||
) -> Result<Parser<'_>, Vec<Diag<'_>>> {
|
||||
let source_file = psess.source_map().new_source_file(name, source);
|
||||
new_parser_from_source_file(psess, source_file, StripTokens::ShebangAndFrontmatter)
|
||||
}
|
||||
|
||||
/// 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)
|
||||
new_parser_from_source_file(psess, source_file, strip_tokens)
|
||||
}
|
||||
|
||||
/// 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>(
|
||||
psess: &'a ParseSess,
|
||||
path: &Path,
|
||||
strip_tokens: StripTokens,
|
||||
sp: Option<Span>,
|
||||
) -> Result<Parser<'a>, Vec<Diag<'a>>> {
|
||||
let sm = psess.source_map();
|
||||
|
|
@ -110,7 +100,7 @@ pub fn new_parser_from_file<'a>(
|
|||
}
|
||||
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>(
|
||||
|
|
@ -172,6 +162,9 @@ fn new_parser_from_source_file(
|
|||
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(
|
||||
psess: &ParseSess,
|
||||
name: FileName,
|
||||
|
|
@ -179,13 +172,16 @@ pub fn source_str_to_stream(
|
|||
override_span: Option<Span>,
|
||||
) -> Result<TokenStream, Vec<Diag<'_>>> {
|
||||
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
|
||||
// frontmatters as frontmatters, but for compatibility reason still strip the shebang
|
||||
// FIXME(frontmatter): Consider stripping frontmatter in a future edition. We can't strip them
|
||||
// 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)
|
||||
}
|
||||
|
||||
/// Given a source file, produces a sequence of token trees. Returns any buffered errors from
|
||||
/// parsing the token stream.
|
||||
/// Given a source file, produces a sequence of token trees.
|
||||
///
|
||||
/// Returns any buffered errors from parsing the token stream.
|
||||
fn source_file_to_stream<'psess>(
|
||||
psess: &'psess ParseSess,
|
||||
source_file: Arc<SourceFile>,
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ use rustc_span::{
|
|||
};
|
||||
use termcolor::WriteColor;
|
||||
|
||||
use crate::lexer::StripTokens;
|
||||
use crate::parser::{ForceCollect, Parser};
|
||||
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,
|
||||
PathBuf::from("bogofile").into(),
|
||||
source_str,
|
||||
StripTokens::Nothing,
|
||||
))
|
||||
}
|
||||
|
||||
|
|
@ -2240,7 +2242,7 @@ fn parse_item_from_source_str(
|
|||
source: String,
|
||||
psess: &ParseSess,
|
||||
) -> 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)
|
||||
}
|
||||
|
||||
|
|
@ -2520,7 +2522,8 @@ fn ttdelim_span() {
|
|||
source: String,
|
||||
psess: &ParseSess,
|
||||
) -> 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(|| {
|
||||
|
|
|
|||
|
|
@ -21,18 +21,17 @@ mod tests;
|
|||
|
||||
// The proc macro code for this is in `compiler/rustc_macros/src/symbols.rs`.
|
||||
symbols! {
|
||||
// This list includes things that are definitely keywords (e.g. `if`),
|
||||
// a few things that are definitely not keywords (e.g. the empty symbol,
|
||||
// `{{root}}`) and things where there is disagreement between people and/or
|
||||
// documents (such as the Rust Reference) about whether it is a keyword
|
||||
// (e.g. `_`).
|
||||
// This list includes things that are definitely keywords (e.g. `if`), a
|
||||
// few things that are definitely not keywords (e.g. `{{root}}`) and things
|
||||
// where there is disagreement between people and/or documents (such as the
|
||||
// Rust Reference) about whether it is a keyword (e.g. `_`).
|
||||
//
|
||||
// If you modify this list, adjust any relevant `Symbol::{is,can_be}_*`
|
||||
// predicates and `used_keywords`. Also consider adding new keywords to the
|
||||
// `ui/parser/raw/raw-idents.rs` test.
|
||||
Keywords {
|
||||
// Special reserved identifiers used internally for elided lifetimes,
|
||||
// unnamed method parameters, crate root module, error recovery etc.
|
||||
// Special reserved identifiers used internally for unnamed method
|
||||
// parameters, crate root module, etc.
|
||||
// Matching predicates: `is_special`/`is_reserved`
|
||||
//
|
||||
// tidy-alphabetical-start
|
||||
|
|
|
|||
|
|
@ -95,6 +95,9 @@ impl Error {
|
|||
|
||||
pub(crate) const ZERO_TIMEOUT: Self =
|
||||
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")]
|
||||
|
|
|
|||
|
|
@ -34,7 +34,6 @@ pub use self::tcp::IntoIncoming;
|
|||
pub use self::tcp::{Incoming, TcpListener, TcpStream};
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub use self::udp::UdpSocket;
|
||||
use crate::io::{self, ErrorKind};
|
||||
|
||||
mod ip_addr;
|
||||
mod socket_addr;
|
||||
|
|
@ -67,23 +66,3 @@ pub enum Shutdown {
|
|||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
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")
|
||||
}))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -167,7 +167,7 @@ impl TcpStream {
|
|||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
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.
|
||||
|
|
@ -782,7 +782,7 @@ impl TcpListener {
|
|||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
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.
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
use crate::io::prelude::*;
|
||||
use crate::io::{BorrowedBuf, IoSlice, IoSliceMut};
|
||||
use crate::io::{BorrowedBuf, ErrorKind, IoSlice, IoSliceMut};
|
||||
use crate::mem::MaybeUninit;
|
||||
use crate::net::test::{next_test_ip4, next_test_ip6};
|
||||
use crate::net::*;
|
||||
|
|
|
|||
|
|
@ -120,7 +120,7 @@ impl UdpSocket {
|
|||
/// [`Ipv4Addr::UNSPECIFIED`] or [`Ipv6Addr::UNSPECIFIED`].
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
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
|
||||
|
|
@ -677,7 +677,7 @@ impl UdpSocket {
|
|||
/// on the platform.
|
||||
#[stable(feature = "net2_mutators", since = "1.9.0")]
|
||||
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.
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
use crate::io::ErrorKind;
|
||||
use crate::net::test::{compare_ignore_zoneid, next_test_ip4, next_test_ip6};
|
||||
use crate::net::*;
|
||||
use crate::sync::mpsc::channel;
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
use crate::fmt;
|
||||
use crate::panic::RefUnwindSafe;
|
||||
use crate::sync::nonpoison::{Condvar, Mutex};
|
||||
|
||||
/// A barrier enables multiple threads to synchronize the beginning
|
||||
|
|
@ -31,6 +32,9 @@ pub struct Barrier {
|
|||
num_threads: usize,
|
||||
}
|
||||
|
||||
#[stable(feature = "unwind_safe_lock_refs", since = "1.12.0")]
|
||||
impl RefUnwindSafe for Barrier {}
|
||||
|
||||
// The inner state of a double barrier
|
||||
struct BarrierState {
|
||||
count: usize,
|
||||
|
|
|
|||
57
library/std/src/sys/net/connection/mod.rs
Normal file
57
library/std/src/sys/net/connection/mod.rs
Normal 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),
|
||||
}
|
||||
}
|
||||
|
|
@ -1,3 +1,5 @@
|
|||
use crate::error;
|
||||
use crate::fmt::{self, Write};
|
||||
use crate::io::{self, BorrowedCursor, IoSlice, IoSliceMut};
|
||||
use crate::net::{Ipv4Addr, Ipv6Addr, Shutdown, SocketAddr, ToSocketAddrs};
|
||||
use crate::sync::Arc;
|
||||
|
|
@ -5,7 +7,6 @@ use crate::sys::abi::usercalls;
|
|||
use crate::sys::fd::FileDesc;
|
||||
use crate::sys::{AsInner, FromInner, IntoInner, TryIntoInner, sgx_ineffective, unsupported};
|
||||
use crate::time::Duration;
|
||||
use crate::{error, fmt};
|
||||
|
||||
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> {
|
||||
match result {
|
||||
Ok(saddr) => Ok(saddr.to_string()),
|
||||
// need to downcast twice because io::Error::into_inner doesn't return the original
|
||||
// value if the conversion fails
|
||||
Err(e) => {
|
||||
if e.get_ref().and_then(|e| e.downcast_ref::<NonIpSockAddr>()).is_some() {
|
||||
Ok(e.into_inner().unwrap().downcast::<NonIpSockAddr>().unwrap().host)
|
||||
} else {
|
||||
Err(e)
|
||||
/// Converts each address in `addr` into a hostname.
|
||||
///
|
||||
/// SGX doesn't support DNS resolution but rather accepts hostnames in
|
||||
/// the same place as socket addresses. So, to make e.g.
|
||||
/// ```rust
|
||||
/// TcpStream::connect("example.com:80")`
|
||||
/// ```
|
||||
/// work, the DNS lookup returns a special error (`NonIpSockAddr`) instead,
|
||||
/// which contains the hostname being looked up. When `.to_socket_addrs()`
|
||||
/// 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 {
|
||||
pub fn connect(addr: io::Result<&SocketAddr>) -> io::Result<TcpStream> {
|
||||
let addr = io_err_to_addr(addr)?;
|
||||
let (fd, local_addr, peer_addr) = usercalls::connect_stream(&addr)?;
|
||||
Ok(TcpStream { inner: Socket::new(fd, local_addr), peer_addr: Some(peer_addr) })
|
||||
pub fn connect<A: ToSocketAddrs>(addr: A) -> io::Result<TcpStream> {
|
||||
each_addr(addr, |addr| {
|
||||
let (fd, local_addr, peer_addr) = usercalls::connect_stream(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> {
|
||||
if dur == Duration::default() {
|
||||
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<()> {
|
||||
|
|
@ -247,10 +283,11 @@ impl fmt::Debug for TcpListener {
|
|||
}
|
||||
|
||||
impl TcpListener {
|
||||
pub fn bind(addr: io::Result<&SocketAddr>) -> io::Result<TcpListener> {
|
||||
let addr = io_err_to_addr(addr)?;
|
||||
let (fd, local_addr) = usercalls::bind_stream(&addr)?;
|
||||
Ok(TcpListener { inner: Socket::new(fd, local_addr) })
|
||||
pub fn bind<A: ToSocketAddrs>(addr: A) -> io::Result<TcpListener> {
|
||||
each_addr(addr, |addr| {
|
||||
let (fd, local_addr) = usercalls::bind_stream(addr)?;
|
||||
Ok(TcpListener { inner: Socket::new(fd, local_addr) })
|
||||
})
|
||||
}
|
||||
|
||||
pub fn socket_addr(&self) -> io::Result<SocketAddr> {
|
||||
|
|
@ -316,7 +353,7 @@ impl FromInner<Socket> for TcpListener {
|
|||
pub struct UdpSocket(!);
|
||||
|
||||
impl UdpSocket {
|
||||
pub fn bind(_: io::Result<&SocketAddr>) -> io::Result<UdpSocket> {
|
||||
pub fn bind<A: ToSocketAddrs>(_: A) -> io::Result<UdpSocket> {
|
||||
unsupported()
|
||||
}
|
||||
|
||||
|
|
@ -436,7 +473,7 @@ impl UdpSocket {
|
|||
self.0
|
||||
}
|
||||
|
||||
pub fn connect(&self, _: io::Result<&SocketAddr>) -> io::Result<()> {
|
||||
pub fn connect<A: ToSocketAddrs>(&self, _: A) -> io::Result<()> {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,8 +3,11 @@ mod tests;
|
|||
|
||||
use crate::ffi::{c_int, c_void};
|
||||
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::net::connection::each_addr;
|
||||
use crate::sys_common::{AsInner, FromInner};
|
||||
use crate::time::Duration;
|
||||
use crate::{cmp, fmt, mem, ptr};
|
||||
|
|
@ -342,14 +345,15 @@ pub struct TcpStream {
|
|||
}
|
||||
|
||||
impl TcpStream {
|
||||
pub fn connect(addr: io::Result<&SocketAddr>) -> io::Result<TcpStream> {
|
||||
let addr = addr?;
|
||||
|
||||
pub fn connect<A: ToSocketAddrs>(addr: A) -> io::Result<TcpStream> {
|
||||
init();
|
||||
return each_addr(addr, inner);
|
||||
|
||||
let sock = Socket::new(addr, c::SOCK_STREAM)?;
|
||||
sock.connect(addr)?;
|
||||
Ok(TcpStream { inner: sock })
|
||||
fn inner(addr: &SocketAddr) -> io::Result<TcpStream> {
|
||||
let sock = Socket::new(addr, c::SOCK_STREAM)?;
|
||||
sock.connect(addr)?;
|
||||
Ok(TcpStream { inner: sock })
|
||||
}
|
||||
}
|
||||
|
||||
pub fn connect_timeout(addr: &SocketAddr, timeout: Duration) -> io::Result<TcpStream> {
|
||||
|
|
@ -512,48 +516,45 @@ pub struct TcpListener {
|
|||
}
|
||||
|
||||
impl TcpListener {
|
||||
pub fn bind(addr: io::Result<&SocketAddr>) -> io::Result<TcpListener> {
|
||||
let addr = addr?;
|
||||
|
||||
pub fn bind<A: ToSocketAddrs>(addr: A) -> io::Result<TcpListener> {
|
||||
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
|
||||
// rebind a socket, without needing to wait for the OS to clean up the
|
||||
// previous one.
|
||||
//
|
||||
// On Windows, this allows rebinding sockets which are actively in use,
|
||||
// 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
|
||||
#[cfg(not(windows))]
|
||||
setsockopt(&sock, c::SOL_SOCKET, c::SO_REUSEADDR, 1 as c_int)?;
|
||||
// On platforms with Berkeley-derived sockets, this allows to quickly
|
||||
// rebind a socket, without needing to wait for the OS to clean up the
|
||||
// previous one.
|
||||
//
|
||||
// On Windows, this allows rebinding sockets which are actively in use,
|
||||
// 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
|
||||
#[cfg(not(windows))]
|
||||
setsockopt(&sock, c::SOL_SOCKET, c::SO_REUSEADDR, 1 as c_int)?;
|
||||
|
||||
// Bind our new socket
|
||||
let (addr, len) = socket_addr_to_c(addr);
|
||||
cvt(unsafe { c::bind(sock.as_raw(), addr.as_ptr(), len as _) })?;
|
||||
// Bind our new socket
|
||||
let (addr, len) = socket_addr_to_c(addr);
|
||||
cvt(unsafe { c::bind(sock.as_raw(), addr.as_ptr(), len as _) })?;
|
||||
|
||||
cfg_select! {
|
||||
target_os = "horizon" => {
|
||||
let backlog = if cfg!(target_os = "horizon") {
|
||||
// The 3DS doesn't support a big connection backlog. Sometimes
|
||||
// it allows up to about 37, but other times it doesn't even
|
||||
// accept 32. There may be a global limitation causing this.
|
||||
let backlog = 20;
|
||||
}
|
||||
target_os = "haiku" => {
|
||||
20
|
||||
} else if cfg!(target_os = "haiku") {
|
||||
// Haiku does not support a queue length > 32
|
||||
// https://github.com/haiku/haiku/blob/979a0bc487864675517fb2fab28f87dc8bf43041/headers/posix/sys/socket.h#L81
|
||||
let backlog = 32;
|
||||
}
|
||||
_ => {
|
||||
32
|
||||
} else {
|
||||
// The default for all other platforms
|
||||
let backlog = 128;
|
||||
}
|
||||
}
|
||||
128
|
||||
};
|
||||
|
||||
// Start listening
|
||||
cvt(unsafe { c::listen(sock.as_raw(), backlog) })?;
|
||||
Ok(TcpListener { inner: sock })
|
||||
// Start listening
|
||||
cvt(unsafe { c::listen(sock.as_raw(), backlog) })?;
|
||||
Ok(TcpListener { inner: sock })
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
|
|
@ -639,15 +640,16 @@ pub struct UdpSocket {
|
|||
}
|
||||
|
||||
impl UdpSocket {
|
||||
pub fn bind(addr: io::Result<&SocketAddr>) -> io::Result<UdpSocket> {
|
||||
let addr = addr?;
|
||||
|
||||
pub fn bind<A: ToSocketAddrs>(addr: A) -> io::Result<UdpSocket> {
|
||||
init();
|
||||
return each_addr(addr, inner);
|
||||
|
||||
let sock = Socket::new(addr, c::SOCK_DGRAM)?;
|
||||
let (addr, len) = socket_addr_to_c(addr);
|
||||
cvt(unsafe { c::bind(sock.as_raw(), addr.as_ptr(), len as _) })?;
|
||||
Ok(UdpSocket { inner: sock })
|
||||
fn inner(addr: &SocketAddr) -> io::Result<UdpSocket> {
|
||||
let sock = Socket::new(addr, c::SOCK_DGRAM)?;
|
||||
let (addr, len) = socket_addr_to_c(addr);
|
||||
cvt(unsafe { c::bind(sock.as_raw(), addr.as_ptr(), len as _) })?;
|
||||
Ok(UdpSocket { inner: sock })
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
|
|
@ -822,9 +824,13 @@ impl UdpSocket {
|
|||
Ok(ret as usize)
|
||||
}
|
||||
|
||||
pub fn connect(&self, addr: io::Result<&SocketAddr>) -> io::Result<()> {
|
||||
let (addr, len) = socket_addr_to_c(addr?);
|
||||
cvt_r(|| unsafe { c::connect(self.inner.as_raw(), addr.as_ptr(), len) }).map(drop)
|
||||
pub fn connect<A: ToSocketAddrs>(&self, addr: A) -> io::Result<()> {
|
||||
return each_addr(addr, |addr| inner(self, addr));
|
||||
|
||||
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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1,6 +1,7 @@
|
|||
use super::each_addr;
|
||||
use crate::fmt;
|
||||
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::sys::unsupported;
|
||||
use crate::time::Duration;
|
||||
|
|
@ -15,13 +16,17 @@ pub struct TcpStream {
|
|||
}
|
||||
|
||||
impl TcpStream {
|
||||
pub fn connect(addr: io::Result<&SocketAddr>) -> io::Result<TcpStream> {
|
||||
let inner = tcp::Tcp::connect(addr?, None)?;
|
||||
Ok(Self {
|
||||
inner,
|
||||
read_timeout: Arc::new(Mutex::new(None)),
|
||||
write_timeout: Arc::new(Mutex::new(None)),
|
||||
})
|
||||
pub fn connect<A: ToSocketAddrs>(addr: A) -> io::Result<TcpStream> {
|
||||
return each_addr(addr, inner);
|
||||
|
||||
fn inner(addr: &SocketAddr) -> io::Result<TcpStream> {
|
||||
let inner = tcp::Tcp::connect(addr, 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> {
|
||||
|
|
@ -145,7 +150,7 @@ pub struct TcpListener {
|
|||
}
|
||||
|
||||
impl TcpListener {
|
||||
pub fn bind(_: io::Result<&SocketAddr>) -> io::Result<TcpListener> {
|
||||
pub fn bind<A: ToSocketAddrs>(_: A) -> io::Result<TcpListener> {
|
||||
unsupported()
|
||||
}
|
||||
|
||||
|
|
@ -195,7 +200,7 @@ impl fmt::Debug for TcpListener {
|
|||
pub struct UdpSocket(!);
|
||||
|
||||
impl UdpSocket {
|
||||
pub fn bind(_: io::Result<&SocketAddr>) -> io::Result<UdpSocket> {
|
||||
pub fn bind<A: ToSocketAddrs>(_: A) -> io::Result<UdpSocket> {
|
||||
unsupported()
|
||||
}
|
||||
|
||||
|
|
@ -315,7 +320,7 @@ impl UdpSocket {
|
|||
self.0
|
||||
}
|
||||
|
||||
pub fn connect(&self, _: io::Result<&SocketAddr>) -> io::Result<()> {
|
||||
pub fn connect<A: ToSocketAddrs>(&self, _: A) -> io::Result<()> {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,13 +1,13 @@
|
|||
use crate::fmt;
|
||||
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::time::Duration;
|
||||
|
||||
pub struct TcpStream(!);
|
||||
|
||||
impl TcpStream {
|
||||
pub fn connect(_: io::Result<&SocketAddr>) -> io::Result<TcpStream> {
|
||||
pub fn connect<A: ToSocketAddrs>(_: A) -> io::Result<TcpStream> {
|
||||
unsupported()
|
||||
}
|
||||
|
||||
|
|
@ -121,7 +121,7 @@ impl fmt::Debug for TcpStream {
|
|||
pub struct TcpListener(!);
|
||||
|
||||
impl TcpListener {
|
||||
pub fn bind(_: io::Result<&SocketAddr>) -> io::Result<TcpListener> {
|
||||
pub fn bind<A: ToSocketAddrs>(_: A) -> io::Result<TcpListener> {
|
||||
unsupported()
|
||||
}
|
||||
|
||||
|
|
@ -171,7 +171,7 @@ impl fmt::Debug for TcpListener {
|
|||
pub struct UdpSocket(!);
|
||||
|
||||
impl UdpSocket {
|
||||
pub fn bind(_: io::Result<&SocketAddr>) -> io::Result<UdpSocket> {
|
||||
pub fn bind<A: ToSocketAddrs>(_: A) -> io::Result<UdpSocket> {
|
||||
unsupported()
|
||||
}
|
||||
|
||||
|
|
@ -291,7 +291,7 @@ impl UdpSocket {
|
|||
self.0
|
||||
}
|
||||
|
||||
pub fn connect(&self, _: io::Result<&SocketAddr>) -> io::Result<()> {
|
||||
pub fn connect<A: ToSocketAddrs>(&self, _: A) -> io::Result<()> {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
use crate::fmt;
|
||||
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::sys::fd::WasiFd;
|
||||
use crate::sys::{err2io, unsupported};
|
||||
|
|
@ -60,7 +60,7 @@ impl FromRawFd for Socket {
|
|||
}
|
||||
|
||||
impl TcpStream {
|
||||
pub fn connect(_: io::Result<&SocketAddr>) -> io::Result<TcpStream> {
|
||||
pub fn connect<A: ToSocketAddrs>(_: A) -> io::Result<TcpStream> {
|
||||
unsupported()
|
||||
}
|
||||
|
||||
|
|
@ -212,7 +212,7 @@ pub struct TcpListener {
|
|||
}
|
||||
|
||||
impl TcpListener {
|
||||
pub fn bind(_: io::Result<&SocketAddr>) -> io::Result<TcpListener> {
|
||||
pub fn bind<A: ToSocketAddrs>(_: A) -> io::Result<TcpListener> {
|
||||
unsupported()
|
||||
}
|
||||
|
||||
|
|
@ -316,7 +316,7 @@ pub struct UdpSocket {
|
|||
}
|
||||
|
||||
impl UdpSocket {
|
||||
pub fn bind(_: io::Result<&SocketAddr>) -> io::Result<UdpSocket> {
|
||||
pub fn bind<A: ToSocketAddrs>(_: A) -> io::Result<UdpSocket> {
|
||||
unsupported()
|
||||
}
|
||||
|
||||
|
|
@ -436,7 +436,7 @@ impl UdpSocket {
|
|||
unsupported()
|
||||
}
|
||||
|
||||
pub fn connect(&self, _: io::Result<&SocketAddr>) -> io::Result<()> {
|
||||
pub fn connect<A: ToSocketAddrs>(&self, _: A) -> io::Result<()> {
|
||||
unsupported()
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -2,9 +2,10 @@ use core::convert::TryInto;
|
|||
use core::sync::atomic::{Atomic, AtomicBool, AtomicU16, AtomicUsize, Ordering};
|
||||
|
||||
use super::*;
|
||||
use crate::net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr};
|
||||
use crate::net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr, ToSocketAddrs};
|
||||
use crate::os::xous::services;
|
||||
use crate::sync::Arc;
|
||||
use crate::sys::net::connection::each_addr;
|
||||
use crate::{fmt, io};
|
||||
|
||||
macro_rules! unimpl {
|
||||
|
|
@ -25,16 +26,19 @@ pub struct TcpListener {
|
|||
}
|
||||
|
||||
impl TcpListener {
|
||||
pub fn bind(socketaddr: io::Result<&SocketAddr>) -> io::Result<TcpListener> {
|
||||
let mut addr = *socketaddr?;
|
||||
pub fn bind<A: ToSocketAddrs>(addr: A) -> io::Result<TcpListener> {
|
||||
return each_addr(addr, inner);
|
||||
|
||||
let fd = TcpListener::bind_inner(&mut addr)?;
|
||||
return Ok(TcpListener {
|
||||
fd: Arc::new(AtomicU16::new(fd)),
|
||||
local: addr,
|
||||
handle_count: Arc::new(AtomicUsize::new(1)),
|
||||
nonblocking: Arc::new(AtomicBool::new(false)),
|
||||
});
|
||||
fn inner(addr: &SocketAddr) -> io::Result<TcpListener> {
|
||||
let mut addr = *addr;
|
||||
let fd = TcpListener::bind_inner(&mut addr)?;
|
||||
Ok(TcpListener {
|
||||
fd: Arc::new(AtomicU16::new(fd)),
|
||||
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
|
||||
|
|
|
|||
|
|
@ -3,9 +3,12 @@ use core::sync::atomic::{Atomic, AtomicBool, AtomicU32, AtomicUsize, Ordering};
|
|||
use super::*;
|
||||
use crate::fmt;
|
||||
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::sync::Arc;
|
||||
use crate::sys::net::connection::each_addr;
|
||||
use crate::time::Duration;
|
||||
|
||||
macro_rules! unimpl {
|
||||
|
|
@ -79,8 +82,8 @@ impl TcpStream {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn connect(socketaddr: io::Result<&SocketAddr>) -> io::Result<TcpStream> {
|
||||
Self::connect_timeout(socketaddr?, Duration::ZERO)
|
||||
pub fn connect<A: ToSocketAddrs>(addr: A) -> io::Result<TcpStream> {
|
||||
each_addr(addr, |addr| Self::connect_timeout(addr, Duration::ZERO))
|
||||
}
|
||||
|
||||
pub fn connect_timeout(addr: &SocketAddr, duration: Duration) -> io::Result<TcpStream> {
|
||||
|
|
|
|||
|
|
@ -3,9 +3,10 @@ use core::sync::atomic::{Atomic, AtomicUsize, Ordering};
|
|||
|
||||
use super::*;
|
||||
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::sync::Arc;
|
||||
use crate::sys::net::connection::each_addr;
|
||||
use crate::time::Duration;
|
||||
use crate::{fmt, io};
|
||||
|
||||
|
|
@ -32,40 +33,45 @@ pub struct UdpSocket {
|
|||
}
|
||||
|
||||
impl UdpSocket {
|
||||
pub fn bind(socketaddr: io::Result<&SocketAddr>) -> io::Result<UdpSocket> {
|
||||
let addr = socketaddr?;
|
||||
// Construct the request
|
||||
let mut connect_request = ConnectRequest { raw: [0u8; 4096] };
|
||||
pub fn bind<A: ToSocketAddrs>(addr: A) -> io::Result<UdpSocket> {
|
||||
return each_addr(addr, inner);
|
||||
|
||||
// Serialize the StdUdpBind structure. This is done "manually" because we don't want to
|
||||
// make an auto-serdes (like bincode or rkyv) crate a dependency of Xous.
|
||||
let port_bytes = addr.port().to_le_bytes();
|
||||
connect_request.raw[0] = port_bytes[0];
|
||||
connect_request.raw[1] = port_bytes[1];
|
||||
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;
|
||||
fn inner(addr: &SocketAddr) -> io::Result<UdpSocket> {
|
||||
// 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
|
||||
// make an auto-serdes (like bincode or rkyv) crate a dependency of Xous.
|
||||
let port_bytes = addr.port().to_le_bytes();
|
||||
connect_request.raw[0] = port_bytes[0];
|
||||
connect_request.raw[1] = port_bytes[1];
|
||||
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(
|
||||
services::net_server(),
|
||||
services::NetLendMut::StdUdpBind.into(),
|
||||
&mut connect_request.raw,
|
||||
0,
|
||||
4096,
|
||||
);
|
||||
let response = crate::os::xous::ffi::lend_mut(
|
||||
services::net_server(),
|
||||
services::NetLendMut::StdUdpBind.into(),
|
||||
&mut connect_request.raw,
|
||||
0,
|
||||
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
|
||||
// for an error.
|
||||
let response = connect_request.raw;
|
||||
|
|
@ -87,8 +93,9 @@ impl UdpSocket {
|
|||
));
|
||||
}
|
||||
}
|
||||
|
||||
let fd = response[1] as u16;
|
||||
return Ok(UdpSocket {
|
||||
Ok(UdpSocket {
|
||||
fd,
|
||||
local: *addr,
|
||||
remote: Cell::new(None),
|
||||
|
|
@ -96,9 +103,8 @@ impl UdpSocket {
|
|||
write_timeout: Cell::new(0),
|
||||
handle_count: Arc::new(AtomicUsize::new(1)),
|
||||
nonblocking: Cell::new(false),
|
||||
});
|
||||
})
|
||||
}
|
||||
Err(io::const_error!(io::ErrorKind::InvalidInput, "invalid response"))
|
||||
}
|
||||
|
||||
pub fn peer_addr(&self) -> io::Result<SocketAddr> {
|
||||
|
|
@ -198,10 +204,11 @@ impl UdpSocket {
|
|||
self.peek_from(buf).map(|(len, _addr)| len)
|
||||
}
|
||||
|
||||
pub fn connect(&self, maybe_addr: io::Result<&SocketAddr>) -> io::Result<()> {
|
||||
let addr = maybe_addr?;
|
||||
self.remote.set(Some(*addr));
|
||||
Ok(())
|
||||
pub fn connect<A: ToSocketAddrs>(&self, addr: A) -> io::Result<()> {
|
||||
each_addr(addr, |addr| {
|
||||
self.remote.set(Some(*addr));
|
||||
Ok(())
|
||||
})
|
||||
}
|
||||
|
||||
pub fn send(&self, buf: &[u8]) -> io::Result<usize> {
|
||||
|
|
|
|||
|
|
@ -1,46 +1,4 @@
|
|||
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 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::*;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// This module contains the implementations of `TcpStream`, `TcpListener` and
|
||||
/// `UdpSocket` as well as related functionality like DNS resolving.
|
||||
mod connection;
|
||||
pub use connection::*;
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
use std::panic::RefUnwindSafe;
|
||||
use std::sync::mpsc::{TryRecvError, channel};
|
||||
use std::sync::{Arc, Barrier};
|
||||
use std::thread;
|
||||
|
|
@ -33,3 +34,11 @@ fn test_barrier() {
|
|||
}
|
||||
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>();
|
||||
};
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ use rustc_ast::tokenstream::{TokenStream, TokenTree};
|
|||
use rustc_ast_pretty::pprust::PrintState;
|
||||
use rustc_ast_pretty::pprust::state::State as Printer;
|
||||
use rustc_middle::ty::TyCtxt;
|
||||
use rustc_parse::lexer::StripTokens;
|
||||
use rustc_session::parse::ParseSess;
|
||||
use rustc_span::symbol::{Ident, Symbol, kw};
|
||||
use rustc_span::{FileName, Span};
|
||||
|
|
@ -64,14 +65,18 @@ fn snippet_equal_to_token(tcx: TyCtxt<'_>, matcher: &TokenTree) -> Option<String
|
|||
// Create a Parser.
|
||||
let psess = ParseSess::new(rustc_driver::DEFAULT_LOCALE_RESOURCES.to_vec());
|
||||
let file_name = FileName::macro_expansion_source_code(&snippet);
|
||||
let mut parser =
|
||||
match rustc_parse::new_parser_from_source_str(&psess, file_name, snippet.clone()) {
|
||||
Ok(parser) => parser,
|
||||
Err(errs) => {
|
||||
errs.into_iter().for_each(|err| err.cancel());
|
||||
return None;
|
||||
}
|
||||
};
|
||||
let mut parser = match rustc_parse::new_parser_from_source_str(
|
||||
&psess,
|
||||
file_name,
|
||||
snippet.clone(),
|
||||
StripTokens::Nothing,
|
||||
) {
|
||||
Ok(parser) => parser,
|
||||
Err(errs) => {
|
||||
errs.into_iter().for_each(|err| err.cancel());
|
||||
return None;
|
||||
}
|
||||
};
|
||||
|
||||
// Reparse a single token tree.
|
||||
if parser.token == token::Eof {
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ use rustc_ast::tokenstream::TokenTree;
|
|||
use rustc_ast::{self as ast, AttrStyle, HasAttrs, StmtKind};
|
||||
use rustc_errors::emitter::stderr_destination;
|
||||
use rustc_errors::{ColorConfig, DiagCtxtHandle};
|
||||
use rustc_parse::lexer::StripTokens;
|
||||
use rustc_parse::new_parser_from_source_str;
|
||||
use rustc_session::parse::ParseSess;
|
||||
use rustc_span::edition::{DEFAULT_EDITION, Edition};
|
||||
|
|
@ -468,14 +469,16 @@ fn parse_source(
|
|||
let dcx = DiagCtxt::new(Box::new(emitter)).disable_warnings();
|
||||
let psess = ParseSess::with_dcx(dcx, sm);
|
||||
|
||||
let mut parser = match new_parser_from_source_str(&psess, filename, wrapped_source) {
|
||||
Ok(p) => p,
|
||||
Err(errs) => {
|
||||
errs.into_iter().for_each(|err| err.cancel());
|
||||
reset_error_count(&psess);
|
||||
return Err(());
|
||||
}
|
||||
};
|
||||
// Don't strip any tokens; it wouldn't matter anyway because the source is wrapped in a function.
|
||||
let mut parser =
|
||||
match new_parser_from_source_str(&psess, filename, wrapped_source, StripTokens::Nothing) {
|
||||
Ok(p) => p,
|
||||
Err(errs) => {
|
||||
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) {
|
||||
let extra_len = DOCTEST_CODE_WRAPPER.len();
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ use rustc_ast::{CoroutineKind, Fn, FnRetTy, Item, ItemKind};
|
|||
use rustc_errors::emitter::HumanEmitter;
|
||||
use rustc_errors::{Diag, DiagCtxt};
|
||||
use rustc_lint::LateContext;
|
||||
use rustc_parse::lexer::StripTokens;
|
||||
use rustc_parse::new_parser_from_source_str;
|
||||
use rustc_parse::parser::ForceCollect;
|
||||
use rustc_session::parse::ParseSess;
|
||||
|
|
@ -49,13 +50,14 @@ pub fn check(
|
|||
let sm = Arc::new(SourceMap::new(FilePathMapping::empty()));
|
||||
let psess = ParseSess::with_dcx(dcx, sm);
|
||||
|
||||
let mut parser = match new_parser_from_source_str(&psess, filename, code) {
|
||||
Ok(p) => p,
|
||||
Err(errs) => {
|
||||
errs.into_iter().for_each(Diag::cancel);
|
||||
return (false, test_attr_spans);
|
||||
},
|
||||
};
|
||||
let mut parser =
|
||||
match new_parser_from_source_str(&psess, filename, code, StripTokens::ShebangAndFrontmatter) {
|
||||
Ok(p) => p,
|
||||
Err(errs) => {
|
||||
errs.into_iter().for_each(Diag::cancel);
|
||||
return (false, test_attr_spans);
|
||||
},
|
||||
};
|
||||
|
||||
let mut relevant_main_found = false;
|
||||
let mut eligible = true;
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ use std::path::{Path, PathBuf};
|
|||
|
||||
use rustc_ast::{ast, attr};
|
||||
use rustc_errors::Diag;
|
||||
use rustc_parse::lexer::StripTokens;
|
||||
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_span::{Span, sym};
|
||||
|
|
@ -64,11 +65,14 @@ impl<'a> ParserBuilder<'a> {
|
|||
input: Input,
|
||||
) -> Result<RawParser<'a>, Vec<Diag<'a>>> {
|
||||
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(
|
||||
psess,
|
||||
rustc_span::FileName::Custom("stdin".to_owned()),
|
||||
text,
|
||||
StripTokens::ShebangAndFrontmatter,
|
||||
),
|
||||
}
|
||||
}
|
||||
|
|
@ -104,8 +108,12 @@ impl<'a> Parser<'a> {
|
|||
span: Span,
|
||||
) -> Result<(ast::AttrVec, ThinVec<Box<ast::Item>>, Span), ParserError> {
|
||||
let result = catch_unwind(AssertUnwindSafe(|| {
|
||||
let mut parser =
|
||||
unwrap_or_emit_fatal(new_parser_from_file(psess.inner(), path, Some(span)));
|
||||
let mut parser = unwrap_or_emit_fatal(new_parser_from_file(
|
||||
psess.inner(),
|
||||
path,
|
||||
StripTokens::ShebangAndFrontmatter,
|
||||
Some(span),
|
||||
));
|
||||
match parser.parse_mod(exp!(Eof)) {
|
||||
Ok((a, i, spans)) => Some((a, i, spans.inner_span)),
|
||||
Err(e) => {
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ extern crate rustc_span;
|
|||
use rustc_ast::ast::{AttrKind, Attribute, DUMMY_NODE_ID, Expr};
|
||||
use rustc_ast::mut_visit::{self, MutVisitor};
|
||||
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_errors::Diag;
|
||||
use rustc_parse::parser::Recovery;
|
||||
|
|
@ -23,6 +23,7 @@ pub fn parse_expr(psess: &ParseSess, source_code: &str) -> Option<Box<Expr>> {
|
|||
psess,
|
||||
FileName::anon_source_code(source_code),
|
||||
source_code.to_owned(),
|
||||
rustc_parse::lexer::StripTokens::Nothing,
|
||||
));
|
||||
|
||||
let mut parser = parser.recovery(Recovery::Forbidden);
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ extern crate rustc_span;
|
|||
#[allow(unused_extern_crates)]
|
||||
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 std::path::Path;
|
||||
|
||||
|
|
@ -34,6 +34,11 @@ fn parse() {
|
|||
|
||||
let path = Path::new(file!());
|
||||
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();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 `...` 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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 ) {
|
||||
| ^^^
|
||||
|
||||
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
|
||||
|
|
||||
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
|
||||
--> $DIR/issue-86053-1.rs:11:48
|
||||
|
|
|
|||
7
tests/ui/c-variadic/not-async.rs
Normal file
7
tests/ui/c-variadic/not-async.rs
Normal 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
|
||||
19
tests/ui/c-variadic/not-async.stderr
Normal file
19
tests/ui/c-variadic/not-async.stderr
Normal 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`.
|
||||
|
|
@ -53,9 +53,7 @@ extern "cmse-nonsecure-entry" fn trait_object(x: &dyn Trait) -> &dyn Trait {
|
|||
x
|
||||
}
|
||||
|
||||
extern "cmse-nonsecure-entry" fn static_trait_object(
|
||||
x: &'static dyn Trait,
|
||||
) -> &'static dyn Trait {
|
||||
extern "cmse-nonsecure-entry" fn static_trait_object(x: &'static dyn Trait) -> &'static dyn Trait {
|
||||
//~^ ERROR return value of `"cmse-nonsecure-entry"` function too large to pass via registers [E0798]
|
||||
x
|
||||
}
|
||||
|
|
@ -63,14 +61,12 @@ extern "cmse-nonsecure-entry" fn static_trait_object(
|
|||
#[repr(transparent)]
|
||||
struct WrapperTransparent<'a>(&'a dyn Trait);
|
||||
|
||||
extern "cmse-nonsecure-entry" fn wrapped_trait_object(
|
||||
x: WrapperTransparent,
|
||||
) -> WrapperTransparent {
|
||||
extern "cmse-nonsecure-entry" fn wrapped_trait_object(x: WrapperTransparent) -> WrapperTransparent {
|
||||
//~^ ERROR return value of `"cmse-nonsecure-entry"` function too large to pass via registers [E0798]
|
||||
x
|
||||
}
|
||||
|
||||
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
|
||||
unsafe extern "cmse-nonsecure-entry" fn c_variadic(_: u32, _: ...) {
|
||||
//~^ ERROR `...` is not supported for `extern "cmse-nonsecure-entry"` functions
|
||||
//~| ERROR requires `va_list` lang_item
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
--> $DIR/generics.rs:73:53
|
||||
error: `...` is not supported for `extern "cmse-nonsecure-entry"` functions
|
||||
--> $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
|
||||
--> $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
|
||||
|
||||
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 {
|
||||
| ^^^^^^^^^^^^^^^^^^ this type doesn't fit in the available registers
|
||||
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
|
||||
|
|
||||
= 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
|
||||
|
||||
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 {
|
||||
| ^^^^^^^^^^^^^^^^^^ this type doesn't fit in the available registers
|
||||
LL | extern "cmse-nonsecure-entry" fn wrapped_trait_object(x: WrapperTransparent) -> WrapperTransparent {
|
||||
| ^^^^^^^^^^^^^^^^^^ 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: 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
|
||||
--> $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
|
||||
|
||||
|
|
|
|||
79
tests/ui/deref/pin-deref-const.rs
Normal file
79
tests/ui/deref/pin-deref-const.rs
Normal 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() {}
|
||||
51
tests/ui/deref/pin-deref-const.stderr
Normal file
51
tests/ui/deref/pin-deref-const.stderr
Normal 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`.
|
||||
76
tests/ui/deref/pin-deref.rs
Normal file
76
tests/ui/deref/pin-deref.rs
Normal 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() {}
|
||||
51
tests/ui/deref/pin-deref.stderr
Normal file
51
tests/ui/deref/pin-deref.stderr
Normal 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`.
|
||||
40
tests/ui/deref/pin-impl-deref.rs
Normal file
40
tests/ui/deref/pin-impl-deref.rs
Normal 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() {}
|
||||
85
tests/ui/deref/pin-impl-deref.stderr
Normal file
85
tests/ui/deref/pin-impl-deref.stderr
Normal 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`.
|
||||
|
|
@ -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
|
||||
|
||||
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 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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
||||
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
|
||||
--> $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
|
||||
= 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
|
||||
--> $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
|
||||
= help: add `#![feature(c_variadic)]` to the crate attributes to enable
|
||||
|
|
|
|||
|
|
@ -62,6 +62,11 @@ LL | format!("", 1, 2);
|
|||
| | |
|
||||
| | argument never used
|
||||
| multiple missing formatting specifiers
|
||||
|
|
||||
help: format specifiers use curly braces, consider adding 2 format specifiers
|
||||
|
|
||||
LL | format!("{}{}", 1, 2);
|
||||
| ++++
|
||||
|
||||
error: argument never used
|
||||
--> $DIR/ifmt-bad-arg.rs:33:22
|
||||
|
|
@ -102,6 +107,11 @@ LL | format!("", foo=2);
|
|||
| -- ^ named argument never used
|
||||
| |
|
||||
| formatting specifier missing
|
||||
|
|
||||
help: format specifiers use curly braces, consider adding a format specifier
|
||||
|
|
||||
LL | format!("{}", foo=2);
|
||||
| ++
|
||||
|
||||
error: multiple unused formatting arguments
|
||||
--> $DIR/ifmt-bad-arg.rs:38:32
|
||||
|
|
@ -111,6 +121,8 @@ LL | format!("{} {}", 1, 2, foo=1, bar=2);
|
|||
| | |
|
||||
| | named argument never used
|
||||
| multiple missing formatting specifiers
|
||||
|
|
||||
= note: consider adding 2 format specifiers
|
||||
|
||||
error: duplicate argument named `foo`
|
||||
--> $DIR/ifmt-bad-arg.rs:40:29
|
||||
|
|
|
|||
4
tests/ui/frontmatter/auxiliary/expr.rs
Normal file
4
tests/ui/frontmatter/auxiliary/expr.rs
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
---
|
||||
-
|
||||
---
|
||||
1
|
||||
|
|
@ -1,8 +1,20 @@
|
|||
extern crate proc_macro;
|
||||
use proc_macro::TokenStream;
|
||||
use proc_macro::{Literal, TokenStream};
|
||||
|
||||
#[proc_macro]
|
||||
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());
|
||||
|
||||
// issue: <https://github.com/rust-lang/rust/issues/146132>
|
||||
assert!("---".parse::<Literal>().is_err());
|
||||
|
||||
Default::default()
|
||||
}
|
||||
|
|
|
|||
9
tests/ui/frontmatter/include-in-expr-ctxt.rs
Normal file
9
tests/ui/frontmatter/include-in-expr-ctxt.rs
Normal 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"));
|
||||
}
|
||||
10
tests/ui/frontmatter/include-in-item-ctxt.rs
Normal file
10
tests/ui/frontmatter/include-in-item-ctxt.rs
Normal 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);
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
|
|
@ -2,10 +2,9 @@
|
|||
//@ proc-macro: makro.rs
|
||||
//@ 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!();
|
||||
|
||||
// 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() {}
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@
|
|||
#![feature(c_variadic)]
|
||||
|
||||
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() {}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
--> $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 `'_`
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0700`.
|
||||
|
|
|
|||
|
|
@ -7,6 +7,11 @@ LL | println!("Test", 123, 456, 789);
|
|||
| | | argument never used
|
||||
| | argument never used
|
||||
| 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
|
||||
--> $DIR/format-unused-lables.rs:6:9
|
||||
|
|
@ -19,6 +24,11 @@ LL | 456,
|
|||
| ^^^ argument never used
|
||||
LL | 789
|
||||
| ^^^ argument never used
|
||||
|
|
||||
help: format specifiers use curly braces, consider adding 3 format specifiers
|
||||
|
|
||||
LL | println!("Test2{}{}{}",
|
||||
| ++++++
|
||||
|
||||
error: named argument never used
|
||||
--> $DIR/format-unused-lables.rs:11:35
|
||||
|
|
@ -27,6 +37,11 @@ LL | println!("Some stuff", UNUSED="args");
|
|||
| ------------ ^^^^^^ named argument never used
|
||||
| |
|
||||
| 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
|
||||
--> $DIR/format-unused-lables.rs:14:9
|
||||
|
|
|
|||
|
|
@ -4,7 +4,6 @@
|
|||
|
||||
fn main() {}
|
||||
|
||||
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
|
||||
unsafe extern "C" fn foo(_: Bar, ...) -> impl {}
|
||||
//~^ ERROR cannot find type `Bar` in this scope
|
||||
//~| ERROR at least one trait must be specified
|
||||
|
|
|
|||
|
|
@ -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
|
||||
--> $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
|
||||
--> $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 {}
|
||||
| ^^^ not found in this scope
|
||||
LL | unsafe extern "C" fn foo(_: Bar, ...) -> impl {}
|
||||
| ^^^ 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`.
|
||||
|
|
|
|||
|
|
@ -5,6 +5,11 @@ LL | println!("C", unsafe { &symbol });
|
|||
| --- ^^^^^^^^^^^^^^^^^^ argument never used
|
||||
| |
|
||||
| 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
|
||||
--> $DIR/unsized-extern-static.rs:6:5
|
||||
|
|
|
|||
|
|
@ -4,25 +4,28 @@
|
|||
fn main() {}
|
||||
|
||||
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(...) {}
|
||||
//~^ 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, ...) {}
|
||||
//~^ 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(...) {}
|
||||
//~^ 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) {}
|
||||
//~^ ERROR `...` must be the last argument of a C-variadic function
|
||||
|
||||
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(...) {}
|
||||
//~^ 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) {}
|
||||
//~^ 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, ...) {}
|
||||
//~^ 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
|
||||
|
||||
const extern "C" fn f4_3(..., x: isize, ...) {}
|
||||
//~^ 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
|
||||
|
||||
extern "C" {
|
||||
|
|
@ -50,30 +53,30 @@ struct X;
|
|||
|
||||
impl X {
|
||||
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(...) {}
|
||||
//~^ 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, ...) {}
|
||||
//~^ 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
|
||||
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
|
||||
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 destructor of `VaListImpl<'_>` cannot be evaluated at compile-time
|
||||
}
|
||||
|
||||
trait T {
|
||||
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, ...);
|
||||
//~^ 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(...) {}
|
||||
//~^ 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(...);
|
||||
//~^ 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) {}
|
||||
//~^ ERROR `...` must be the last argument of a C-variadic function
|
||||
fn t_f6(..., x: isize);
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
||||
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
|
||||
|
|
||||
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
|
||||
|
|
||||
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, ...) {}
|
||||
| ^^^
|
||||
|
|
||||
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
|
||||
--> $DIR/variadic-ffi-semantic-restrictions.rs:15:20
|
||||
error: functions with a C variable argument list must be unsafe
|
||||
--> $DIR/variadic-ffi-semantic-restrictions.rs:18:20
|
||||
|
|
||||
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
|
||||
--> $DIR/variadic-ffi-semantic-restrictions.rs:18:20
|
||||
--> $DIR/variadic-ffi-semantic-restrictions.rs:21:20
|
||||
|
|
||||
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
|
||||
--> $DIR/variadic-ffi-semantic-restrictions.rs:21:30
|
||||
error: functions with a C variable argument list must be unsafe
|
||||
--> $DIR/variadic-ffi-semantic-restrictions.rs:24:30
|
||||
|
|
||||
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
|
||||
--> $DIR/variadic-ffi-semantic-restrictions.rs:24:20
|
||||
error: functions with a C variable argument list must be unsafe
|
||||
--> $DIR/variadic-ffi-semantic-restrictions.rs:27:20
|
||||
|
|
||||
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
|
||||
--> $DIR/variadic-ffi-semantic-restrictions.rs:27:20
|
||||
--> $DIR/variadic-ffi-semantic-restrictions.rs:30:20
|
||||
|
|
||||
LL | extern "C" fn f3_3(..., x: isize) {}
|
||||
| ^^^
|
||||
|
||||
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, ...) {}
|
||||
| ^^^^^ `const` because of this ^^^ C-variadic because of this
|
||||
|
||||
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, ...) {}
|
||||
| ^^^^^ `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
|
||||
--> $DIR/variadic-ffi-semantic-restrictions.rs:34:36
|
||||
error: functions with a C variable argument list must be unsafe
|
||||
--> $DIR/variadic-ffi-semantic-restrictions.rs:37:36
|
||||
|
|
||||
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
|
||||
--> $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, ...) {}
|
||||
| ^^^
|
||||
|
||||
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, ...) {}
|
||||
| ^^^^^ `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
|
||||
--> $DIR/variadic-ffi-semantic-restrictions.rs:39:41
|
||||
error: functions with a C variable argument list must be unsafe
|
||||
--> $DIR/variadic-ffi-semantic-restrictions.rs:42:41
|
||||
|
|
||||
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
|
||||
--> $DIR/variadic-ffi-semantic-restrictions.rs:45:13
|
||||
--> $DIR/variadic-ffi-semantic-restrictions.rs:48:13
|
||||
|
|
||||
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
|
||||
--> $DIR/variadic-ffi-semantic-restrictions.rs:52:23
|
||||
error: associated functions cannot have a C variable argument list
|
||||
--> $DIR/variadic-ffi-semantic-restrictions.rs:55:23
|
||||
|
|
||||
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
|
||||
--> $DIR/variadic-ffi-semantic-restrictions.rs:54:13
|
||||
error: associated functions cannot have a C variable argument list
|
||||
--> $DIR/variadic-ffi-semantic-restrictions.rs:57:13
|
||||
|
|
||||
LL | fn i_f2(...) {}
|
||||
| ^^^
|
||||
|
||||
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, ...) {}
|
||||
| ^^^
|
||||
|
||||
error: defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention
|
||||
--> $DIR/variadic-ffi-semantic-restrictions.rs:56:28
|
||||
error: associated functions cannot have a C variable argument list
|
||||
--> $DIR/variadic-ffi-semantic-restrictions.rs:59:28
|
||||
|
|
||||
LL | fn i_f3(..., x: isize, ...) {}
|
||||
| ^^^
|
||||
|
||||
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, ...) {}
|
||||
| ^^^
|
||||
|
||||
error: defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention
|
||||
--> $DIR/variadic-ffi-semantic-restrictions.rs:59:28
|
||||
error: associated functions cannot have a C variable argument list
|
||||
--> $DIR/variadic-ffi-semantic-restrictions.rs:62:28
|
||||
|
|
||||
LL | fn i_f4(..., x: isize, ...) {}
|
||||
| ^^^
|
||||
|
||||
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, ...) {}
|
||||
| ^^^^^ ^^^ C-variadic 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
|
||||
--> $DIR/variadic-ffi-semantic-restrictions.rs:62:29
|
||||
error: associated functions cannot have a C variable argument list
|
||||
--> $DIR/variadic-ffi-semantic-restrictions.rs:65:29
|
||||
|
|
||||
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
|
||||
--> $DIR/variadic-ffi-semantic-restrictions.rs:69:23
|
||||
error: associated functions cannot have a C variable argument list
|
||||
--> $DIR/variadic-ffi-semantic-restrictions.rs:72:23
|
||||
|
|
||||
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
|
||||
--> $DIR/variadic-ffi-semantic-restrictions.rs:71:23
|
||||
error: associated functions cannot have a C variable argument list
|
||||
--> $DIR/variadic-ffi-semantic-restrictions.rs:74:23
|
||||
|
|
||||
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
|
||||
--> $DIR/variadic-ffi-semantic-restrictions.rs:73:13
|
||||
error: associated functions cannot have a C variable argument list
|
||||
--> $DIR/variadic-ffi-semantic-restrictions.rs:76:13
|
||||
|
|
||||
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
|
||||
--> $DIR/variadic-ffi-semantic-restrictions.rs:75:13
|
||||
error: associated functions cannot have a C variable argument list
|
||||
--> $DIR/variadic-ffi-semantic-restrictions.rs:78:13
|
||||
|
|
||||
LL | fn t_f4(...);
|
||||
| ^^^
|
||||
|
||||
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) {}
|
||||
| ^^^
|
||||
|
||||
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);
|
||||
| ^^^
|
||||
|
||||
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, ...) {}
|
||||
| ^^^ - 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
|
||||
|
||||
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, ...) {}
|
||||
| ^^^ - 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
|
||||
|
||||
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, ...) {}
|
||||
| ^^^ - value is dropped here
|
||||
| |
|
||||
| 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`.
|
||||
|
|
|
|||
|
|
@ -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() { }
|
||||
|
|
@ -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
|
||||
|
||||
|
|
@ -21,6 +21,20 @@ fn bar<T: ?Sized + ?Trait2 + ?Trait1 + ?Trait4>(_: &T) {}
|
|||
|
||||
// FIXME: `?Trait1` should be rejected, `Trait1` isn't marked `#[lang = "default_traitN"]`.
|
||||
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;
|
||||
impl !Trait2 for S {}
|
||||
|
|
|
|||
|
|
@ -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`
|
||||
--> $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) {}
|
||||
| ^^^^^^^
|
||||
|
||||
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
|
||||
|
||||
|
|
|
|||
|
|
@ -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() {}
|
||||
|
|
@ -13,32 +13,37 @@
|
|||
#![no_core]
|
||||
|
||||
#[lang = "pointee_sized"]
|
||||
trait PointeeSized {}
|
||||
trait PointeeSized: ?Leak {}
|
||||
|
||||
#[lang = "meta_sized"]
|
||||
trait MetaSized: PointeeSized {}
|
||||
trait MetaSized: PointeeSized + ?Leak {}
|
||||
|
||||
#[lang = "sized"]
|
||||
trait Sized: MetaSized {}
|
||||
trait Sized: MetaSized + ?Leak {}
|
||||
|
||||
#[lang = "copy"]
|
||||
pub trait Copy {}
|
||||
pub trait Copy: ?Leak {}
|
||||
impl<'a, T: ?Sized> Copy for &'a T {}
|
||||
|
||||
#[lang = "legacy_receiver"]
|
||||
trait Receiver {}
|
||||
trait Receiver: ?Leak {}
|
||||
impl<T: ?Sized + ?Leak> Receiver for &T {}
|
||||
impl<T: ?Sized + ?Leak> Receiver for &mut T {}
|
||||
|
||||
#[lang = "unsize"]
|
||||
trait Unsize<T: ?Sized + ?Leak> {}
|
||||
trait Unsize<T: ?Sized + ?Leak>: ?Leak {}
|
||||
|
||||
#[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 {}
|
||||
// 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"]
|
||||
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 {}
|
||||
// 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"]
|
||||
auto trait Leak {}
|
||||
|
|
@ -47,25 +52,52 @@ struct NonLeakS;
|
|||
impl !Leak for NonLeakS {}
|
||||
struct LeakS;
|
||||
|
||||
trait Trait {
|
||||
fn leak_foo(&self) {}
|
||||
fn maybe_leak_foo(&self) where Self: ?Leak {}
|
||||
fn bounds_check() {
|
||||
trait LeakTr {}
|
||||
|
||||
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 {}
|
||||
impl Trait for LeakS {}
|
||||
fn dyn_compat_check() {
|
||||
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.
|
||||
let _: dyn Trait + ?Leak<(), Undefined = ()>;
|
||||
let _: dyn LeakTr + ?Leak<(), Undefined = ()>;
|
||||
//~^ ERROR trait takes 0 generic arguments but 1 generic argument was supplied
|
||||
//~| ERROR associated type `Undefined` not found for `Leak`
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
|
|
|||
|
|
@ -1,49 +1,57 @@
|
|||
error[E0277]: the trait bound `NonLeakS: Leak` is not satisfied
|
||||
--> $DIR/maybe-bounds-in-dyn-traits.rs:59:25
|
||||
error[E0277]: the trait bound `NonLeakS: bounds_check::LeakTr` is not satisfied
|
||||
--> $DIR/maybe-bounds-in-dyn-traits.rs:65:26
|
||||
|
|
||||
LL | let _: &dyn Trait = &NonLeakS;
|
||||
| ^^^^^^^^^ unsatisfied trait bound
|
||||
LL | let _: &dyn LeakTr = &NonLeakS;
|
||||
| ^^^^^^^^^ unsatisfied trait bound
|
||||
|
|
||||
help: the trait `Leak` is not implemented for `NonLeakS`
|
||||
--> $DIR/maybe-bounds-in-dyn-traits.rs:46:1
|
||||
help: the trait `bounds_check::LeakTr` is not implemented for `NonLeakS`
|
||||
--> $DIR/maybe-bounds-in-dyn-traits.rs:51:1
|
||||
|
|
||||
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
|
||||
--> $DIR/maybe-bounds-in-dyn-traits.rs:64:7
|
||||
error[E0038]: the trait `DynCompatCheck2` is not dyn compatible
|
||||
--> $DIR/maybe-bounds-in-dyn-traits.rs:90:17
|
||||
|
|
||||
LL | x.leak_foo();
|
||||
| ^^^^^^^^ the trait `Leak` is not implemented for `dyn Trait`
|
||||
LL | fn mut_foo(&mut self) {}
|
||||
| --------- 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`
|
||||
--> $DIR/maybe-bounds-in-dyn-traits.rs:51:5
|
||||
note: for a trait to be dyn compatible it needs to allow building a vtable
|
||||
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) {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Trait::leak_foo`
|
||||
LL | trait DynCompatCheck2: ?Leak {
|
||||
| --------------- 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
|
||||
--> $DIR/maybe-bounds-in-dyn-traits.rs:68:25
|
||||
--> $DIR/maybe-bounds-in-dyn-traits.rs:98:26
|
||||
|
|
||||
LL | let _: dyn Trait + ?Leak<(), Undefined = ()>;
|
||||
| ^^^^-------------------- help: remove the unnecessary generics
|
||||
| |
|
||||
| expected 0 generic arguments
|
||||
LL | let _: dyn LeakTr + ?Leak<(), Undefined = ()>;
|
||||
| ^^^^-------------------- help: remove the unnecessary generics
|
||||
| |
|
||||
| expected 0 generic arguments
|
||||
|
|
||||
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 {}
|
||||
| ^^^^
|
||||
|
||||
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 = ()>;
|
||||
| ^^^^^^^^^ associated type `Undefined` not found
|
||||
LL | let _: dyn LeakTr + ?Leak<(), Undefined = ()>;
|
||||
| ^^^^^^^^^ associated type `Undefined` not found
|
||||
|
||||
error: aborting due to 4 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0107, E0220, E0277.
|
||||
For more information about an error, try `rustc --explain E0107`.
|
||||
Some errors have detailed explanations: E0038, E0107, E0220, E0277.
|
||||
For more information about an error, try `rustc --explain E0038`.
|
||||
|
|
|
|||
|
|
@ -14,18 +14,22 @@
|
|||
#![no_std]
|
||||
#![no_core]
|
||||
|
||||
#[lang = "copy"]
|
||||
pub trait Copy: ?Leak {}
|
||||
|
||||
#[lang = "pointee_sized"]
|
||||
trait PointeeSized {}
|
||||
trait PointeeSized: ?Leak {}
|
||||
|
||||
#[lang = "meta_sized"]
|
||||
trait MetaSized: PointeeSized {}
|
||||
trait MetaSized: PointeeSized + ?Leak {}
|
||||
|
||||
#[lang = "sized"]
|
||||
trait Sized: MetaSized {}
|
||||
trait Sized: MetaSized + ?Leak {}
|
||||
|
||||
#[lang = "legacy_receiver"]
|
||||
trait LegacyReceiver {}
|
||||
trait LegacyReceiver: ?Leak {}
|
||||
impl<T: ?Sized + ?Leak> LegacyReceiver for &T {}
|
||||
// Omit `T: ?Leak`.
|
||||
impl<T: ?Sized> LegacyReceiver for &mut T {}
|
||||
|
||||
#[lang = "default_trait1"]
|
||||
|
|
@ -38,83 +42,40 @@ struct LeakS;
|
|||
mod supertraits {
|
||||
use crate::*;
|
||||
|
||||
trait MaybeLeakT1: ?Leak {}
|
||||
trait MaybeLeakT2 where Self: ?Leak {}
|
||||
trait MaybeLeak: ?Leak {}
|
||||
impl MaybeLeak for NonLeakS {}
|
||||
|
||||
impl MaybeLeakT1 for NonLeakS {}
|
||||
impl MaybeLeakT2 for NonLeakS {}
|
||||
trait LeakT {}
|
||||
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::*;
|
||||
|
||||
trait TestBase1<T: ?Sized> {}
|
||||
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 {
|
||||
trait Test1 {
|
||||
type Leak1 = LeakS;
|
||||
type Leak2 = NonLeakS;
|
||||
//~^ ERROR the trait bound `NonLeakS: Leak` is not satisfied
|
||||
}
|
||||
|
||||
trait Test4 {
|
||||
trait Test2 {
|
||||
type MaybeLeak1: ?Leak = LeakS;
|
||||
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 {
|
||||
use crate::*;
|
||||
|
||||
trait Trait {
|
||||
fn leak_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`
|
||||
trait ReceiveCheck1: ?Leak {
|
||||
fn foo(&self) {}
|
||||
}
|
||||
|
||||
impl Trait for NonLeakS {}
|
||||
impl Trait for LeakS {}
|
||||
|
||||
fn foo() {
|
||||
LeakS.leak_foo();
|
||||
LeakS.maybe_leak_foo();
|
||||
NonLeakS.leak_foo();
|
||||
//~^ ERROR the trait bound `NonLeakS: Leak` is not satisfied
|
||||
NonLeakS.maybe_leak_foo();
|
||||
trait ReceiveCheck2: ?Leak {
|
||||
// There is no `?Leak` bound on corresponding `LegacyReceiver` impl.
|
||||
fn mut_foo(&mut self) {}
|
||||
//~^ ERROR `&mut Self` cannot be used as the type of `self` without the `arbitrary_self_types`
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,81 +1,49 @@
|
|||
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;
|
||||
| ^^^^^^^^ unsatisfied trait bound
|
||||
|
|
||||
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;
|
||||
| ^^^^^^^^^^^^^^^
|
||||
note: required by a bound in `Test3::Leak2`
|
||||
--> $DIR/maybe-bounds-in-traits.rs:67:9
|
||||
note: required by a bound in `Test1::Leak2`
|
||||
--> $DIR/maybe-bounds-in-traits.rs:58:9
|
||||
|
|
||||
LL | type Leak2 = NonLeakS;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Test3::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 {
|
||||
| ++++++
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Test1::Leak2`
|
||||
|
||||
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
|
||||
= 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
|
||||
= 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
|
||||
--> $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
|
||||
error: aborting due to 3 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0277, E0658.
|
||||
For more information about an error, try `rustc --explain E0277`.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue