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,
|
pub span: Span,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl FnSig {
|
||||||
|
/// Return a span encompassing the header, or where to insert it if empty.
|
||||||
|
pub fn header_span(&self) -> Span {
|
||||||
|
match self.header.ext {
|
||||||
|
Extern::Implicit(span) | Extern::Explicit(_, span) => {
|
||||||
|
return self.span.with_hi(span.hi());
|
||||||
|
}
|
||||||
|
Extern::None => {}
|
||||||
|
}
|
||||||
|
|
||||||
|
match self.header.safety {
|
||||||
|
Safety::Unsafe(span) | Safety::Safe(span) => return self.span.with_hi(span.hi()),
|
||||||
|
Safety::Default => {}
|
||||||
|
};
|
||||||
|
|
||||||
|
if let Some(coroutine_kind) = self.header.coroutine_kind {
|
||||||
|
return self.span.with_hi(coroutine_kind.span().hi());
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Const::Yes(span) = self.header.constness {
|
||||||
|
return self.span.with_hi(span.hi());
|
||||||
|
}
|
||||||
|
|
||||||
|
self.span.shrink_to_lo()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The span of the header's safety, or where to insert it if empty.
|
||||||
|
pub fn safety_span(&self) -> Span {
|
||||||
|
match self.header.safety {
|
||||||
|
Safety::Unsafe(span) | Safety::Safe(span) => span,
|
||||||
|
Safety::Default => {
|
||||||
|
// Insert after the `coroutine_kind` if available.
|
||||||
|
if let Some(extern_span) = self.header.ext.span() {
|
||||||
|
return extern_span.shrink_to_lo();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Insert right at the front of the signature.
|
||||||
|
self.header_span().shrink_to_hi()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The span of the header's extern, or where to insert it if empty.
|
||||||
|
pub fn extern_span(&self) -> Span {
|
||||||
|
self.header.ext.span().unwrap_or(self.safety_span().shrink_to_hi())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// A constraint on an associated item.
|
/// A constraint on an associated item.
|
||||||
///
|
///
|
||||||
/// ### Examples
|
/// ### Examples
|
||||||
|
|
@ -3526,6 +3574,13 @@ impl Extern {
|
||||||
None => Extern::Implicit(span),
|
None => Extern::Implicit(span),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn span(self) -> Option<Span> {
|
||||||
|
match self {
|
||||||
|
Extern::None => None,
|
||||||
|
Extern::Implicit(span) | Extern::Explicit(_, span) => Some(span),
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A function header.
|
/// A function header.
|
||||||
|
|
@ -3534,12 +3589,12 @@ impl Extern {
|
||||||
/// included in this struct (e.g., `async unsafe fn` or `const extern "C" fn`).
|
/// included in this struct (e.g., `async unsafe fn` or `const extern "C" fn`).
|
||||||
#[derive(Clone, Copy, Encodable, Decodable, Debug, Walkable)]
|
#[derive(Clone, Copy, Encodable, Decodable, Debug, Walkable)]
|
||||||
pub struct FnHeader {
|
pub struct FnHeader {
|
||||||
/// Whether this is `unsafe`, or has a default safety.
|
|
||||||
pub safety: Safety,
|
|
||||||
/// Whether this is `async`, `gen`, or nothing.
|
|
||||||
pub coroutine_kind: Option<CoroutineKind>,
|
|
||||||
/// The `const` keyword, if any
|
/// The `const` keyword, if any
|
||||||
pub constness: Const,
|
pub constness: Const,
|
||||||
|
/// Whether this is `async`, `gen`, or nothing.
|
||||||
|
pub coroutine_kind: Option<CoroutineKind>,
|
||||||
|
/// Whether this is `unsafe`, or has a default safety.
|
||||||
|
pub safety: Safety,
|
||||||
/// The `extern` keyword and corresponding ABI string, if any.
|
/// The `extern` keyword and corresponding ABI string, if any.
|
||||||
pub ext: Extern,
|
pub ext: Extern,
|
||||||
}
|
}
|
||||||
|
|
@ -3553,38 +3608,6 @@ impl FnHeader {
|
||||||
|| matches!(constness, Const::Yes(_))
|
|| matches!(constness, Const::Yes(_))
|
||||||
|| !matches!(ext, Extern::None)
|
|| !matches!(ext, Extern::None)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return a span encompassing the header, or none if all options are default.
|
|
||||||
pub fn span(&self) -> Option<Span> {
|
|
||||||
fn append(a: &mut Option<Span>, b: Span) {
|
|
||||||
*a = match a {
|
|
||||||
None => Some(b),
|
|
||||||
Some(x) => Some(x.to(b)),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut full_span = None;
|
|
||||||
|
|
||||||
match self.safety {
|
|
||||||
Safety::Unsafe(span) | Safety::Safe(span) => append(&mut full_span, span),
|
|
||||||
Safety::Default => {}
|
|
||||||
};
|
|
||||||
|
|
||||||
if let Some(coroutine_kind) = self.coroutine_kind {
|
|
||||||
append(&mut full_span, coroutine_kind.span());
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Const::Yes(span) = self.constness {
|
|
||||||
append(&mut full_span, span);
|
|
||||||
}
|
|
||||||
|
|
||||||
match self.ext {
|
|
||||||
Extern::Implicit(span) | Extern::Explicit(_, span) => append(&mut full_span, span),
|
|
||||||
Extern::None => {}
|
|
||||||
}
|
|
||||||
|
|
||||||
full_span
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for FnHeader {
|
impl Default for FnHeader {
|
||||||
|
|
|
||||||
|
|
@ -2101,17 +2101,14 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if self.tcx.features().more_maybe_bounds() {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
RelaxedBoundPolicy::Forbidden(reason) => {
|
RelaxedBoundPolicy::Forbidden(reason) => {
|
||||||
if self.tcx.features().more_maybe_bounds() {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
match reason {
|
match reason {
|
||||||
RelaxedBoundForbiddenReason::TraitObjectTy => {
|
RelaxedBoundForbiddenReason::TraitObjectTy => {
|
||||||
|
if self.tcx.features().more_maybe_bounds() {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
self.dcx().span_err(
|
self.dcx().span_err(
|
||||||
span,
|
span,
|
||||||
"relaxed bounds are not permitted in trait object types",
|
"relaxed bounds are not permitted in trait object types",
|
||||||
|
|
@ -2119,6 +2116,10 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
RelaxedBoundForbiddenReason::SuperTrait => {
|
RelaxedBoundForbiddenReason::SuperTrait => {
|
||||||
|
if self.tcx.features().more_maybe_bounds() {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
let mut diag = self.dcx().struct_span_err(
|
let mut diag = self.dcx().struct_span_err(
|
||||||
span,
|
span,
|
||||||
"relaxed bounds are not permitted in supertrait bounds",
|
"relaxed bounds are not permitted in supertrait bounds",
|
||||||
|
|
|
||||||
|
|
@ -57,8 +57,6 @@ ast_passes_auto_super_lifetime = auto traits cannot have super traits or lifetim
|
||||||
.label = {ast_passes_auto_super_lifetime}
|
.label = {ast_passes_auto_super_lifetime}
|
||||||
.suggestion = remove the super traits or lifetime bounds
|
.suggestion = remove the super traits or lifetime bounds
|
||||||
|
|
||||||
ast_passes_bad_c_variadic = defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention
|
|
||||||
|
|
||||||
ast_passes_body_in_extern = incorrect `{$kind}` inside `extern` block
|
ast_passes_body_in_extern = incorrect `{$kind}` inside `extern` block
|
||||||
.cannot_have = cannot have a body
|
.cannot_have = cannot have a body
|
||||||
.invalid = the invalid body
|
.invalid = the invalid body
|
||||||
|
|
@ -66,6 +64,19 @@ ast_passes_body_in_extern = incorrect `{$kind}` inside `extern` block
|
||||||
|
|
||||||
ast_passes_bound_in_context = bounds on `type`s in {$ctx} have no effect
|
ast_passes_bound_in_context = bounds on `type`s in {$ctx} have no effect
|
||||||
|
|
||||||
|
ast_passes_c_variadic_associated_function = associated functions cannot have a C variable argument list
|
||||||
|
|
||||||
|
ast_passes_c_variadic_bad_extern = `...` is not supported for `extern "{$abi}"` functions
|
||||||
|
.label = `extern "{$abi}"` because of this
|
||||||
|
.help = only `extern "C"` and `extern "C-unwind"` functions may have a C variable argument list
|
||||||
|
|
||||||
|
ast_passes_c_variadic_must_be_unsafe =
|
||||||
|
functions with a C variable argument list must be unsafe
|
||||||
|
.suggestion = add the `unsafe` keyword to this definition
|
||||||
|
|
||||||
|
ast_passes_c_variadic_no_extern = `...` is not supported for non-extern functions
|
||||||
|
.help = only `extern "C"` and `extern "C-unwind"` functions may have a C variable argument list
|
||||||
|
|
||||||
ast_passes_const_and_c_variadic = functions cannot be both `const` and C-variadic
|
ast_passes_const_and_c_variadic = functions cannot be both `const` and C-variadic
|
||||||
.const = `const` because of this
|
.const = `const` because of this
|
||||||
.variadic = C-variadic because of this
|
.variadic = C-variadic because of this
|
||||||
|
|
@ -84,6 +95,10 @@ ast_passes_const_without_body =
|
||||||
ast_passes_constraint_on_negative_bound =
|
ast_passes_constraint_on_negative_bound =
|
||||||
associated type constraints not allowed on negative bounds
|
associated type constraints not allowed on negative bounds
|
||||||
|
|
||||||
|
ast_passes_coroutine_and_c_variadic = functions cannot be both `{$coroutine_kind}` and C-variadic
|
||||||
|
.const = `{$coroutine_kind}` because of this
|
||||||
|
.variadic = C-variadic because of this
|
||||||
|
|
||||||
ast_passes_equality_in_where = equality constraints are not yet supported in `where` clauses
|
ast_passes_equality_in_where = equality constraints are not yet supported in `where` clauses
|
||||||
.label = not supported
|
.label = not supported
|
||||||
.suggestion = if `{$ident}` is an associated type you're trying to set, use the associated type binding syntax
|
.suggestion = if `{$ident}` is an associated type you're trying to set, use the associated type binding syntax
|
||||||
|
|
|
||||||
|
|
@ -492,7 +492,7 @@ impl<'a> AstValidator<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
if !spans.is_empty() {
|
if !spans.is_empty() {
|
||||||
let header_span = sig.header.span().unwrap_or(sig.span.shrink_to_lo());
|
let header_span = sig.header_span();
|
||||||
let suggestion_span = header_span.shrink_to_hi().to(sig.decl.output.span());
|
let suggestion_span = header_span.shrink_to_hi().to(sig.decl.output.span());
|
||||||
let padding = if header_span.is_empty() { "" } else { " " };
|
let padding = if header_span.is_empty() { "" } else { " " };
|
||||||
|
|
||||||
|
|
@ -685,22 +685,53 @@ impl<'a> AstValidator<'a> {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if let Some(coroutine_kind) = sig.header.coroutine_kind {
|
||||||
|
self.dcx().emit_err(errors::CoroutineAndCVariadic {
|
||||||
|
spans: vec![coroutine_kind.span(), variadic_param.span],
|
||||||
|
coroutine_kind: coroutine_kind.as_str(),
|
||||||
|
coroutine_span: coroutine_kind.span(),
|
||||||
|
variadic_span: variadic_param.span,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
match fn_ctxt {
|
match fn_ctxt {
|
||||||
FnCtxt::Foreign => return,
|
FnCtxt::Foreign => return,
|
||||||
FnCtxt::Free => match sig.header.ext {
|
FnCtxt::Free => match sig.header.ext {
|
||||||
Extern::Explicit(StrLit { symbol_unescaped: sym::C, .. }, _)
|
Extern::Implicit(_) => {
|
||||||
| Extern::Explicit(StrLit { symbol_unescaped: sym::C_dash_unwind, .. }, _)
|
if !matches!(sig.header.safety, Safety::Unsafe(_)) {
|
||||||
| Extern::Implicit(_)
|
self.dcx().emit_err(errors::CVariadicMustBeUnsafe {
|
||||||
if matches!(sig.header.safety, Safety::Unsafe(_)) =>
|
span: variadic_param.span,
|
||||||
{
|
unsafe_span: sig.safety_span(),
|
||||||
return;
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
_ => {}
|
Extern::Explicit(StrLit { symbol_unescaped, .. }, _) => {
|
||||||
},
|
if !matches!(symbol_unescaped, sym::C | sym::C_dash_unwind) {
|
||||||
FnCtxt::Assoc(_) => {}
|
self.dcx().emit_err(errors::CVariadicBadExtern {
|
||||||
};
|
span: variadic_param.span,
|
||||||
|
abi: symbol_unescaped,
|
||||||
|
extern_span: sig.extern_span(),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
self.dcx().emit_err(errors::BadCVariadic { span: variadic_param.span });
|
if !matches!(sig.header.safety, Safety::Unsafe(_)) {
|
||||||
|
self.dcx().emit_err(errors::CVariadicMustBeUnsafe {
|
||||||
|
span: variadic_param.span,
|
||||||
|
unsafe_span: sig.safety_span(),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Extern::None => {
|
||||||
|
let err = errors::CVariadicNoExtern { span: variadic_param.span };
|
||||||
|
self.dcx().emit_err(err);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
FnCtxt::Assoc(_) => {
|
||||||
|
// For now, C variable argument lists are unsupported in associated functions.
|
||||||
|
let err = errors::CVariadicAssociatedFunction { span: variadic_param.span };
|
||||||
|
self.dcx().emit_err(err);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_item_named(&self, ident: Ident, kind: &str) {
|
fn check_item_named(&self, ident: Ident, kind: &str) {
|
||||||
|
|
|
||||||
|
|
@ -319,12 +319,46 @@ pub(crate) struct ExternItemAscii {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Diagnostic)]
|
#[derive(Diagnostic)]
|
||||||
#[diag(ast_passes_bad_c_variadic)]
|
#[diag(ast_passes_c_variadic_associated_function)]
|
||||||
pub(crate) struct BadCVariadic {
|
pub(crate) struct CVariadicAssociatedFunction {
|
||||||
#[primary_span]
|
#[primary_span]
|
||||||
pub span: Span,
|
pub span: Span,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Diagnostic)]
|
||||||
|
#[diag(ast_passes_c_variadic_no_extern)]
|
||||||
|
#[help]
|
||||||
|
pub(crate) struct CVariadicNoExtern {
|
||||||
|
#[primary_span]
|
||||||
|
pub span: Span,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Diagnostic)]
|
||||||
|
#[diag(ast_passes_c_variadic_must_be_unsafe)]
|
||||||
|
pub(crate) struct CVariadicMustBeUnsafe {
|
||||||
|
#[primary_span]
|
||||||
|
pub span: Span,
|
||||||
|
|
||||||
|
#[suggestion(
|
||||||
|
ast_passes_suggestion,
|
||||||
|
applicability = "maybe-incorrect",
|
||||||
|
code = "unsafe ",
|
||||||
|
style = "verbose"
|
||||||
|
)]
|
||||||
|
pub unsafe_span: Span,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Diagnostic)]
|
||||||
|
#[diag(ast_passes_c_variadic_bad_extern)]
|
||||||
|
#[help]
|
||||||
|
pub(crate) struct CVariadicBadExtern {
|
||||||
|
#[primary_span]
|
||||||
|
pub span: Span,
|
||||||
|
pub abi: Symbol,
|
||||||
|
#[label]
|
||||||
|
pub extern_span: Span,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Diagnostic)]
|
#[derive(Diagnostic)]
|
||||||
#[diag(ast_passes_item_underscore)]
|
#[diag(ast_passes_item_underscore)]
|
||||||
pub(crate) struct ItemUnderscore<'a> {
|
pub(crate) struct ItemUnderscore<'a> {
|
||||||
|
|
@ -659,6 +693,18 @@ pub(crate) struct ConstAndCVariadic {
|
||||||
pub variadic_span: Span,
|
pub variadic_span: Span,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Diagnostic)]
|
||||||
|
#[diag(ast_passes_coroutine_and_c_variadic)]
|
||||||
|
pub(crate) struct CoroutineAndCVariadic {
|
||||||
|
#[primary_span]
|
||||||
|
pub spans: Vec<Span>,
|
||||||
|
pub coroutine_kind: &'static str,
|
||||||
|
#[label(ast_passes_const)]
|
||||||
|
pub coroutine_span: Span,
|
||||||
|
#[label(ast_passes_variadic)]
|
||||||
|
pub variadic_span: Span,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Diagnostic)]
|
#[derive(Diagnostic)]
|
||||||
#[diag(ast_passes_pattern_in_foreign, code = E0130)]
|
#[diag(ast_passes_pattern_in_foreign, code = E0130)]
|
||||||
// FIXME: deduplicate with rustc_lint (`BuiltinLintDiag::PatternsInFnsWithoutBody`)
|
// FIXME: deduplicate with rustc_lint (`BuiltinLintDiag::PatternsInFnsWithoutBody`)
|
||||||
|
|
|
||||||
|
|
@ -565,6 +565,7 @@ fn make_format_args(
|
||||||
&used,
|
&used,
|
||||||
&args,
|
&args,
|
||||||
&pieces,
|
&pieces,
|
||||||
|
&invalid_refs,
|
||||||
detect_foreign_fmt,
|
detect_foreign_fmt,
|
||||||
str_style,
|
str_style,
|
||||||
fmt_str,
|
fmt_str,
|
||||||
|
|
@ -645,6 +646,7 @@ fn report_missing_placeholders(
|
||||||
used: &[bool],
|
used: &[bool],
|
||||||
args: &FormatArguments,
|
args: &FormatArguments,
|
||||||
pieces: &[parse::Piece<'_>],
|
pieces: &[parse::Piece<'_>],
|
||||||
|
invalid_refs: &[(usize, Option<Span>, PositionUsedAs, FormatArgPositionKind)],
|
||||||
detect_foreign_fmt: bool,
|
detect_foreign_fmt: bool,
|
||||||
str_style: Option<usize>,
|
str_style: Option<usize>,
|
||||||
fmt_str: &str,
|
fmt_str: &str,
|
||||||
|
|
@ -762,6 +764,31 @@ fn report_missing_placeholders(
|
||||||
diag.span_label(fmt_span, "formatting specifier missing");
|
diag.span_label(fmt_span, "formatting specifier missing");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if !found_foreign && invalid_refs.is_empty() {
|
||||||
|
// Show example if user didn't use any format specifiers
|
||||||
|
let show_example = used.iter().all(|used| !used);
|
||||||
|
|
||||||
|
if !show_example {
|
||||||
|
if unused.len() > 1 {
|
||||||
|
diag.note(format!("consider adding {} format specifiers", unused.len()));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
let original_fmt_str =
|
||||||
|
if fmt_str.len() >= 1 { &fmt_str[..fmt_str.len() - 1] } else { "" };
|
||||||
|
|
||||||
|
let msg = if unused.len() == 1 {
|
||||||
|
"a format specifier".to_string()
|
||||||
|
} else {
|
||||||
|
format!("{} format specifiers", unused.len())
|
||||||
|
};
|
||||||
|
|
||||||
|
let sugg = format!("\"{}{}\"", original_fmt_str, "{}".repeat(unused.len()));
|
||||||
|
let msg = format!("format specifiers use curly braces, consider adding {msg}");
|
||||||
|
|
||||||
|
diag.span_suggestion_verbose(fmt_span, msg, sugg, Applicability::MaybeIncorrect);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
diag.emit();
|
diag.emit();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,5 @@
|
||||||
|
//! The implementation of built-in macros which relate to the file system.
|
||||||
|
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
@ -11,9 +13,11 @@ use rustc_expand::base::{
|
||||||
};
|
};
|
||||||
use rustc_expand::module::DirOwnership;
|
use rustc_expand::module::DirOwnership;
|
||||||
use rustc_lint_defs::BuiltinLintDiag;
|
use rustc_lint_defs::BuiltinLintDiag;
|
||||||
use rustc_parse::parser::{ForceCollect, Parser};
|
use rustc_parse::lexer::StripTokens;
|
||||||
|
use rustc_parse::parser::ForceCollect;
|
||||||
use rustc_parse::{new_parser_from_file, unwrap_or_emit_fatal, utf8_error};
|
use rustc_parse::{new_parser_from_file, unwrap_or_emit_fatal, utf8_error};
|
||||||
use rustc_session::lint::builtin::INCOMPLETE_INCLUDE;
|
use rustc_session::lint::builtin::INCOMPLETE_INCLUDE;
|
||||||
|
use rustc_session::parse::ParseSess;
|
||||||
use rustc_span::source_map::SourceMap;
|
use rustc_span::source_map::SourceMap;
|
||||||
use rustc_span::{ByteSymbol, Pos, Span, Symbol};
|
use rustc_span::{ByteSymbol, Pos, Span, Symbol};
|
||||||
use smallvec::SmallVec;
|
use smallvec::SmallVec;
|
||||||
|
|
@ -23,11 +27,7 @@ use crate::util::{
|
||||||
check_zero_tts, get_single_str_from_tts, get_single_str_spanned_from_tts, parse_expr,
|
check_zero_tts, get_single_str_from_tts, get_single_str_spanned_from_tts, parse_expr,
|
||||||
};
|
};
|
||||||
|
|
||||||
// These macros all relate to the file system; they either return
|
/// Expand `line!()` to the current line number.
|
||||||
// the column/row/filename of the expression, or they include
|
|
||||||
// a given file into the current one.
|
|
||||||
|
|
||||||
/// line!(): expands to the current line number
|
|
||||||
pub(crate) fn expand_line(
|
pub(crate) fn expand_line(
|
||||||
cx: &mut ExtCtxt<'_>,
|
cx: &mut ExtCtxt<'_>,
|
||||||
sp: Span,
|
sp: Span,
|
||||||
|
|
@ -42,7 +42,7 @@ pub(crate) fn expand_line(
|
||||||
ExpandResult::Ready(MacEager::expr(cx.expr_u32(topmost, loc.line as u32)))
|
ExpandResult::Ready(MacEager::expr(cx.expr_u32(topmost, loc.line as u32)))
|
||||||
}
|
}
|
||||||
|
|
||||||
/* column!(): expands to the current column number */
|
/// Expand `column!()` to the current column number.
|
||||||
pub(crate) fn expand_column(
|
pub(crate) fn expand_column(
|
||||||
cx: &mut ExtCtxt<'_>,
|
cx: &mut ExtCtxt<'_>,
|
||||||
sp: Span,
|
sp: Span,
|
||||||
|
|
@ -57,9 +57,7 @@ pub(crate) fn expand_column(
|
||||||
ExpandResult::Ready(MacEager::expr(cx.expr_u32(topmost, loc.col.to_usize() as u32 + 1)))
|
ExpandResult::Ready(MacEager::expr(cx.expr_u32(topmost, loc.col.to_usize() as u32 + 1)))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// file!(): expands to the current filename */
|
/// Expand `file!()` to the current filename.
|
||||||
/// The source_file (`loc.file`) contains a bunch more information we could spit
|
|
||||||
/// out if we wanted.
|
|
||||||
pub(crate) fn expand_file(
|
pub(crate) fn expand_file(
|
||||||
cx: &mut ExtCtxt<'_>,
|
cx: &mut ExtCtxt<'_>,
|
||||||
sp: Span,
|
sp: Span,
|
||||||
|
|
@ -81,6 +79,7 @@ pub(crate) fn expand_file(
|
||||||
)))
|
)))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Expand `stringify!($input)`.
|
||||||
pub(crate) fn expand_stringify(
|
pub(crate) fn expand_stringify(
|
||||||
cx: &mut ExtCtxt<'_>,
|
cx: &mut ExtCtxt<'_>,
|
||||||
sp: Span,
|
sp: Span,
|
||||||
|
|
@ -91,6 +90,7 @@ pub(crate) fn expand_stringify(
|
||||||
ExpandResult::Ready(MacEager::expr(cx.expr_str(sp, Symbol::intern(&s))))
|
ExpandResult::Ready(MacEager::expr(cx.expr_str(sp, Symbol::intern(&s))))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Expand `module_path!()` to (a textual representation of) the current module path.
|
||||||
pub(crate) fn expand_mod(
|
pub(crate) fn expand_mod(
|
||||||
cx: &mut ExtCtxt<'_>,
|
cx: &mut ExtCtxt<'_>,
|
||||||
sp: Span,
|
sp: Span,
|
||||||
|
|
@ -104,9 +104,9 @@ pub(crate) fn expand_mod(
|
||||||
ExpandResult::Ready(MacEager::expr(cx.expr_str(sp, Symbol::intern(&string))))
|
ExpandResult::Ready(MacEager::expr(cx.expr_str(sp, Symbol::intern(&string))))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// include! : parse the given file as an expr
|
/// Expand `include!($input)`.
|
||||||
/// This is generally a bad idea because it's going to behave
|
///
|
||||||
/// unhygienically.
|
/// This works in item and expression position. Notably, it doesn't work in pattern position.
|
||||||
pub(crate) fn expand_include<'cx>(
|
pub(crate) fn expand_include<'cx>(
|
||||||
cx: &'cx mut ExtCtxt<'_>,
|
cx: &'cx mut ExtCtxt<'_>,
|
||||||
sp: Span,
|
sp: Span,
|
||||||
|
|
@ -116,39 +116,48 @@ pub(crate) fn expand_include<'cx>(
|
||||||
let ExpandResult::Ready(mac) = get_single_str_from_tts(cx, sp, tts, "include!") else {
|
let ExpandResult::Ready(mac) = get_single_str_from_tts(cx, sp, tts, "include!") else {
|
||||||
return ExpandResult::Retry(());
|
return ExpandResult::Retry(());
|
||||||
};
|
};
|
||||||
let file = match mac {
|
let path = match mac {
|
||||||
Ok(file) => file,
|
Ok(path) => path,
|
||||||
Err(guar) => return ExpandResult::Ready(DummyResult::any(sp, guar)),
|
Err(guar) => return ExpandResult::Ready(DummyResult::any(sp, guar)),
|
||||||
};
|
};
|
||||||
// The file will be added to the code map by the parser
|
// The file will be added to the code map by the parser
|
||||||
let file = match resolve_path(&cx.sess, file.as_str(), sp) {
|
let path = match resolve_path(&cx.sess, path.as_str(), sp) {
|
||||||
Ok(f) => f,
|
Ok(path) => path,
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
let guar = err.emit();
|
let guar = err.emit();
|
||||||
return ExpandResult::Ready(DummyResult::any(sp, guar));
|
return ExpandResult::Ready(DummyResult::any(sp, guar));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
let p = unwrap_or_emit_fatal(new_parser_from_file(cx.psess(), &file, Some(sp)));
|
|
||||||
|
|
||||||
// If in the included file we have e.g., `mod bar;`,
|
// If in the included file we have e.g., `mod bar;`,
|
||||||
// then the path of `bar.rs` should be relative to the directory of `file`.
|
// then the path of `bar.rs` should be relative to the directory of `path`.
|
||||||
// See https://github.com/rust-lang/rust/pull/69838/files#r395217057 for a discussion.
|
// See https://github.com/rust-lang/rust/pull/69838/files#r395217057 for a discussion.
|
||||||
// `MacroExpander::fully_expand_fragment` later restores, so "stack discipline" is maintained.
|
// `MacroExpander::fully_expand_fragment` later restores, so "stack discipline" is maintained.
|
||||||
let dir_path = file.parent().unwrap_or(&file).to_owned();
|
let dir_path = path.parent().unwrap_or(&path).to_owned();
|
||||||
cx.current_expansion.module = Rc::new(cx.current_expansion.module.with_dir_path(dir_path));
|
cx.current_expansion.module = Rc::new(cx.current_expansion.module.with_dir_path(dir_path));
|
||||||
cx.current_expansion.dir_ownership = DirOwnership::Owned { relative: None };
|
cx.current_expansion.dir_ownership = DirOwnership::Owned { relative: None };
|
||||||
|
|
||||||
struct ExpandInclude<'a> {
|
struct ExpandInclude<'a> {
|
||||||
p: Parser<'a>,
|
psess: &'a ParseSess,
|
||||||
|
path: PathBuf,
|
||||||
node_id: ast::NodeId,
|
node_id: ast::NodeId,
|
||||||
|
span: Span,
|
||||||
}
|
}
|
||||||
impl<'a> MacResult for ExpandInclude<'a> {
|
impl<'a> MacResult for ExpandInclude<'a> {
|
||||||
fn make_expr(mut self: Box<ExpandInclude<'a>>) -> Option<Box<ast::Expr>> {
|
fn make_expr(self: Box<ExpandInclude<'a>>) -> Option<Box<ast::Expr>> {
|
||||||
let expr = parse_expr(&mut self.p).ok()?;
|
let mut p = unwrap_or_emit_fatal(new_parser_from_file(
|
||||||
if self.p.token != token::Eof {
|
self.psess,
|
||||||
self.p.psess.buffer_lint(
|
&self.path,
|
||||||
|
// Don't strip frontmatter for backward compatibility, `---` may be the start of a
|
||||||
|
// manifold negation. FIXME: Ideally, we wouldn't strip shebangs here either.
|
||||||
|
StripTokens::Shebang,
|
||||||
|
Some(self.span),
|
||||||
|
));
|
||||||
|
let expr = parse_expr(&mut p).ok()?;
|
||||||
|
if p.token != token::Eof {
|
||||||
|
p.psess.buffer_lint(
|
||||||
INCOMPLETE_INCLUDE,
|
INCOMPLETE_INCLUDE,
|
||||||
self.p.token.span,
|
p.token.span,
|
||||||
self.node_id,
|
self.node_id,
|
||||||
BuiltinLintDiag::IncompleteInclude,
|
BuiltinLintDiag::IncompleteInclude,
|
||||||
);
|
);
|
||||||
|
|
@ -156,24 +165,27 @@ pub(crate) fn expand_include<'cx>(
|
||||||
Some(expr)
|
Some(expr)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn make_items(mut self: Box<ExpandInclude<'a>>) -> Option<SmallVec<[Box<ast::Item>; 1]>> {
|
fn make_items(self: Box<ExpandInclude<'a>>) -> Option<SmallVec<[Box<ast::Item>; 1]>> {
|
||||||
|
let mut p = unwrap_or_emit_fatal(new_parser_from_file(
|
||||||
|
self.psess,
|
||||||
|
&self.path,
|
||||||
|
StripTokens::ShebangAndFrontmatter,
|
||||||
|
Some(self.span),
|
||||||
|
));
|
||||||
let mut ret = SmallVec::new();
|
let mut ret = SmallVec::new();
|
||||||
loop {
|
loop {
|
||||||
match self.p.parse_item(ForceCollect::No) {
|
match p.parse_item(ForceCollect::No) {
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
err.emit();
|
err.emit();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
Ok(Some(item)) => ret.push(item),
|
Ok(Some(item)) => ret.push(item),
|
||||||
Ok(None) => {
|
Ok(None) => {
|
||||||
if self.p.token != token::Eof {
|
if p.token != token::Eof {
|
||||||
self.p
|
p.dcx().emit_err(errors::ExpectedItem {
|
||||||
.dcx()
|
span: p.token.span,
|
||||||
.create_err(errors::ExpectedItem {
|
token: &pprust::token_to_string(&p.token),
|
||||||
span: self.p.token.span,
|
});
|
||||||
token: &pprust::token_to_string(&self.p.token),
|
|
||||||
})
|
|
||||||
.emit();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
@ -184,10 +196,17 @@ pub(crate) fn expand_include<'cx>(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ExpandResult::Ready(Box::new(ExpandInclude { p, node_id: cx.current_expansion.lint_node_id }))
|
ExpandResult::Ready(Box::new(ExpandInclude {
|
||||||
|
psess: cx.psess(),
|
||||||
|
path,
|
||||||
|
node_id: cx.current_expansion.lint_node_id,
|
||||||
|
span: sp,
|
||||||
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// `include_str!`: read the given file, insert it as a literal string expr
|
/// Expand `include_str!($input)` to the content of the UTF-8-encoded file given by path `$input` as a string literal.
|
||||||
|
///
|
||||||
|
/// This works in expression, pattern and statement position.
|
||||||
pub(crate) fn expand_include_str(
|
pub(crate) fn expand_include_str(
|
||||||
cx: &mut ExtCtxt<'_>,
|
cx: &mut ExtCtxt<'_>,
|
||||||
sp: Span,
|
sp: Span,
|
||||||
|
|
@ -206,6 +225,7 @@ pub(crate) fn expand_include_str(
|
||||||
Ok((bytes, bsp)) => match std::str::from_utf8(&bytes) {
|
Ok((bytes, bsp)) => match std::str::from_utf8(&bytes) {
|
||||||
Ok(src) => {
|
Ok(src) => {
|
||||||
let interned_src = Symbol::intern(src);
|
let interned_src = Symbol::intern(src);
|
||||||
|
// MacEager converts the expr into a pat if need be.
|
||||||
MacEager::expr(cx.expr_str(cx.with_def_site_ctxt(bsp), interned_src))
|
MacEager::expr(cx.expr_str(cx.with_def_site_ctxt(bsp), interned_src))
|
||||||
}
|
}
|
||||||
Err(utf8err) => {
|
Err(utf8err) => {
|
||||||
|
|
@ -218,6 +238,9 @@ pub(crate) fn expand_include_str(
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Expand `include_bytes!($input)` to the content of the file given by path `$input`.
|
||||||
|
///
|
||||||
|
/// This works in expression, pattern and statement position.
|
||||||
pub(crate) fn expand_include_bytes(
|
pub(crate) fn expand_include_bytes(
|
||||||
cx: &mut ExtCtxt<'_>,
|
cx: &mut ExtCtxt<'_>,
|
||||||
sp: Span,
|
sp: Span,
|
||||||
|
|
@ -237,6 +260,7 @@ pub(crate) fn expand_include_bytes(
|
||||||
// Don't care about getting the span for the raw bytes,
|
// Don't care about getting the span for the raw bytes,
|
||||||
// because the console can't really show them anyway.
|
// because the console can't really show them anyway.
|
||||||
let expr = cx.expr(sp, ast::ExprKind::IncludedBytes(ByteSymbol::intern(&bytes)));
|
let expr = cx.expr(sp, ast::ExprKind::IncludedBytes(ByteSymbol::intern(&bytes)));
|
||||||
|
// MacEager converts the expr into a pat if need be.
|
||||||
MacEager::expr(expr)
|
MacEager::expr(expr)
|
||||||
}
|
}
|
||||||
Err(dummy) => dummy,
|
Err(dummy) => dummy,
|
||||||
|
|
|
||||||
|
|
@ -51,6 +51,7 @@ use rustc_lint::unerased_lint_store;
|
||||||
use rustc_metadata::creader::MetadataLoader;
|
use rustc_metadata::creader::MetadataLoader;
|
||||||
use rustc_metadata::locator;
|
use rustc_metadata::locator;
|
||||||
use rustc_middle::ty::TyCtxt;
|
use rustc_middle::ty::TyCtxt;
|
||||||
|
use rustc_parse::lexer::StripTokens;
|
||||||
use rustc_parse::{new_parser_from_file, new_parser_from_source_str, unwrap_or_emit_fatal};
|
use rustc_parse::{new_parser_from_file, new_parser_from_source_str, unwrap_or_emit_fatal};
|
||||||
use rustc_session::config::{
|
use rustc_session::config::{
|
||||||
CG_OPTIONS, CrateType, ErrorOutputType, Input, OptionDesc, OutFileName, OutputType, Sysroot,
|
CG_OPTIONS, CrateType, ErrorOutputType, Input, OptionDesc, OutFileName, OutputType, Sysroot,
|
||||||
|
|
@ -1288,10 +1289,15 @@ fn warn_on_confusing_output_filename_flag(
|
||||||
|
|
||||||
fn parse_crate_attrs<'a>(sess: &'a Session) -> PResult<'a, ast::AttrVec> {
|
fn parse_crate_attrs<'a>(sess: &'a Session) -> PResult<'a, ast::AttrVec> {
|
||||||
let mut parser = unwrap_or_emit_fatal(match &sess.io.input {
|
let mut parser = unwrap_or_emit_fatal(match &sess.io.input {
|
||||||
Input::File(file) => new_parser_from_file(&sess.psess, file, None),
|
Input::File(file) => {
|
||||||
Input::Str { name, input } => {
|
new_parser_from_file(&sess.psess, file, StripTokens::ShebangAndFrontmatter, None)
|
||||||
new_parser_from_source_str(&sess.psess, name.clone(), input.clone())
|
|
||||||
}
|
}
|
||||||
|
Input::Str { name, input } => new_parser_from_source_str(
|
||||||
|
&sess.psess,
|
||||||
|
name.clone(),
|
||||||
|
input.clone(),
|
||||||
|
StripTokens::ShebangAndFrontmatter,
|
||||||
|
),
|
||||||
});
|
});
|
||||||
parser.parse_inner_attributes()
|
parser.parse_inner_attributes()
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@ use std::path::{self, Path, PathBuf};
|
||||||
use rustc_ast::{AttrVec, Attribute, Inline, Item, ModSpans};
|
use rustc_ast::{AttrVec, Attribute, Inline, Item, ModSpans};
|
||||||
use rustc_attr_parsing::validate_attr;
|
use rustc_attr_parsing::validate_attr;
|
||||||
use rustc_errors::{Diag, ErrorGuaranteed};
|
use rustc_errors::{Diag, ErrorGuaranteed};
|
||||||
|
use rustc_parse::lexer::StripTokens;
|
||||||
use rustc_parse::{exp, new_parser_from_file, unwrap_or_emit_fatal};
|
use rustc_parse::{exp, new_parser_from_file, unwrap_or_emit_fatal};
|
||||||
use rustc_session::Session;
|
use rustc_session::Session;
|
||||||
use rustc_session::parse::ParseSess;
|
use rustc_session::parse::ParseSess;
|
||||||
|
|
@ -67,8 +68,12 @@ pub(crate) fn parse_external_mod(
|
||||||
}
|
}
|
||||||
|
|
||||||
// Actually parse the external file as a module.
|
// Actually parse the external file as a module.
|
||||||
let mut parser =
|
let mut parser = unwrap_or_emit_fatal(new_parser_from_file(
|
||||||
unwrap_or_emit_fatal(new_parser_from_file(&sess.psess, &mp.file_path, Some(span)));
|
&sess.psess,
|
||||||
|
&mp.file_path,
|
||||||
|
StripTokens::ShebangAndFrontmatter,
|
||||||
|
Some(span),
|
||||||
|
));
|
||||||
let (inner_attrs, items, inner_span) =
|
let (inner_attrs, items, inner_span) =
|
||||||
parser.parse_mod(exp!(Eof)).map_err(|err| ModError::ParserError(err))?;
|
parser.parse_mod(exp!(Eof)).map_err(|err| ModError::ParserError(err))?;
|
||||||
attrs.extend(inner_attrs);
|
attrs.extend(inner_attrs);
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@ use rustc_ast::util::literal::escape_byte_str_symbol;
|
||||||
use rustc_ast_pretty::pprust;
|
use rustc_ast_pretty::pprust;
|
||||||
use rustc_data_structures::fx::FxHashMap;
|
use rustc_data_structures::fx::FxHashMap;
|
||||||
use rustc_errors::{Diag, ErrorGuaranteed, MultiSpan, PResult};
|
use rustc_errors::{Diag, ErrorGuaranteed, MultiSpan, PResult};
|
||||||
use rustc_parse::lexer::nfc_normalize;
|
use rustc_parse::lexer::{StripTokens, nfc_normalize};
|
||||||
use rustc_parse::parser::Parser;
|
use rustc_parse::parser::Parser;
|
||||||
use rustc_parse::{exp, new_parser_from_source_str, source_str_to_stream, unwrap_or_emit_fatal};
|
use rustc_parse::{exp, new_parser_from_source_str, source_str_to_stream, unwrap_or_emit_fatal};
|
||||||
use rustc_proc_macro::bridge::{
|
use rustc_proc_macro::bridge::{
|
||||||
|
|
@ -485,8 +485,13 @@ impl server::FreeFunctions for Rustc<'_, '_> {
|
||||||
|
|
||||||
fn literal_from_str(&mut self, s: &str) -> Result<Literal<Self::Span, Self::Symbol>, ()> {
|
fn literal_from_str(&mut self, s: &str) -> Result<Literal<Self::Span, Self::Symbol>, ()> {
|
||||||
let name = FileName::proc_macro_source_code(s);
|
let name = FileName::proc_macro_source_code(s);
|
||||||
let mut parser =
|
|
||||||
unwrap_or_emit_fatal(new_parser_from_source_str(self.psess(), name, s.to_owned()));
|
let mut parser = unwrap_or_emit_fatal(new_parser_from_source_str(
|
||||||
|
self.psess(),
|
||||||
|
name,
|
||||||
|
s.to_owned(),
|
||||||
|
StripTokens::Nothing,
|
||||||
|
));
|
||||||
|
|
||||||
let first_span = parser.token.span.data();
|
let first_span = parser.token.span.data();
|
||||||
let minus_present = parser.eat(exp!(Minus));
|
let minus_present = parser.eat(exp!(Minus));
|
||||||
|
|
|
||||||
|
|
@ -174,12 +174,6 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
if let Node::TraitItem(item) = node {
|
|
||||||
let mut bounds = Vec::new();
|
|
||||||
icx.lowerer().add_default_trait_item_bounds(item, &mut bounds);
|
|
||||||
predicates.extend(bounds);
|
|
||||||
}
|
|
||||||
|
|
||||||
let generics = tcx.generics_of(def_id);
|
let generics = tcx.generics_of(def_id);
|
||||||
|
|
||||||
// Below we'll consider the bounds on the type parameters (including `Self`)
|
// Below we'll consider the bounds on the type parameters (including `Self`)
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,13 @@
|
||||||
|
use std::assert_matches::assert_matches;
|
||||||
use std::ops::ControlFlow;
|
use std::ops::ControlFlow;
|
||||||
|
|
||||||
use rustc_data_structures::fx::{FxIndexMap, FxIndexSet};
|
use rustc_data_structures::fx::{FxIndexMap, FxIndexSet};
|
||||||
use rustc_errors::codes::*;
|
use rustc_errors::codes::*;
|
||||||
use rustc_errors::struct_span_code_err;
|
use rustc_errors::struct_span_code_err;
|
||||||
use rustc_hir as hir;
|
use rustc_hir as hir;
|
||||||
|
use rustc_hir::PolyTraitRef;
|
||||||
use rustc_hir::def::{DefKind, Res};
|
use rustc_hir::def::{DefKind, Res};
|
||||||
use rustc_hir::def_id::{CRATE_DEF_ID, DefId, LocalDefId};
|
use rustc_hir::def_id::{CRATE_DEF_ID, DefId, LocalDefId};
|
||||||
use rustc_hir::{AmbigArg, PolyTraitRef};
|
|
||||||
use rustc_middle::bug;
|
use rustc_middle::bug;
|
||||||
use rustc_middle::ty::{
|
use rustc_middle::ty::{
|
||||||
self as ty, IsSuggestable, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitableExt,
|
self as ty, IsSuggestable, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitableExt,
|
||||||
|
|
@ -230,122 +231,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Checks whether `Self: DefaultAutoTrait` bounds should be added on trait super bounds
|
/// Adds `experimental_default_bounds` bounds to the supertrait bounds.
|
||||||
/// or associated items.
|
|
||||||
///
|
|
||||||
/// To keep backward compatibility with existing code, `experimental_default_bounds` bounds
|
|
||||||
/// should be added everywhere, including super bounds. However this causes a huge performance
|
|
||||||
/// costs. For optimization purposes instead of adding default supertraits, bounds
|
|
||||||
/// are added to the associated items:
|
|
||||||
///
|
|
||||||
/// ```ignore(illustrative)
|
|
||||||
/// // Default bounds are generated in the following way:
|
|
||||||
/// trait Trait {
|
|
||||||
/// fn foo(&self) where Self: Leak {}
|
|
||||||
/// }
|
|
||||||
///
|
|
||||||
/// // instead of this:
|
|
||||||
/// trait Trait: Leak {
|
|
||||||
/// fn foo(&self) {}
|
|
||||||
/// }
|
|
||||||
/// ```
|
|
||||||
/// It is not always possible to do this because of backward compatibility:
|
|
||||||
///
|
|
||||||
/// ```ignore(illustrative)
|
|
||||||
/// pub trait Trait<Rhs = Self> {}
|
|
||||||
/// pub trait Trait1 : Trait {}
|
|
||||||
/// //~^ ERROR: `Rhs` requires `DefaultAutoTrait`, but `Self` is not `DefaultAutoTrait`
|
|
||||||
/// ```
|
|
||||||
///
|
|
||||||
/// or:
|
|
||||||
///
|
|
||||||
/// ```ignore(illustrative)
|
|
||||||
/// trait Trait {
|
|
||||||
/// type Type where Self: Sized;
|
|
||||||
/// }
|
|
||||||
/// trait Trait2<T> : Trait<Type = T> {}
|
|
||||||
/// //~^ ERROR: `DefaultAutoTrait` required for `Trait2`, by implicit `Self: DefaultAutoTrait` in `Trait::Type`
|
|
||||||
/// ```
|
|
||||||
///
|
|
||||||
/// Therefore, `experimental_default_bounds` are still being added to supertraits if
|
|
||||||
/// the `SelfTyParam` or `AssocItemConstraint` were found in a trait header.
|
|
||||||
fn requires_default_supertraits(
|
|
||||||
&self,
|
|
||||||
hir_bounds: &'tcx [hir::GenericBound<'tcx>],
|
|
||||||
hir_generics: &'tcx hir::Generics<'tcx>,
|
|
||||||
) -> bool {
|
|
||||||
struct TraitInfoCollector;
|
|
||||||
|
|
||||||
impl<'tcx> hir::intravisit::Visitor<'tcx> for TraitInfoCollector {
|
|
||||||
type Result = ControlFlow<()>;
|
|
||||||
|
|
||||||
fn visit_assoc_item_constraint(
|
|
||||||
&mut self,
|
|
||||||
_constraint: &'tcx hir::AssocItemConstraint<'tcx>,
|
|
||||||
) -> Self::Result {
|
|
||||||
ControlFlow::Break(())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn visit_ty(&mut self, t: &'tcx hir::Ty<'tcx, AmbigArg>) -> Self::Result {
|
|
||||||
if matches!(
|
|
||||||
&t.kind,
|
|
||||||
hir::TyKind::Path(hir::QPath::Resolved(
|
|
||||||
_,
|
|
||||||
hir::Path { res: hir::def::Res::SelfTyParam { .. }, .. },
|
|
||||||
))
|
|
||||||
) {
|
|
||||||
return ControlFlow::Break(());
|
|
||||||
}
|
|
||||||
hir::intravisit::walk_ty(self, t)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut found = false;
|
|
||||||
for bound in hir_bounds {
|
|
||||||
found |= hir::intravisit::walk_param_bound(&mut TraitInfoCollector, bound).is_break();
|
|
||||||
}
|
|
||||||
found |= hir::intravisit::walk_generics(&mut TraitInfoCollector, hir_generics).is_break();
|
|
||||||
found
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Implicitly add `Self: DefaultAutoTrait` clauses on trait associated items if
|
|
||||||
/// they are not added as super trait bounds to the trait itself. See
|
|
||||||
/// `requires_default_supertraits` for more information.
|
|
||||||
pub(crate) fn add_default_trait_item_bounds(
|
|
||||||
&self,
|
|
||||||
trait_item: &hir::TraitItem<'tcx>,
|
|
||||||
bounds: &mut Vec<(ty::Clause<'tcx>, Span)>,
|
|
||||||
) {
|
|
||||||
let tcx = self.tcx();
|
|
||||||
if !tcx.sess.opts.unstable_opts.experimental_default_bounds {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
let parent = tcx.local_parent(trait_item.hir_id().owner.def_id);
|
|
||||||
let hir::Node::Item(parent_trait) = tcx.hir_node_by_def_id(parent) else {
|
|
||||||
unreachable!();
|
|
||||||
};
|
|
||||||
|
|
||||||
let (trait_generics, trait_bounds) = match parent_trait.kind {
|
|
||||||
hir::ItemKind::Trait(_, _, _, _, generics, supertraits, _) => (generics, supertraits),
|
|
||||||
hir::ItemKind::TraitAlias(_, generics, supertraits) => (generics, supertraits),
|
|
||||||
_ => unreachable!(),
|
|
||||||
};
|
|
||||||
|
|
||||||
if !self.requires_default_supertraits(trait_bounds, trait_generics) {
|
|
||||||
let self_ty_where_predicates = (parent, trait_item.generics.predicates);
|
|
||||||
self.add_default_traits(
|
|
||||||
bounds,
|
|
||||||
tcx.types.self_param,
|
|
||||||
&[],
|
|
||||||
Some(self_ty_where_predicates),
|
|
||||||
trait_item.span,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Lazily sets `experimental_default_bounds` to true on trait super bounds.
|
|
||||||
/// See `requires_default_supertraits` for more information.
|
|
||||||
pub(crate) fn add_default_super_traits(
|
pub(crate) fn add_default_super_traits(
|
||||||
&self,
|
&self,
|
||||||
trait_def_id: LocalDefId,
|
trait_def_id: LocalDefId,
|
||||||
|
|
@ -354,21 +240,21 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
||||||
hir_generics: &'tcx hir::Generics<'tcx>,
|
hir_generics: &'tcx hir::Generics<'tcx>,
|
||||||
span: Span,
|
span: Span,
|
||||||
) {
|
) {
|
||||||
if !self.tcx().sess.opts.unstable_opts.experimental_default_bounds {
|
assert_matches!(self.tcx().def_kind(trait_def_id), DefKind::Trait | DefKind::TraitAlias);
|
||||||
|
|
||||||
|
// Supertraits for auto trait are unsound according to the unstable book:
|
||||||
|
// https://doc.rust-lang.org/beta/unstable-book/language-features/auto-traits.html#supertraits
|
||||||
|
if self.tcx().trait_is_auto(trait_def_id.to_def_id()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
assert!(matches!(self.tcx().def_kind(trait_def_id), DefKind::Trait | DefKind::TraitAlias));
|
self.add_default_traits(
|
||||||
if self.requires_default_supertraits(hir_bounds, hir_generics) {
|
bounds,
|
||||||
let self_ty_where_predicates = (trait_def_id, hir_generics.predicates);
|
self.tcx().types.self_param,
|
||||||
self.add_default_traits(
|
hir_bounds,
|
||||||
bounds,
|
Some((trait_def_id, hir_generics.predicates)),
|
||||||
self.tcx().types.self_param,
|
span,
|
||||||
hir_bounds,
|
);
|
||||||
Some(self_ty_where_predicates),
|
|
||||||
span,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn add_default_traits(
|
pub(crate) fn add_default_traits(
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,8 @@ use rustc_lint::LintStore;
|
||||||
use rustc_middle::ty;
|
use rustc_middle::ty;
|
||||||
use rustc_middle::ty::CurrentGcx;
|
use rustc_middle::ty::CurrentGcx;
|
||||||
use rustc_middle::util::Providers;
|
use rustc_middle::util::Providers;
|
||||||
use rustc_parse::new_parser_from_simple_source_str;
|
use rustc_parse::lexer::StripTokens;
|
||||||
|
use rustc_parse::new_parser_from_source_str;
|
||||||
use rustc_parse::parser::attr::AllowLeadingUnsafe;
|
use rustc_parse::parser::attr::AllowLeadingUnsafe;
|
||||||
use rustc_query_impl::QueryCtxt;
|
use rustc_query_impl::QueryCtxt;
|
||||||
use rustc_query_system::query::print_query_stack;
|
use rustc_query_system::query::print_query_stack;
|
||||||
|
|
@ -68,7 +69,8 @@ pub(crate) fn parse_cfg(dcx: DiagCtxtHandle<'_>, cfgs: Vec<String>) -> Cfg {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
match new_parser_from_simple_source_str(&psess, filename, s.to_string()) {
|
match new_parser_from_source_str(&psess, filename, s.to_string(), StripTokens::Nothing)
|
||||||
|
{
|
||||||
Ok(mut parser) => match parser.parse_meta_item(AllowLeadingUnsafe::No) {
|
Ok(mut parser) => match parser.parse_meta_item(AllowLeadingUnsafe::No) {
|
||||||
Ok(meta_item) if parser.token == token::Eof => {
|
Ok(meta_item) if parser.token == token::Eof => {
|
||||||
if meta_item.path.segments.len() != 1 {
|
if meta_item.path.segments.len() != 1 {
|
||||||
|
|
@ -166,13 +168,15 @@ pub(crate) fn parse_check_cfg(dcx: DiagCtxtHandle<'_>, specs: Vec<String>) -> Ch
|
||||||
error!("expected `cfg(name, values(\"value1\", \"value2\", ... \"valueN\"))`")
|
error!("expected `cfg(name, values(\"value1\", \"value2\", ... \"valueN\"))`")
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut parser = match new_parser_from_simple_source_str(&psess, filename, s.to_string()) {
|
let mut parser =
|
||||||
Ok(parser) => parser,
|
match new_parser_from_source_str(&psess, filename, s.to_string(), StripTokens::Nothing)
|
||||||
Err(errs) => {
|
{
|
||||||
errs.into_iter().for_each(|err| err.cancel());
|
Ok(parser) => parser,
|
||||||
expected_error();
|
Err(errs) => {
|
||||||
}
|
errs.into_iter().for_each(|err| err.cancel());
|
||||||
};
|
expected_error();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
let meta_item = match parser.parse_meta_item(AllowLeadingUnsafe::No) {
|
let meta_item = match parser.parse_meta_item(AllowLeadingUnsafe::No) {
|
||||||
Ok(meta_item) if parser.token == token::Eof => meta_item,
|
Ok(meta_item) if parser.token == token::Eof => meta_item,
|
||||||
|
|
|
||||||
|
|
@ -28,6 +28,7 @@ use rustc_middle::arena::Arena;
|
||||||
use rustc_middle::dep_graph::DepsType;
|
use rustc_middle::dep_graph::DepsType;
|
||||||
use rustc_middle::ty::{self, CurrentGcx, GlobalCtxt, RegisteredTools, TyCtxt};
|
use rustc_middle::ty::{self, CurrentGcx, GlobalCtxt, RegisteredTools, TyCtxt};
|
||||||
use rustc_middle::util::Providers;
|
use rustc_middle::util::Providers;
|
||||||
|
use rustc_parse::lexer::StripTokens;
|
||||||
use rustc_parse::{new_parser_from_file, new_parser_from_source_str, unwrap_or_emit_fatal};
|
use rustc_parse::{new_parser_from_file, new_parser_from_source_str, unwrap_or_emit_fatal};
|
||||||
use rustc_passes::{abi_test, input_stats, layout_test};
|
use rustc_passes::{abi_test, input_stats, layout_test};
|
||||||
use rustc_resolve::{Resolver, ResolverOutputs};
|
use rustc_resolve::{Resolver, ResolverOutputs};
|
||||||
|
|
@ -52,10 +53,18 @@ pub fn parse<'a>(sess: &'a Session) -> ast::Crate {
|
||||||
let mut krate = sess
|
let mut krate = sess
|
||||||
.time("parse_crate", || {
|
.time("parse_crate", || {
|
||||||
let mut parser = unwrap_or_emit_fatal(match &sess.io.input {
|
let mut parser = unwrap_or_emit_fatal(match &sess.io.input {
|
||||||
Input::File(file) => new_parser_from_file(&sess.psess, file, None),
|
Input::File(file) => new_parser_from_file(
|
||||||
Input::Str { input, name } => {
|
&sess.psess,
|
||||||
new_parser_from_source_str(&sess.psess, name.clone(), input.clone())
|
file,
|
||||||
}
|
StripTokens::ShebangAndFrontmatter,
|
||||||
|
None,
|
||||||
|
),
|
||||||
|
Input::Str { input, name } => new_parser_from_source_str(
|
||||||
|
&sess.psess,
|
||||||
|
name.clone(),
|
||||||
|
input.clone(),
|
||||||
|
StripTokens::ShebangAndFrontmatter,
|
||||||
|
),
|
||||||
});
|
});
|
||||||
parser.parse_crate_mod()
|
parser.parse_crate_mod()
|
||||||
})
|
})
|
||||||
|
|
|
||||||
|
|
@ -47,7 +47,8 @@ impl<'tcx> LateLintPass<'tcx> for MultipleSupertraitUpcastable {
|
||||||
.explicit_super_predicates_of(def_id)
|
.explicit_super_predicates_of(def_id)
|
||||||
.iter_identity_copied()
|
.iter_identity_copied()
|
||||||
.filter_map(|(pred, _)| pred.as_trait_clause())
|
.filter_map(|(pred, _)| pred.as_trait_clause())
|
||||||
.filter(|pred| !cx.tcx.is_lang_item(pred.def_id(), hir::LangItem::MetaSized));
|
.filter(|pred| !cx.tcx.is_lang_item(pred.def_id(), hir::LangItem::MetaSized))
|
||||||
|
.filter(|pred| !cx.tcx.is_default_trait(pred.def_id()));
|
||||||
if direct_super_traits_iter.count() > 1 {
|
if direct_super_traits_iter.count() > 1 {
|
||||||
cx.emit_span_lint(
|
cx.emit_span_lint(
|
||||||
MULTIPLE_SUPERTRAIT_UPCASTABLE,
|
MULTIPLE_SUPERTRAIT_UPCASTABLE,
|
||||||
|
|
|
||||||
|
|
@ -45,7 +45,7 @@ pub(crate) struct UnmatchedDelim {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Which tokens should be stripped before lexing the tokens.
|
/// Which tokens should be stripped before lexing the tokens.
|
||||||
pub(crate) enum StripTokens {
|
pub enum StripTokens {
|
||||||
/// Strip both shebang and frontmatter.
|
/// Strip both shebang and frontmatter.
|
||||||
ShebangAndFrontmatter,
|
ShebangAndFrontmatter,
|
||||||
/// Strip the shebang but not frontmatter.
|
/// Strip the shebang but not frontmatter.
|
||||||
|
|
|
||||||
|
|
@ -54,29 +54,18 @@ pub fn unwrap_or_emit_fatal<T>(expr: Result<T, Vec<Diag<'_>>>) -> T {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Creates a new parser from a source string. On failure, the errors must be consumed via
|
/// Creates a new parser from a source string.
|
||||||
/// `unwrap_or_emit_fatal`, `emit`, `cancel`, etc., otherwise a panic will occur when they are
|
///
|
||||||
/// dropped.
|
/// On failure, the errors must be consumed via `unwrap_or_emit_fatal`, `emit`, `cancel`,
|
||||||
|
/// etc., otherwise a panic will occur when they are dropped.
|
||||||
pub fn new_parser_from_source_str(
|
pub fn new_parser_from_source_str(
|
||||||
psess: &ParseSess,
|
psess: &ParseSess,
|
||||||
name: FileName,
|
name: FileName,
|
||||||
source: String,
|
source: String,
|
||||||
|
strip_tokens: StripTokens,
|
||||||
) -> Result<Parser<'_>, Vec<Diag<'_>>> {
|
) -> Result<Parser<'_>, Vec<Diag<'_>>> {
|
||||||
let source_file = psess.source_map().new_source_file(name, source);
|
let source_file = psess.source_map().new_source_file(name, source);
|
||||||
new_parser_from_source_file(psess, source_file, StripTokens::ShebangAndFrontmatter)
|
new_parser_from_source_file(psess, source_file, strip_tokens)
|
||||||
}
|
|
||||||
|
|
||||||
/// Creates a new parser from a simple (no shebang, no frontmatter) source string.
|
|
||||||
///
|
|
||||||
/// On failure, the errors must be consumed via `unwrap_or_emit_fatal`, `emit`, `cancel`,
|
|
||||||
/// etc., otherwise a panic will occur when they are dropped.
|
|
||||||
pub fn new_parser_from_simple_source_str(
|
|
||||||
psess: &ParseSess,
|
|
||||||
name: FileName,
|
|
||||||
source: String,
|
|
||||||
) -> Result<Parser<'_>, Vec<Diag<'_>>> {
|
|
||||||
let source_file = psess.source_map().new_source_file(name, source);
|
|
||||||
new_parser_from_source_file(psess, source_file, StripTokens::Nothing)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Creates a new parser from a filename. On failure, the errors must be consumed via
|
/// Creates a new parser from a filename. On failure, the errors must be consumed via
|
||||||
|
|
@ -87,6 +76,7 @@ pub fn new_parser_from_simple_source_str(
|
||||||
pub fn new_parser_from_file<'a>(
|
pub fn new_parser_from_file<'a>(
|
||||||
psess: &'a ParseSess,
|
psess: &'a ParseSess,
|
||||||
path: &Path,
|
path: &Path,
|
||||||
|
strip_tokens: StripTokens,
|
||||||
sp: Option<Span>,
|
sp: Option<Span>,
|
||||||
) -> Result<Parser<'a>, Vec<Diag<'a>>> {
|
) -> Result<Parser<'a>, Vec<Diag<'a>>> {
|
||||||
let sm = psess.source_map();
|
let sm = psess.source_map();
|
||||||
|
|
@ -110,7 +100,7 @@ pub fn new_parser_from_file<'a>(
|
||||||
}
|
}
|
||||||
err.emit();
|
err.emit();
|
||||||
});
|
});
|
||||||
new_parser_from_source_file(psess, source_file, StripTokens::ShebangAndFrontmatter)
|
new_parser_from_source_file(psess, source_file, strip_tokens)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn utf8_error<E: EmissionGuarantee>(
|
pub fn utf8_error<E: EmissionGuarantee>(
|
||||||
|
|
@ -172,6 +162,9 @@ fn new_parser_from_source_file(
|
||||||
Ok(parser)
|
Ok(parser)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Given a source string, produces a sequence of token trees.
|
||||||
|
///
|
||||||
|
/// NOTE: This only strips shebangs, not frontmatter!
|
||||||
pub fn source_str_to_stream(
|
pub fn source_str_to_stream(
|
||||||
psess: &ParseSess,
|
psess: &ParseSess,
|
||||||
name: FileName,
|
name: FileName,
|
||||||
|
|
@ -179,13 +172,16 @@ pub fn source_str_to_stream(
|
||||||
override_span: Option<Span>,
|
override_span: Option<Span>,
|
||||||
) -> Result<TokenStream, Vec<Diag<'_>>> {
|
) -> Result<TokenStream, Vec<Diag<'_>>> {
|
||||||
let source_file = psess.source_map().new_source_file(name, source);
|
let source_file = psess.source_map().new_source_file(name, source);
|
||||||
// used mainly for `proc_macro` and the likes, not for our parsing purposes, so don't parse
|
// FIXME(frontmatter): Consider stripping frontmatter in a future edition. We can't strip them
|
||||||
// frontmatters as frontmatters, but for compatibility reason still strip the shebang
|
// in the current edition since that would be breaking.
|
||||||
|
// See also <https://github.com/rust-lang/rust/issues/145520>.
|
||||||
|
// Alternatively, stop stripping shebangs here, too, if T-lang and crater approve.
|
||||||
source_file_to_stream(psess, source_file, override_span, StripTokens::Shebang)
|
source_file_to_stream(psess, source_file, override_span, StripTokens::Shebang)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Given a source file, produces a sequence of token trees. Returns any buffered errors from
|
/// Given a source file, produces a sequence of token trees.
|
||||||
/// parsing the token stream.
|
///
|
||||||
|
/// Returns any buffered errors from parsing the token stream.
|
||||||
fn source_file_to_stream<'psess>(
|
fn source_file_to_stream<'psess>(
|
||||||
psess: &'psess ParseSess,
|
psess: &'psess ParseSess,
|
||||||
source_file: Arc<SourceFile>,
|
source_file: Arc<SourceFile>,
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,7 @@ use rustc_span::{
|
||||||
};
|
};
|
||||||
use termcolor::WriteColor;
|
use termcolor::WriteColor;
|
||||||
|
|
||||||
|
use crate::lexer::StripTokens;
|
||||||
use crate::parser::{ForceCollect, Parser};
|
use crate::parser::{ForceCollect, Parser};
|
||||||
use crate::{new_parser_from_source_str, source_str_to_stream, unwrap_or_emit_fatal};
|
use crate::{new_parser_from_source_str, source_str_to_stream, unwrap_or_emit_fatal};
|
||||||
|
|
||||||
|
|
@ -35,6 +36,7 @@ fn string_to_parser(psess: &ParseSess, source_str: String) -> Parser<'_> {
|
||||||
psess,
|
psess,
|
||||||
PathBuf::from("bogofile").into(),
|
PathBuf::from("bogofile").into(),
|
||||||
source_str,
|
source_str,
|
||||||
|
StripTokens::Nothing,
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -2240,7 +2242,7 @@ fn parse_item_from_source_str(
|
||||||
source: String,
|
source: String,
|
||||||
psess: &ParseSess,
|
psess: &ParseSess,
|
||||||
) -> PResult<'_, Option<Box<ast::Item>>> {
|
) -> PResult<'_, Option<Box<ast::Item>>> {
|
||||||
unwrap_or_emit_fatal(new_parser_from_source_str(psess, name, source))
|
unwrap_or_emit_fatal(new_parser_from_source_str(psess, name, source, StripTokens::Nothing))
|
||||||
.parse_item(ForceCollect::No)
|
.parse_item(ForceCollect::No)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -2520,7 +2522,8 @@ fn ttdelim_span() {
|
||||||
source: String,
|
source: String,
|
||||||
psess: &ParseSess,
|
psess: &ParseSess,
|
||||||
) -> PResult<'_, Box<ast::Expr>> {
|
) -> PResult<'_, Box<ast::Expr>> {
|
||||||
unwrap_or_emit_fatal(new_parser_from_source_str(psess, name, source)).parse_expr()
|
unwrap_or_emit_fatal(new_parser_from_source_str(psess, name, source, StripTokens::Nothing))
|
||||||
|
.parse_expr()
|
||||||
}
|
}
|
||||||
|
|
||||||
create_default_session_globals_then(|| {
|
create_default_session_globals_then(|| {
|
||||||
|
|
|
||||||
|
|
@ -21,18 +21,17 @@ mod tests;
|
||||||
|
|
||||||
// The proc macro code for this is in `compiler/rustc_macros/src/symbols.rs`.
|
// The proc macro code for this is in `compiler/rustc_macros/src/symbols.rs`.
|
||||||
symbols! {
|
symbols! {
|
||||||
// This list includes things that are definitely keywords (e.g. `if`),
|
// This list includes things that are definitely keywords (e.g. `if`), a
|
||||||
// a few things that are definitely not keywords (e.g. the empty symbol,
|
// few things that are definitely not keywords (e.g. `{{root}}`) and things
|
||||||
// `{{root}}`) and things where there is disagreement between people and/or
|
// where there is disagreement between people and/or documents (such as the
|
||||||
// documents (such as the Rust Reference) about whether it is a keyword
|
// Rust Reference) about whether it is a keyword (e.g. `_`).
|
||||||
// (e.g. `_`).
|
|
||||||
//
|
//
|
||||||
// If you modify this list, adjust any relevant `Symbol::{is,can_be}_*`
|
// If you modify this list, adjust any relevant `Symbol::{is,can_be}_*`
|
||||||
// predicates and `used_keywords`. Also consider adding new keywords to the
|
// predicates and `used_keywords`. Also consider adding new keywords to the
|
||||||
// `ui/parser/raw/raw-idents.rs` test.
|
// `ui/parser/raw/raw-idents.rs` test.
|
||||||
Keywords {
|
Keywords {
|
||||||
// Special reserved identifiers used internally for elided lifetimes,
|
// Special reserved identifiers used internally for unnamed method
|
||||||
// unnamed method parameters, crate root module, error recovery etc.
|
// parameters, crate root module, etc.
|
||||||
// Matching predicates: `is_special`/`is_reserved`
|
// Matching predicates: `is_special`/`is_reserved`
|
||||||
//
|
//
|
||||||
// tidy-alphabetical-start
|
// tidy-alphabetical-start
|
||||||
|
|
|
||||||
|
|
@ -95,6 +95,9 @@ impl Error {
|
||||||
|
|
||||||
pub(crate) const ZERO_TIMEOUT: Self =
|
pub(crate) const ZERO_TIMEOUT: Self =
|
||||||
const_error!(ErrorKind::InvalidInput, "cannot set a 0 duration timeout");
|
const_error!(ErrorKind::InvalidInput, "cannot set a 0 duration timeout");
|
||||||
|
|
||||||
|
pub(crate) const NO_ADDRESSES: Self =
|
||||||
|
const_error!(ErrorKind::InvalidInput, "could not resolve to any addresses");
|
||||||
}
|
}
|
||||||
|
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
|
|
|
||||||
|
|
@ -34,7 +34,6 @@ pub use self::tcp::IntoIncoming;
|
||||||
pub use self::tcp::{Incoming, TcpListener, TcpStream};
|
pub use self::tcp::{Incoming, TcpListener, TcpStream};
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
pub use self::udp::UdpSocket;
|
pub use self::udp::UdpSocket;
|
||||||
use crate::io::{self, ErrorKind};
|
|
||||||
|
|
||||||
mod ip_addr;
|
mod ip_addr;
|
||||||
mod socket_addr;
|
mod socket_addr;
|
||||||
|
|
@ -67,23 +66,3 @@ pub enum Shutdown {
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
Both,
|
Both,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn each_addr<A: ToSocketAddrs, F, T>(addr: A, mut f: F) -> io::Result<T>
|
|
||||||
where
|
|
||||||
F: FnMut(io::Result<&SocketAddr>) -> io::Result<T>,
|
|
||||||
{
|
|
||||||
let addrs = match addr.to_socket_addrs() {
|
|
||||||
Ok(addrs) => addrs,
|
|
||||||
Err(e) => return f(Err(e)),
|
|
||||||
};
|
|
||||||
let mut last_err = None;
|
|
||||||
for addr in addrs {
|
|
||||||
match f(Ok(&addr)) {
|
|
||||||
Ok(l) => return Ok(l),
|
|
||||||
Err(e) => last_err = Some(e),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Err(last_err.unwrap_or_else(|| {
|
|
||||||
io::const_error!(ErrorKind::InvalidInput, "could not resolve to any addresses")
|
|
||||||
}))
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -167,7 +167,7 @@ impl TcpStream {
|
||||||
/// ```
|
/// ```
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
pub fn connect<A: ToSocketAddrs>(addr: A) -> io::Result<TcpStream> {
|
pub fn connect<A: ToSocketAddrs>(addr: A) -> io::Result<TcpStream> {
|
||||||
super::each_addr(addr, net_imp::TcpStream::connect).map(TcpStream)
|
net_imp::TcpStream::connect(addr).map(TcpStream)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Opens a TCP connection to a remote host with a timeout.
|
/// Opens a TCP connection to a remote host with a timeout.
|
||||||
|
|
@ -782,7 +782,7 @@ impl TcpListener {
|
||||||
/// ```
|
/// ```
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
pub fn bind<A: ToSocketAddrs>(addr: A) -> io::Result<TcpListener> {
|
pub fn bind<A: ToSocketAddrs>(addr: A) -> io::Result<TcpListener> {
|
||||||
super::each_addr(addr, net_imp::TcpListener::bind).map(TcpListener)
|
net_imp::TcpListener::bind(addr).map(TcpListener)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the local socket address of this listener.
|
/// Returns the local socket address of this listener.
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
use crate::io::prelude::*;
|
use crate::io::prelude::*;
|
||||||
use crate::io::{BorrowedBuf, IoSlice, IoSliceMut};
|
use crate::io::{BorrowedBuf, ErrorKind, IoSlice, IoSliceMut};
|
||||||
use crate::mem::MaybeUninit;
|
use crate::mem::MaybeUninit;
|
||||||
use crate::net::test::{next_test_ip4, next_test_ip6};
|
use crate::net::test::{next_test_ip4, next_test_ip6};
|
||||||
use crate::net::*;
|
use crate::net::*;
|
||||||
|
|
|
||||||
|
|
@ -120,7 +120,7 @@ impl UdpSocket {
|
||||||
/// [`Ipv4Addr::UNSPECIFIED`] or [`Ipv6Addr::UNSPECIFIED`].
|
/// [`Ipv4Addr::UNSPECIFIED`] or [`Ipv6Addr::UNSPECIFIED`].
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
pub fn bind<A: ToSocketAddrs>(addr: A) -> io::Result<UdpSocket> {
|
pub fn bind<A: ToSocketAddrs>(addr: A) -> io::Result<UdpSocket> {
|
||||||
super::each_addr(addr, net_imp::UdpSocket::bind).map(UdpSocket)
|
net_imp::UdpSocket::bind(addr).map(UdpSocket)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Receives a single datagram message on the socket. On success, returns the number
|
/// Receives a single datagram message on the socket. On success, returns the number
|
||||||
|
|
@ -677,7 +677,7 @@ impl UdpSocket {
|
||||||
/// on the platform.
|
/// on the platform.
|
||||||
#[stable(feature = "net2_mutators", since = "1.9.0")]
|
#[stable(feature = "net2_mutators", since = "1.9.0")]
|
||||||
pub fn connect<A: ToSocketAddrs>(&self, addr: A) -> io::Result<()> {
|
pub fn connect<A: ToSocketAddrs>(&self, addr: A) -> io::Result<()> {
|
||||||
super::each_addr(addr, |addr| self.0.connect(addr))
|
self.0.connect(addr)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Sends data on the socket to the remote address to which it is connected.
|
/// Sends data on the socket to the remote address to which it is connected.
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
use crate::io::ErrorKind;
|
||||||
use crate::net::test::{compare_ignore_zoneid, next_test_ip4, next_test_ip6};
|
use crate::net::test::{compare_ignore_zoneid, next_test_ip4, next_test_ip6};
|
||||||
use crate::net::*;
|
use crate::net::*;
|
||||||
use crate::sync::mpsc::channel;
|
use crate::sync::mpsc::channel;
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
use crate::fmt;
|
use crate::fmt;
|
||||||
|
use crate::panic::RefUnwindSafe;
|
||||||
use crate::sync::nonpoison::{Condvar, Mutex};
|
use crate::sync::nonpoison::{Condvar, Mutex};
|
||||||
|
|
||||||
/// A barrier enables multiple threads to synchronize the beginning
|
/// A barrier enables multiple threads to synchronize the beginning
|
||||||
|
|
@ -31,6 +32,9 @@ pub struct Barrier {
|
||||||
num_threads: usize,
|
num_threads: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[stable(feature = "unwind_safe_lock_refs", since = "1.12.0")]
|
||||||
|
impl RefUnwindSafe for Barrier {}
|
||||||
|
|
||||||
// The inner state of a double barrier
|
// The inner state of a double barrier
|
||||||
struct BarrierState {
|
struct BarrierState {
|
||||||
count: usize,
|
count: usize,
|
||||||
|
|
|
||||||
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::io::{self, BorrowedCursor, IoSlice, IoSliceMut};
|
||||||
use crate::net::{Ipv4Addr, Ipv6Addr, Shutdown, SocketAddr, ToSocketAddrs};
|
use crate::net::{Ipv4Addr, Ipv6Addr, Shutdown, SocketAddr, ToSocketAddrs};
|
||||||
use crate::sync::Arc;
|
use crate::sync::Arc;
|
||||||
|
|
@ -5,7 +7,6 @@ use crate::sys::abi::usercalls;
|
||||||
use crate::sys::fd::FileDesc;
|
use crate::sys::fd::FileDesc;
|
||||||
use crate::sys::{AsInner, FromInner, IntoInner, TryIntoInner, sgx_ineffective, unsupported};
|
use crate::sys::{AsInner, FromInner, IntoInner, TryIntoInner, sgx_ineffective, unsupported};
|
||||||
use crate::time::Duration;
|
use crate::time::Duration;
|
||||||
use crate::{error, fmt};
|
|
||||||
|
|
||||||
const DEFAULT_FAKE_TTL: u32 = 64;
|
const DEFAULT_FAKE_TTL: u32 = 64;
|
||||||
|
|
||||||
|
|
@ -63,18 +64,52 @@ impl fmt::Debug for TcpStream {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn io_err_to_addr(result: io::Result<&SocketAddr>) -> io::Result<String> {
|
/// Converts each address in `addr` into a hostname.
|
||||||
match result {
|
///
|
||||||
Ok(saddr) => Ok(saddr.to_string()),
|
/// SGX doesn't support DNS resolution but rather accepts hostnames in
|
||||||
// need to downcast twice because io::Error::into_inner doesn't return the original
|
/// the same place as socket addresses. So, to make e.g.
|
||||||
// value if the conversion fails
|
/// ```rust
|
||||||
Err(e) => {
|
/// TcpStream::connect("example.com:80")`
|
||||||
if e.get_ref().and_then(|e| e.downcast_ref::<NonIpSockAddr>()).is_some() {
|
/// ```
|
||||||
Ok(e.into_inner().unwrap().downcast::<NonIpSockAddr>().unwrap().host)
|
/// work, the DNS lookup returns a special error (`NonIpSockAddr`) instead,
|
||||||
} else {
|
/// which contains the hostname being looked up. When `.to_socket_addrs()`
|
||||||
Err(e)
|
/// fails, we inspect the error and try recover the hostname from it. If that
|
||||||
|
/// succeeds, we thus continue with the hostname.
|
||||||
|
///
|
||||||
|
/// This is a terrible hack and leads to buggy code. For instance, when users
|
||||||
|
/// use the result of `.to_socket_addrs()` in their own `ToSocketAddrs`
|
||||||
|
/// implementation to select from a list of possible URLs, the only URL used
|
||||||
|
/// will be that of the last item tried.
|
||||||
|
// FIXME: This is a terrible, terrible hack. Fixing this requires Fortanix to
|
||||||
|
// add a method for resolving addresses.
|
||||||
|
fn each_addr<A: ToSocketAddrs, F, T>(addr: A, mut f: F) -> io::Result<T>
|
||||||
|
where
|
||||||
|
F: FnMut(&str) -> io::Result<T>,
|
||||||
|
{
|
||||||
|
match addr.to_socket_addrs() {
|
||||||
|
Ok(addrs) => {
|
||||||
|
let mut last_err = None;
|
||||||
|
let mut encoded = String::new();
|
||||||
|
for addr in addrs {
|
||||||
|
// Format the IP address as a string, reusing the buffer.
|
||||||
|
encoded.clear();
|
||||||
|
write!(encoded, "{}", &addr).unwrap();
|
||||||
|
|
||||||
|
match f(&encoded) {
|
||||||
|
Ok(val) => return Ok(val),
|
||||||
|
Err(err) => last_err = Some(err),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
match last_err {
|
||||||
|
Some(err) => Err(err),
|
||||||
|
None => Err(io::Error::NO_ADDRESSES),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Err(err) => match err.get_ref().and_then(|e| e.downcast_ref::<NonIpSockAddr>()) {
|
||||||
|
Some(NonIpSockAddr { host }) => f(host),
|
||||||
|
None => Err(err),
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -86,17 +121,18 @@ fn addr_to_sockaddr(addr: Option<&str>) -> io::Result<SocketAddr> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TcpStream {
|
impl TcpStream {
|
||||||
pub fn connect(addr: io::Result<&SocketAddr>) -> io::Result<TcpStream> {
|
pub fn connect<A: ToSocketAddrs>(addr: A) -> io::Result<TcpStream> {
|
||||||
let addr = io_err_to_addr(addr)?;
|
each_addr(addr, |addr| {
|
||||||
let (fd, local_addr, peer_addr) = usercalls::connect_stream(&addr)?;
|
let (fd, local_addr, peer_addr) = usercalls::connect_stream(addr)?;
|
||||||
Ok(TcpStream { inner: Socket::new(fd, local_addr), peer_addr: Some(peer_addr) })
|
Ok(TcpStream { inner: Socket::new(fd, local_addr), peer_addr: Some(peer_addr) })
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn connect_timeout(addr: &SocketAddr, dur: Duration) -> io::Result<TcpStream> {
|
pub fn connect_timeout(addr: &SocketAddr, dur: Duration) -> io::Result<TcpStream> {
|
||||||
if dur == Duration::default() {
|
if dur == Duration::default() {
|
||||||
return Err(io::Error::ZERO_TIMEOUT);
|
return Err(io::Error::ZERO_TIMEOUT);
|
||||||
}
|
}
|
||||||
Self::connect(Ok(addr)) // FIXME: ignoring timeout
|
Self::connect(addr) // FIXME: ignoring timeout
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_read_timeout(&self, dur: Option<Duration>) -> io::Result<()> {
|
pub fn set_read_timeout(&self, dur: Option<Duration>) -> io::Result<()> {
|
||||||
|
|
@ -247,10 +283,11 @@ impl fmt::Debug for TcpListener {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TcpListener {
|
impl TcpListener {
|
||||||
pub fn bind(addr: io::Result<&SocketAddr>) -> io::Result<TcpListener> {
|
pub fn bind<A: ToSocketAddrs>(addr: A) -> io::Result<TcpListener> {
|
||||||
let addr = io_err_to_addr(addr)?;
|
each_addr(addr, |addr| {
|
||||||
let (fd, local_addr) = usercalls::bind_stream(&addr)?;
|
let (fd, local_addr) = usercalls::bind_stream(addr)?;
|
||||||
Ok(TcpListener { inner: Socket::new(fd, local_addr) })
|
Ok(TcpListener { inner: Socket::new(fd, local_addr) })
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn socket_addr(&self) -> io::Result<SocketAddr> {
|
pub fn socket_addr(&self) -> io::Result<SocketAddr> {
|
||||||
|
|
@ -316,7 +353,7 @@ impl FromInner<Socket> for TcpListener {
|
||||||
pub struct UdpSocket(!);
|
pub struct UdpSocket(!);
|
||||||
|
|
||||||
impl UdpSocket {
|
impl UdpSocket {
|
||||||
pub fn bind(_: io::Result<&SocketAddr>) -> io::Result<UdpSocket> {
|
pub fn bind<A: ToSocketAddrs>(_: A) -> io::Result<UdpSocket> {
|
||||||
unsupported()
|
unsupported()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -436,7 +473,7 @@ impl UdpSocket {
|
||||||
self.0
|
self.0
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn connect(&self, _: io::Result<&SocketAddr>) -> io::Result<()> {
|
pub fn connect<A: ToSocketAddrs>(&self, _: A) -> io::Result<()> {
|
||||||
self.0
|
self.0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,8 +3,11 @@ mod tests;
|
||||||
|
|
||||||
use crate::ffi::{c_int, c_void};
|
use crate::ffi::{c_int, c_void};
|
||||||
use crate::io::{self, BorrowedCursor, ErrorKind, IoSlice, IoSliceMut};
|
use crate::io::{self, BorrowedCursor, ErrorKind, IoSlice, IoSliceMut};
|
||||||
use crate::net::{Ipv4Addr, Ipv6Addr, Shutdown, SocketAddr, SocketAddrV4, SocketAddrV6};
|
use crate::net::{
|
||||||
|
Ipv4Addr, Ipv6Addr, Shutdown, SocketAddr, SocketAddrV4, SocketAddrV6, ToSocketAddrs,
|
||||||
|
};
|
||||||
use crate::sys::common::small_c_string::run_with_cstr;
|
use crate::sys::common::small_c_string::run_with_cstr;
|
||||||
|
use crate::sys::net::connection::each_addr;
|
||||||
use crate::sys_common::{AsInner, FromInner};
|
use crate::sys_common::{AsInner, FromInner};
|
||||||
use crate::time::Duration;
|
use crate::time::Duration;
|
||||||
use crate::{cmp, fmt, mem, ptr};
|
use crate::{cmp, fmt, mem, ptr};
|
||||||
|
|
@ -342,14 +345,15 @@ pub struct TcpStream {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TcpStream {
|
impl TcpStream {
|
||||||
pub fn connect(addr: io::Result<&SocketAddr>) -> io::Result<TcpStream> {
|
pub fn connect<A: ToSocketAddrs>(addr: A) -> io::Result<TcpStream> {
|
||||||
let addr = addr?;
|
|
||||||
|
|
||||||
init();
|
init();
|
||||||
|
return each_addr(addr, inner);
|
||||||
|
|
||||||
let sock = Socket::new(addr, c::SOCK_STREAM)?;
|
fn inner(addr: &SocketAddr) -> io::Result<TcpStream> {
|
||||||
sock.connect(addr)?;
|
let sock = Socket::new(addr, c::SOCK_STREAM)?;
|
||||||
Ok(TcpStream { inner: sock })
|
sock.connect(addr)?;
|
||||||
|
Ok(TcpStream { inner: sock })
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn connect_timeout(addr: &SocketAddr, timeout: Duration) -> io::Result<TcpStream> {
|
pub fn connect_timeout(addr: &SocketAddr, timeout: Duration) -> io::Result<TcpStream> {
|
||||||
|
|
@ -512,48 +516,45 @@ pub struct TcpListener {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TcpListener {
|
impl TcpListener {
|
||||||
pub fn bind(addr: io::Result<&SocketAddr>) -> io::Result<TcpListener> {
|
pub fn bind<A: ToSocketAddrs>(addr: A) -> io::Result<TcpListener> {
|
||||||
let addr = addr?;
|
|
||||||
|
|
||||||
init();
|
init();
|
||||||
|
return each_addr(addr, inner);
|
||||||
|
|
||||||
let sock = Socket::new(addr, c::SOCK_STREAM)?;
|
fn inner(addr: &SocketAddr) -> io::Result<TcpListener> {
|
||||||
|
let sock = Socket::new(addr, c::SOCK_STREAM)?;
|
||||||
|
|
||||||
// On platforms with Berkeley-derived sockets, this allows to quickly
|
// On platforms with Berkeley-derived sockets, this allows to quickly
|
||||||
// rebind a socket, without needing to wait for the OS to clean up the
|
// rebind a socket, without needing to wait for the OS to clean up the
|
||||||
// previous one.
|
// previous one.
|
||||||
//
|
//
|
||||||
// On Windows, this allows rebinding sockets which are actively in use,
|
// On Windows, this allows rebinding sockets which are actively in use,
|
||||||
// which allows “socket hijacking”, so we explicitly don't set it here.
|
// which allows “socket hijacking”, so we explicitly don't set it here.
|
||||||
// https://docs.microsoft.com/en-us/windows/win32/winsock/using-so-reuseaddr-and-so-exclusiveaddruse
|
// https://docs.microsoft.com/en-us/windows/win32/winsock/using-so-reuseaddr-and-so-exclusiveaddruse
|
||||||
#[cfg(not(windows))]
|
#[cfg(not(windows))]
|
||||||
setsockopt(&sock, c::SOL_SOCKET, c::SO_REUSEADDR, 1 as c_int)?;
|
setsockopt(&sock, c::SOL_SOCKET, c::SO_REUSEADDR, 1 as c_int)?;
|
||||||
|
|
||||||
// Bind our new socket
|
// Bind our new socket
|
||||||
let (addr, len) = socket_addr_to_c(addr);
|
let (addr, len) = socket_addr_to_c(addr);
|
||||||
cvt(unsafe { c::bind(sock.as_raw(), addr.as_ptr(), len as _) })?;
|
cvt(unsafe { c::bind(sock.as_raw(), addr.as_ptr(), len as _) })?;
|
||||||
|
|
||||||
cfg_select! {
|
let backlog = if cfg!(target_os = "horizon") {
|
||||||
target_os = "horizon" => {
|
|
||||||
// The 3DS doesn't support a big connection backlog. Sometimes
|
// The 3DS doesn't support a big connection backlog. Sometimes
|
||||||
// it allows up to about 37, but other times it doesn't even
|
// it allows up to about 37, but other times it doesn't even
|
||||||
// accept 32. There may be a global limitation causing this.
|
// accept 32. There may be a global limitation causing this.
|
||||||
let backlog = 20;
|
20
|
||||||
}
|
} else if cfg!(target_os = "haiku") {
|
||||||
target_os = "haiku" => {
|
|
||||||
// Haiku does not support a queue length > 32
|
// Haiku does not support a queue length > 32
|
||||||
// https://github.com/haiku/haiku/blob/979a0bc487864675517fb2fab28f87dc8bf43041/headers/posix/sys/socket.h#L81
|
// https://github.com/haiku/haiku/blob/979a0bc487864675517fb2fab28f87dc8bf43041/headers/posix/sys/socket.h#L81
|
||||||
let backlog = 32;
|
32
|
||||||
}
|
} else {
|
||||||
_ => {
|
|
||||||
// The default for all other platforms
|
// The default for all other platforms
|
||||||
let backlog = 128;
|
128
|
||||||
}
|
};
|
||||||
}
|
|
||||||
|
|
||||||
// Start listening
|
// Start listening
|
||||||
cvt(unsafe { c::listen(sock.as_raw(), backlog) })?;
|
cvt(unsafe { c::listen(sock.as_raw(), backlog) })?;
|
||||||
Ok(TcpListener { inner: sock })
|
Ok(TcpListener { inner: sock })
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
|
|
@ -639,15 +640,16 @@ pub struct UdpSocket {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl UdpSocket {
|
impl UdpSocket {
|
||||||
pub fn bind(addr: io::Result<&SocketAddr>) -> io::Result<UdpSocket> {
|
pub fn bind<A: ToSocketAddrs>(addr: A) -> io::Result<UdpSocket> {
|
||||||
let addr = addr?;
|
|
||||||
|
|
||||||
init();
|
init();
|
||||||
|
return each_addr(addr, inner);
|
||||||
|
|
||||||
let sock = Socket::new(addr, c::SOCK_DGRAM)?;
|
fn inner(addr: &SocketAddr) -> io::Result<UdpSocket> {
|
||||||
let (addr, len) = socket_addr_to_c(addr);
|
let sock = Socket::new(addr, c::SOCK_DGRAM)?;
|
||||||
cvt(unsafe { c::bind(sock.as_raw(), addr.as_ptr(), len as _) })?;
|
let (addr, len) = socket_addr_to_c(addr);
|
||||||
Ok(UdpSocket { inner: sock })
|
cvt(unsafe { c::bind(sock.as_raw(), addr.as_ptr(), len as _) })?;
|
||||||
|
Ok(UdpSocket { inner: sock })
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
|
|
@ -822,9 +824,13 @@ impl UdpSocket {
|
||||||
Ok(ret as usize)
|
Ok(ret as usize)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn connect(&self, addr: io::Result<&SocketAddr>) -> io::Result<()> {
|
pub fn connect<A: ToSocketAddrs>(&self, addr: A) -> io::Result<()> {
|
||||||
let (addr, len) = socket_addr_to_c(addr?);
|
return each_addr(addr, |addr| inner(self, addr));
|
||||||
cvt_r(|| unsafe { c::connect(self.inner.as_raw(), addr.as_ptr(), len) }).map(drop)
|
|
||||||
|
fn inner(this: &UdpSocket, addr: &SocketAddr) -> io::Result<()> {
|
||||||
|
let (addr, len) = socket_addr_to_c(addr);
|
||||||
|
cvt_r(|| unsafe { c::connect(this.inner.as_raw(), addr.as_ptr(), len) }).map(drop)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
|
use super::each_addr;
|
||||||
use crate::fmt;
|
use crate::fmt;
|
||||||
use crate::io::{self, BorrowedCursor, IoSlice, IoSliceMut};
|
use crate::io::{self, BorrowedCursor, IoSlice, IoSliceMut};
|
||||||
use crate::net::{Ipv4Addr, Ipv6Addr, Shutdown, SocketAddr};
|
use crate::net::{Ipv4Addr, Ipv6Addr, Shutdown, SocketAddr, ToSocketAddrs};
|
||||||
use crate::sync::{Arc, Mutex};
|
use crate::sync::{Arc, Mutex};
|
||||||
use crate::sys::unsupported;
|
use crate::sys::unsupported;
|
||||||
use crate::time::Duration;
|
use crate::time::Duration;
|
||||||
|
|
@ -15,13 +16,17 @@ pub struct TcpStream {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TcpStream {
|
impl TcpStream {
|
||||||
pub fn connect(addr: io::Result<&SocketAddr>) -> io::Result<TcpStream> {
|
pub fn connect<A: ToSocketAddrs>(addr: A) -> io::Result<TcpStream> {
|
||||||
let inner = tcp::Tcp::connect(addr?, None)?;
|
return each_addr(addr, inner);
|
||||||
Ok(Self {
|
|
||||||
inner,
|
fn inner(addr: &SocketAddr) -> io::Result<TcpStream> {
|
||||||
read_timeout: Arc::new(Mutex::new(None)),
|
let inner = tcp::Tcp::connect(addr, None)?;
|
||||||
write_timeout: Arc::new(Mutex::new(None)),
|
Ok(TcpStream {
|
||||||
})
|
inner,
|
||||||
|
read_timeout: Arc::new(Mutex::new(None)),
|
||||||
|
write_timeout: Arc::new(Mutex::new(None)),
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn connect_timeout(addr: &SocketAddr, timeout: Duration) -> io::Result<TcpStream> {
|
pub fn connect_timeout(addr: &SocketAddr, timeout: Duration) -> io::Result<TcpStream> {
|
||||||
|
|
@ -145,7 +150,7 @@ pub struct TcpListener {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TcpListener {
|
impl TcpListener {
|
||||||
pub fn bind(_: io::Result<&SocketAddr>) -> io::Result<TcpListener> {
|
pub fn bind<A: ToSocketAddrs>(_: A) -> io::Result<TcpListener> {
|
||||||
unsupported()
|
unsupported()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -195,7 +200,7 @@ impl fmt::Debug for TcpListener {
|
||||||
pub struct UdpSocket(!);
|
pub struct UdpSocket(!);
|
||||||
|
|
||||||
impl UdpSocket {
|
impl UdpSocket {
|
||||||
pub fn bind(_: io::Result<&SocketAddr>) -> io::Result<UdpSocket> {
|
pub fn bind<A: ToSocketAddrs>(_: A) -> io::Result<UdpSocket> {
|
||||||
unsupported()
|
unsupported()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -315,7 +320,7 @@ impl UdpSocket {
|
||||||
self.0
|
self.0
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn connect(&self, _: io::Result<&SocketAddr>) -> io::Result<()> {
|
pub fn connect<A: ToSocketAddrs>(&self, _: A) -> io::Result<()> {
|
||||||
self.0
|
self.0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,13 @@
|
||||||
use crate::fmt;
|
use crate::fmt;
|
||||||
use crate::io::{self, BorrowedCursor, IoSlice, IoSliceMut};
|
use crate::io::{self, BorrowedCursor, IoSlice, IoSliceMut};
|
||||||
use crate::net::{Ipv4Addr, Ipv6Addr, Shutdown, SocketAddr};
|
use crate::net::{Ipv4Addr, Ipv6Addr, Shutdown, SocketAddr, ToSocketAddrs};
|
||||||
use crate::sys::unsupported;
|
use crate::sys::unsupported;
|
||||||
use crate::time::Duration;
|
use crate::time::Duration;
|
||||||
|
|
||||||
pub struct TcpStream(!);
|
pub struct TcpStream(!);
|
||||||
|
|
||||||
impl TcpStream {
|
impl TcpStream {
|
||||||
pub fn connect(_: io::Result<&SocketAddr>) -> io::Result<TcpStream> {
|
pub fn connect<A: ToSocketAddrs>(_: A) -> io::Result<TcpStream> {
|
||||||
unsupported()
|
unsupported()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -121,7 +121,7 @@ impl fmt::Debug for TcpStream {
|
||||||
pub struct TcpListener(!);
|
pub struct TcpListener(!);
|
||||||
|
|
||||||
impl TcpListener {
|
impl TcpListener {
|
||||||
pub fn bind(_: io::Result<&SocketAddr>) -> io::Result<TcpListener> {
|
pub fn bind<A: ToSocketAddrs>(_: A) -> io::Result<TcpListener> {
|
||||||
unsupported()
|
unsupported()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -171,7 +171,7 @@ impl fmt::Debug for TcpListener {
|
||||||
pub struct UdpSocket(!);
|
pub struct UdpSocket(!);
|
||||||
|
|
||||||
impl UdpSocket {
|
impl UdpSocket {
|
||||||
pub fn bind(_: io::Result<&SocketAddr>) -> io::Result<UdpSocket> {
|
pub fn bind<A: ToSocketAddrs>(_: A) -> io::Result<UdpSocket> {
|
||||||
unsupported()
|
unsupported()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -291,7 +291,7 @@ impl UdpSocket {
|
||||||
self.0
|
self.0
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn connect(&self, _: io::Result<&SocketAddr>) -> io::Result<()> {
|
pub fn connect<A: ToSocketAddrs>(&self, _: A) -> io::Result<()> {
|
||||||
self.0
|
self.0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
use crate::fmt;
|
use crate::fmt;
|
||||||
use crate::io::{self, BorrowedCursor, IoSlice, IoSliceMut};
|
use crate::io::{self, BorrowedCursor, IoSlice, IoSliceMut};
|
||||||
use crate::net::{Ipv4Addr, Ipv6Addr, Shutdown, SocketAddr};
|
use crate::net::{Ipv4Addr, Ipv6Addr, Shutdown, SocketAddr, ToSocketAddrs};
|
||||||
use crate::os::wasi::io::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, RawFd};
|
use crate::os::wasi::io::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, RawFd};
|
||||||
use crate::sys::fd::WasiFd;
|
use crate::sys::fd::WasiFd;
|
||||||
use crate::sys::{err2io, unsupported};
|
use crate::sys::{err2io, unsupported};
|
||||||
|
|
@ -60,7 +60,7 @@ impl FromRawFd for Socket {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TcpStream {
|
impl TcpStream {
|
||||||
pub fn connect(_: io::Result<&SocketAddr>) -> io::Result<TcpStream> {
|
pub fn connect<A: ToSocketAddrs>(_: A) -> io::Result<TcpStream> {
|
||||||
unsupported()
|
unsupported()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -212,7 +212,7 @@ pub struct TcpListener {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TcpListener {
|
impl TcpListener {
|
||||||
pub fn bind(_: io::Result<&SocketAddr>) -> io::Result<TcpListener> {
|
pub fn bind<A: ToSocketAddrs>(_: A) -> io::Result<TcpListener> {
|
||||||
unsupported()
|
unsupported()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -316,7 +316,7 @@ pub struct UdpSocket {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl UdpSocket {
|
impl UdpSocket {
|
||||||
pub fn bind(_: io::Result<&SocketAddr>) -> io::Result<UdpSocket> {
|
pub fn bind<A: ToSocketAddrs>(_: A) -> io::Result<UdpSocket> {
|
||||||
unsupported()
|
unsupported()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -436,7 +436,7 @@ impl UdpSocket {
|
||||||
unsupported()
|
unsupported()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn connect(&self, _: io::Result<&SocketAddr>) -> io::Result<()> {
|
pub fn connect<A: ToSocketAddrs>(&self, _: A) -> io::Result<()> {
|
||||||
unsupported()
|
unsupported()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,9 +2,10 @@ use core::convert::TryInto;
|
||||||
use core::sync::atomic::{Atomic, AtomicBool, AtomicU16, AtomicUsize, Ordering};
|
use core::sync::atomic::{Atomic, AtomicBool, AtomicU16, AtomicUsize, Ordering};
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr};
|
use crate::net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr, ToSocketAddrs};
|
||||||
use crate::os::xous::services;
|
use crate::os::xous::services;
|
||||||
use crate::sync::Arc;
|
use crate::sync::Arc;
|
||||||
|
use crate::sys::net::connection::each_addr;
|
||||||
use crate::{fmt, io};
|
use crate::{fmt, io};
|
||||||
|
|
||||||
macro_rules! unimpl {
|
macro_rules! unimpl {
|
||||||
|
|
@ -25,16 +26,19 @@ pub struct TcpListener {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TcpListener {
|
impl TcpListener {
|
||||||
pub fn bind(socketaddr: io::Result<&SocketAddr>) -> io::Result<TcpListener> {
|
pub fn bind<A: ToSocketAddrs>(addr: A) -> io::Result<TcpListener> {
|
||||||
let mut addr = *socketaddr?;
|
return each_addr(addr, inner);
|
||||||
|
|
||||||
let fd = TcpListener::bind_inner(&mut addr)?;
|
fn inner(addr: &SocketAddr) -> io::Result<TcpListener> {
|
||||||
return Ok(TcpListener {
|
let mut addr = *addr;
|
||||||
fd: Arc::new(AtomicU16::new(fd)),
|
let fd = TcpListener::bind_inner(&mut addr)?;
|
||||||
local: addr,
|
Ok(TcpListener {
|
||||||
handle_count: Arc::new(AtomicUsize::new(1)),
|
fd: Arc::new(AtomicU16::new(fd)),
|
||||||
nonblocking: Arc::new(AtomicBool::new(false)),
|
local: addr,
|
||||||
});
|
handle_count: Arc::new(AtomicUsize::new(1)),
|
||||||
|
nonblocking: Arc::new(AtomicBool::new(false)),
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// This returns the raw fd of a Listener, so that it can also be used by the
|
/// This returns the raw fd of a Listener, so that it can also be used by the
|
||||||
|
|
|
||||||
|
|
@ -3,9 +3,12 @@ use core::sync::atomic::{Atomic, AtomicBool, AtomicU32, AtomicUsize, Ordering};
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::fmt;
|
use crate::fmt;
|
||||||
use crate::io::{self, BorrowedCursor, IoSlice, IoSliceMut};
|
use crate::io::{self, BorrowedCursor, IoSlice, IoSliceMut};
|
||||||
use crate::net::{IpAddr, Ipv4Addr, Shutdown, SocketAddr, SocketAddrV4, SocketAddrV6};
|
use crate::net::{
|
||||||
|
IpAddr, Ipv4Addr, Shutdown, SocketAddr, SocketAddrV4, SocketAddrV6, ToSocketAddrs,
|
||||||
|
};
|
||||||
use crate::os::xous::services;
|
use crate::os::xous::services;
|
||||||
use crate::sync::Arc;
|
use crate::sync::Arc;
|
||||||
|
use crate::sys::net::connection::each_addr;
|
||||||
use crate::time::Duration;
|
use crate::time::Duration;
|
||||||
|
|
||||||
macro_rules! unimpl {
|
macro_rules! unimpl {
|
||||||
|
|
@ -79,8 +82,8 @@ impl TcpStream {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn connect(socketaddr: io::Result<&SocketAddr>) -> io::Result<TcpStream> {
|
pub fn connect<A: ToSocketAddrs>(addr: A) -> io::Result<TcpStream> {
|
||||||
Self::connect_timeout(socketaddr?, Duration::ZERO)
|
each_addr(addr, |addr| Self::connect_timeout(addr, Duration::ZERO))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn connect_timeout(addr: &SocketAddr, duration: Duration) -> io::Result<TcpStream> {
|
pub fn connect_timeout(addr: &SocketAddr, duration: Duration) -> io::Result<TcpStream> {
|
||||||
|
|
|
||||||
|
|
@ -3,9 +3,10 @@ use core::sync::atomic::{Atomic, AtomicUsize, Ordering};
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::cell::Cell;
|
use crate::cell::Cell;
|
||||||
use crate::net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr};
|
use crate::net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr, ToSocketAddrs};
|
||||||
use crate::os::xous::services;
|
use crate::os::xous::services;
|
||||||
use crate::sync::Arc;
|
use crate::sync::Arc;
|
||||||
|
use crate::sys::net::connection::each_addr;
|
||||||
use crate::time::Duration;
|
use crate::time::Duration;
|
||||||
use crate::{fmt, io};
|
use crate::{fmt, io};
|
||||||
|
|
||||||
|
|
@ -32,40 +33,45 @@ pub struct UdpSocket {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl UdpSocket {
|
impl UdpSocket {
|
||||||
pub fn bind(socketaddr: io::Result<&SocketAddr>) -> io::Result<UdpSocket> {
|
pub fn bind<A: ToSocketAddrs>(addr: A) -> io::Result<UdpSocket> {
|
||||||
let addr = socketaddr?;
|
return each_addr(addr, inner);
|
||||||
// Construct the request
|
|
||||||
let mut connect_request = ConnectRequest { raw: [0u8; 4096] };
|
|
||||||
|
|
||||||
// Serialize the StdUdpBind structure. This is done "manually" because we don't want to
|
fn inner(addr: &SocketAddr) -> io::Result<UdpSocket> {
|
||||||
// make an auto-serdes (like bincode or rkyv) crate a dependency of Xous.
|
// Construct the request
|
||||||
let port_bytes = addr.port().to_le_bytes();
|
let mut connect_request = ConnectRequest { raw: [0u8; 4096] };
|
||||||
connect_request.raw[0] = port_bytes[0];
|
|
||||||
connect_request.raw[1] = port_bytes[1];
|
// Serialize the StdUdpBind structure. This is done "manually" because we don't want to
|
||||||
match addr.ip() {
|
// make an auto-serdes (like bincode or rkyv) crate a dependency of Xous.
|
||||||
IpAddr::V4(addr) => {
|
let port_bytes = addr.port().to_le_bytes();
|
||||||
connect_request.raw[2] = 4;
|
connect_request.raw[0] = port_bytes[0];
|
||||||
for (dest, src) in connect_request.raw[3..].iter_mut().zip(addr.octets()) {
|
connect_request.raw[1] = port_bytes[1];
|
||||||
*dest = src;
|
match addr.ip() {
|
||||||
|
IpAddr::V4(addr) => {
|
||||||
|
connect_request.raw[2] = 4;
|
||||||
|
for (dest, src) in connect_request.raw[3..].iter_mut().zip(addr.octets()) {
|
||||||
|
*dest = src;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
IpAddr::V6(addr) => {
|
||||||
|
connect_request.raw[2] = 6;
|
||||||
|
for (dest, src) in connect_request.raw[3..].iter_mut().zip(addr.octets()) {
|
||||||
|
*dest = src;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
IpAddr::V6(addr) => {
|
|
||||||
connect_request.raw[2] = 6;
|
|
||||||
for (dest, src) in connect_request.raw[3..].iter_mut().zip(addr.octets()) {
|
|
||||||
*dest = src;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let response = crate::os::xous::ffi::lend_mut(
|
let response = crate::os::xous::ffi::lend_mut(
|
||||||
services::net_server(),
|
services::net_server(),
|
||||||
services::NetLendMut::StdUdpBind.into(),
|
services::NetLendMut::StdUdpBind.into(),
|
||||||
&mut connect_request.raw,
|
&mut connect_request.raw,
|
||||||
0,
|
0,
|
||||||
4096,
|
4096,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
let Ok((_, valid)) = response else {
|
||||||
|
return Err(io::const_error!(io::ErrorKind::InvalidInput, "invalid response"));
|
||||||
|
};
|
||||||
|
|
||||||
if let Ok((_, valid)) = response {
|
|
||||||
// The first four bytes should be zero upon success, and will be nonzero
|
// The first four bytes should be zero upon success, and will be nonzero
|
||||||
// for an error.
|
// for an error.
|
||||||
let response = connect_request.raw;
|
let response = connect_request.raw;
|
||||||
|
|
@ -87,8 +93,9 @@ impl UdpSocket {
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let fd = response[1] as u16;
|
let fd = response[1] as u16;
|
||||||
return Ok(UdpSocket {
|
Ok(UdpSocket {
|
||||||
fd,
|
fd,
|
||||||
local: *addr,
|
local: *addr,
|
||||||
remote: Cell::new(None),
|
remote: Cell::new(None),
|
||||||
|
|
@ -96,9 +103,8 @@ impl UdpSocket {
|
||||||
write_timeout: Cell::new(0),
|
write_timeout: Cell::new(0),
|
||||||
handle_count: Arc::new(AtomicUsize::new(1)),
|
handle_count: Arc::new(AtomicUsize::new(1)),
|
||||||
nonblocking: Cell::new(false),
|
nonblocking: Cell::new(false),
|
||||||
});
|
})
|
||||||
}
|
}
|
||||||
Err(io::const_error!(io::ErrorKind::InvalidInput, "invalid response"))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn peer_addr(&self) -> io::Result<SocketAddr> {
|
pub fn peer_addr(&self) -> io::Result<SocketAddr> {
|
||||||
|
|
@ -198,10 +204,11 @@ impl UdpSocket {
|
||||||
self.peek_from(buf).map(|(len, _addr)| len)
|
self.peek_from(buf).map(|(len, _addr)| len)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn connect(&self, maybe_addr: io::Result<&SocketAddr>) -> io::Result<()> {
|
pub fn connect<A: ToSocketAddrs>(&self, addr: A) -> io::Result<()> {
|
||||||
let addr = maybe_addr?;
|
each_addr(addr, |addr| {
|
||||||
self.remote.set(Some(*addr));
|
self.remote.set(Some(*addr));
|
||||||
Ok(())
|
Ok(())
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn send(&self, buf: &[u8]) -> io::Result<usize> {
|
pub fn send(&self, buf: &[u8]) -> io::Result<usize> {
|
||||||
|
|
|
||||||
|
|
@ -1,46 +1,4 @@
|
||||||
cfg_select! {
|
/// This module contains the implementations of `TcpStream`, `TcpListener` and
|
||||||
any(
|
/// `UdpSocket` as well as related functionality like DNS resolving.
|
||||||
all(target_family = "unix", not(target_os = "l4re")),
|
mod connection;
|
||||||
target_os = "windows",
|
|
||||||
target_os = "hermit",
|
|
||||||
all(target_os = "wasi", target_env = "p2"),
|
|
||||||
target_os = "solid_asp3",
|
|
||||||
) => {
|
|
||||||
mod connection {
|
|
||||||
mod socket;
|
|
||||||
pub use socket::*;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
all(target_vendor = "fortanix", target_env = "sgx") => {
|
|
||||||
mod connection {
|
|
||||||
mod sgx;
|
|
||||||
pub use sgx::*;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
all(target_os = "wasi", target_env = "p1") => {
|
|
||||||
mod connection {
|
|
||||||
mod wasip1;
|
|
||||||
pub use wasip1::*;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
target_os = "xous" => {
|
|
||||||
mod connection {
|
|
||||||
mod xous;
|
|
||||||
pub use xous::*;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
target_os = "uefi" => {
|
|
||||||
mod connection {
|
|
||||||
mod uefi;
|
|
||||||
pub use uefi::*;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => {
|
|
||||||
mod connection {
|
|
||||||
mod unsupported;
|
|
||||||
pub use unsupported::*;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub use connection::*;
|
pub use connection::*;
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
use std::panic::RefUnwindSafe;
|
||||||
use std::sync::mpsc::{TryRecvError, channel};
|
use std::sync::mpsc::{TryRecvError, channel};
|
||||||
use std::sync::{Arc, Barrier};
|
use std::sync::{Arc, Barrier};
|
||||||
use std::thread;
|
use std::thread;
|
||||||
|
|
@ -33,3 +34,11 @@ fn test_barrier() {
|
||||||
}
|
}
|
||||||
assert!(leader_found);
|
assert!(leader_found);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Asserts that `Barrier` is ref unwind safe.
|
||||||
|
///
|
||||||
|
/// See <https://github.com/rust-lang/rust/issues/146087>.
|
||||||
|
const _: () = {
|
||||||
|
const fn check_ref_unwind_safe<T: RefUnwindSafe>() {}
|
||||||
|
check_ref_unwind_safe::<Barrier>();
|
||||||
|
};
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@ use rustc_ast::tokenstream::{TokenStream, TokenTree};
|
||||||
use rustc_ast_pretty::pprust::PrintState;
|
use rustc_ast_pretty::pprust::PrintState;
|
||||||
use rustc_ast_pretty::pprust::state::State as Printer;
|
use rustc_ast_pretty::pprust::state::State as Printer;
|
||||||
use rustc_middle::ty::TyCtxt;
|
use rustc_middle::ty::TyCtxt;
|
||||||
|
use rustc_parse::lexer::StripTokens;
|
||||||
use rustc_session::parse::ParseSess;
|
use rustc_session::parse::ParseSess;
|
||||||
use rustc_span::symbol::{Ident, Symbol, kw};
|
use rustc_span::symbol::{Ident, Symbol, kw};
|
||||||
use rustc_span::{FileName, Span};
|
use rustc_span::{FileName, Span};
|
||||||
|
|
@ -64,14 +65,18 @@ fn snippet_equal_to_token(tcx: TyCtxt<'_>, matcher: &TokenTree) -> Option<String
|
||||||
// Create a Parser.
|
// Create a Parser.
|
||||||
let psess = ParseSess::new(rustc_driver::DEFAULT_LOCALE_RESOURCES.to_vec());
|
let psess = ParseSess::new(rustc_driver::DEFAULT_LOCALE_RESOURCES.to_vec());
|
||||||
let file_name = FileName::macro_expansion_source_code(&snippet);
|
let file_name = FileName::macro_expansion_source_code(&snippet);
|
||||||
let mut parser =
|
let mut parser = match rustc_parse::new_parser_from_source_str(
|
||||||
match rustc_parse::new_parser_from_source_str(&psess, file_name, snippet.clone()) {
|
&psess,
|
||||||
Ok(parser) => parser,
|
file_name,
|
||||||
Err(errs) => {
|
snippet.clone(),
|
||||||
errs.into_iter().for_each(|err| err.cancel());
|
StripTokens::Nothing,
|
||||||
return None;
|
) {
|
||||||
}
|
Ok(parser) => parser,
|
||||||
};
|
Err(errs) => {
|
||||||
|
errs.into_iter().for_each(|err| err.cancel());
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
// Reparse a single token tree.
|
// Reparse a single token tree.
|
||||||
if parser.token == token::Eof {
|
if parser.token == token::Eof {
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@ use rustc_ast::tokenstream::TokenTree;
|
||||||
use rustc_ast::{self as ast, AttrStyle, HasAttrs, StmtKind};
|
use rustc_ast::{self as ast, AttrStyle, HasAttrs, StmtKind};
|
||||||
use rustc_errors::emitter::stderr_destination;
|
use rustc_errors::emitter::stderr_destination;
|
||||||
use rustc_errors::{ColorConfig, DiagCtxtHandle};
|
use rustc_errors::{ColorConfig, DiagCtxtHandle};
|
||||||
|
use rustc_parse::lexer::StripTokens;
|
||||||
use rustc_parse::new_parser_from_source_str;
|
use rustc_parse::new_parser_from_source_str;
|
||||||
use rustc_session::parse::ParseSess;
|
use rustc_session::parse::ParseSess;
|
||||||
use rustc_span::edition::{DEFAULT_EDITION, Edition};
|
use rustc_span::edition::{DEFAULT_EDITION, Edition};
|
||||||
|
|
@ -468,14 +469,16 @@ fn parse_source(
|
||||||
let dcx = DiagCtxt::new(Box::new(emitter)).disable_warnings();
|
let dcx = DiagCtxt::new(Box::new(emitter)).disable_warnings();
|
||||||
let psess = ParseSess::with_dcx(dcx, sm);
|
let psess = ParseSess::with_dcx(dcx, sm);
|
||||||
|
|
||||||
let mut parser = match new_parser_from_source_str(&psess, filename, wrapped_source) {
|
// Don't strip any tokens; it wouldn't matter anyway because the source is wrapped in a function.
|
||||||
Ok(p) => p,
|
let mut parser =
|
||||||
Err(errs) => {
|
match new_parser_from_source_str(&psess, filename, wrapped_source, StripTokens::Nothing) {
|
||||||
errs.into_iter().for_each(|err| err.cancel());
|
Ok(p) => p,
|
||||||
reset_error_count(&psess);
|
Err(errs) => {
|
||||||
return Err(());
|
errs.into_iter().for_each(|err| err.cancel());
|
||||||
}
|
reset_error_count(&psess);
|
||||||
};
|
return Err(());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
fn push_to_s(s: &mut String, source: &str, span: rustc_span::Span, prev_span_hi: &mut usize) {
|
fn push_to_s(s: &mut String, source: &str, span: rustc_span::Span, prev_span_hi: &mut usize) {
|
||||||
let extra_len = DOCTEST_CODE_WRAPPER.len();
|
let extra_len = DOCTEST_CODE_WRAPPER.len();
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,7 @@ use rustc_ast::{CoroutineKind, Fn, FnRetTy, Item, ItemKind};
|
||||||
use rustc_errors::emitter::HumanEmitter;
|
use rustc_errors::emitter::HumanEmitter;
|
||||||
use rustc_errors::{Diag, DiagCtxt};
|
use rustc_errors::{Diag, DiagCtxt};
|
||||||
use rustc_lint::LateContext;
|
use rustc_lint::LateContext;
|
||||||
|
use rustc_parse::lexer::StripTokens;
|
||||||
use rustc_parse::new_parser_from_source_str;
|
use rustc_parse::new_parser_from_source_str;
|
||||||
use rustc_parse::parser::ForceCollect;
|
use rustc_parse::parser::ForceCollect;
|
||||||
use rustc_session::parse::ParseSess;
|
use rustc_session::parse::ParseSess;
|
||||||
|
|
@ -49,13 +50,14 @@ pub fn check(
|
||||||
let sm = Arc::new(SourceMap::new(FilePathMapping::empty()));
|
let sm = Arc::new(SourceMap::new(FilePathMapping::empty()));
|
||||||
let psess = ParseSess::with_dcx(dcx, sm);
|
let psess = ParseSess::with_dcx(dcx, sm);
|
||||||
|
|
||||||
let mut parser = match new_parser_from_source_str(&psess, filename, code) {
|
let mut parser =
|
||||||
Ok(p) => p,
|
match new_parser_from_source_str(&psess, filename, code, StripTokens::ShebangAndFrontmatter) {
|
||||||
Err(errs) => {
|
Ok(p) => p,
|
||||||
errs.into_iter().for_each(Diag::cancel);
|
Err(errs) => {
|
||||||
return (false, test_attr_spans);
|
errs.into_iter().for_each(Diag::cancel);
|
||||||
},
|
return (false, test_attr_spans);
|
||||||
};
|
},
|
||||||
|
};
|
||||||
|
|
||||||
let mut relevant_main_found = false;
|
let mut relevant_main_found = false;
|
||||||
let mut eligible = true;
|
let mut eligible = true;
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@ use std::path::{Path, PathBuf};
|
||||||
|
|
||||||
use rustc_ast::{ast, attr};
|
use rustc_ast::{ast, attr};
|
||||||
use rustc_errors::Diag;
|
use rustc_errors::Diag;
|
||||||
|
use rustc_parse::lexer::StripTokens;
|
||||||
use rustc_parse::parser::Parser as RawParser;
|
use rustc_parse::parser::Parser as RawParser;
|
||||||
use rustc_parse::{exp, new_parser_from_file, new_parser_from_source_str, unwrap_or_emit_fatal};
|
use rustc_parse::{exp, new_parser_from_file, new_parser_from_source_str, unwrap_or_emit_fatal};
|
||||||
use rustc_span::{Span, sym};
|
use rustc_span::{Span, sym};
|
||||||
|
|
@ -64,11 +65,14 @@ impl<'a> ParserBuilder<'a> {
|
||||||
input: Input,
|
input: Input,
|
||||||
) -> Result<RawParser<'a>, Vec<Diag<'a>>> {
|
) -> Result<RawParser<'a>, Vec<Diag<'a>>> {
|
||||||
match input {
|
match input {
|
||||||
Input::File(ref file) => new_parser_from_file(psess, file, None),
|
Input::File(ref file) => {
|
||||||
|
new_parser_from_file(psess, file, StripTokens::ShebangAndFrontmatter, None)
|
||||||
|
}
|
||||||
Input::Text(text) => new_parser_from_source_str(
|
Input::Text(text) => new_parser_from_source_str(
|
||||||
psess,
|
psess,
|
||||||
rustc_span::FileName::Custom("stdin".to_owned()),
|
rustc_span::FileName::Custom("stdin".to_owned()),
|
||||||
text,
|
text,
|
||||||
|
StripTokens::ShebangAndFrontmatter,
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -104,8 +108,12 @@ impl<'a> Parser<'a> {
|
||||||
span: Span,
|
span: Span,
|
||||||
) -> Result<(ast::AttrVec, ThinVec<Box<ast::Item>>, Span), ParserError> {
|
) -> Result<(ast::AttrVec, ThinVec<Box<ast::Item>>, Span), ParserError> {
|
||||||
let result = catch_unwind(AssertUnwindSafe(|| {
|
let result = catch_unwind(AssertUnwindSafe(|| {
|
||||||
let mut parser =
|
let mut parser = unwrap_or_emit_fatal(new_parser_from_file(
|
||||||
unwrap_or_emit_fatal(new_parser_from_file(psess.inner(), path, Some(span)));
|
psess.inner(),
|
||||||
|
path,
|
||||||
|
StripTokens::ShebangAndFrontmatter,
|
||||||
|
Some(span),
|
||||||
|
));
|
||||||
match parser.parse_mod(exp!(Eof)) {
|
match parser.parse_mod(exp!(Eof)) {
|
||||||
Ok((a, i, spans)) => Some((a, i, spans.inner_span)),
|
Ok((a, i, spans)) => Some((a, i, spans.inner_span)),
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@ extern crate rustc_span;
|
||||||
use rustc_ast::ast::{AttrKind, Attribute, DUMMY_NODE_ID, Expr};
|
use rustc_ast::ast::{AttrKind, Attribute, DUMMY_NODE_ID, Expr};
|
||||||
use rustc_ast::mut_visit::{self, MutVisitor};
|
use rustc_ast::mut_visit::{self, MutVisitor};
|
||||||
use rustc_ast::node_id::NodeId;
|
use rustc_ast::node_id::NodeId;
|
||||||
use rustc_ast::token::{self, Token};
|
use rustc_ast::token;
|
||||||
use rustc_ast::tokenstream::{AttrTokenStream, AttrTokenTree, LazyAttrTokenStream};
|
use rustc_ast::tokenstream::{AttrTokenStream, AttrTokenTree, LazyAttrTokenStream};
|
||||||
use rustc_errors::Diag;
|
use rustc_errors::Diag;
|
||||||
use rustc_parse::parser::Recovery;
|
use rustc_parse::parser::Recovery;
|
||||||
|
|
@ -23,6 +23,7 @@ pub fn parse_expr(psess: &ParseSess, source_code: &str) -> Option<Box<Expr>> {
|
||||||
psess,
|
psess,
|
||||||
FileName::anon_source_code(source_code),
|
FileName::anon_source_code(source_code),
|
||||||
source_code.to_owned(),
|
source_code.to_owned(),
|
||||||
|
rustc_parse::lexer::StripTokens::Nothing,
|
||||||
));
|
));
|
||||||
|
|
||||||
let mut parser = parser.recovery(Recovery::Forbidden);
|
let mut parser = parser.recovery(Recovery::Forbidden);
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,7 @@ extern crate rustc_span;
|
||||||
#[allow(unused_extern_crates)]
|
#[allow(unused_extern_crates)]
|
||||||
extern crate rustc_driver;
|
extern crate rustc_driver;
|
||||||
|
|
||||||
use rustc_parse::{new_parser_from_file, unwrap_or_emit_fatal};
|
use rustc_parse::{lexer::StripTokens, new_parser_from_file, unwrap_or_emit_fatal};
|
||||||
use rustc_session::parse::ParseSess;
|
use rustc_session::parse::ParseSess;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
|
|
||||||
|
|
@ -34,6 +34,11 @@ fn parse() {
|
||||||
|
|
||||||
let path = Path::new(file!());
|
let path = Path::new(file!());
|
||||||
let path = path.canonicalize().unwrap();
|
let path = path.canonicalize().unwrap();
|
||||||
let mut parser = unwrap_or_emit_fatal(new_parser_from_file(&psess, &path, None));
|
let mut parser = unwrap_or_emit_fatal(new_parser_from_file(
|
||||||
|
&psess,
|
||||||
|
&path,
|
||||||
|
StripTokens::ShebangAndFrontmatter,
|
||||||
|
None,
|
||||||
|
));
|
||||||
let _ = parser.parse_crate_mod();
|
let _ = parser.parse_crate_mod();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,6 @@ fn ordering4 < 'a , 'b > ( a : , self , self , self ,
|
||||||
//~| ERROR unexpected `self` parameter in function
|
//~| ERROR unexpected `self` parameter in function
|
||||||
//~| ERROR unexpected `self` parameter in function
|
//~| ERROR unexpected `self` parameter in function
|
||||||
//~| ERROR `...` must be the last argument of a C-variadic function
|
//~| ERROR `...` must be the last argument of a C-variadic function
|
||||||
//~| ERROR defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention
|
//~| ERROR `...` is not supported for non-extern functions
|
||||||
//~| ERROR cannot find type `F` in this scope
|
//~| ERROR cannot find type `F` in this scope
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -46,11 +46,13 @@ error: `...` must be the last argument of a C-variadic function
|
||||||
LL | self , ... , self , self , ... ) where F : FnOnce ( & 'a & 'b usize ) {
|
LL | self , ... , self , self , ... ) where F : FnOnce ( & 'a & 'b usize ) {
|
||||||
| ^^^
|
| ^^^
|
||||||
|
|
||||||
error: defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention
|
error: `...` is not supported for non-extern functions
|
||||||
--> $DIR/issue-86053-1.rs:11:36
|
--> $DIR/issue-86053-1.rs:11:36
|
||||||
|
|
|
|
||||||
LL | self , ... , self , self , ... ) where F : FnOnce ( & 'a & 'b usize ) {
|
LL | self , ... , self , self , ... ) where F : FnOnce ( & 'a & 'b usize ) {
|
||||||
| ^^^
|
| ^^^
|
||||||
|
|
|
||||||
|
= help: only `extern "C"` and `extern "C-unwind"` functions may have a C variable argument list
|
||||||
|
|
||||||
error[E0412]: cannot find type `F` in this scope
|
error[E0412]: cannot find type `F` in this scope
|
||||||
--> $DIR/issue-86053-1.rs:11:48
|
--> $DIR/issue-86053-1.rs:11:48
|
||||||
|
|
|
||||||
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
|
x
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "cmse-nonsecure-entry" fn static_trait_object(
|
extern "cmse-nonsecure-entry" fn static_trait_object(x: &'static dyn Trait) -> &'static dyn Trait {
|
||||||
x: &'static dyn Trait,
|
|
||||||
) -> &'static dyn Trait {
|
|
||||||
//~^ ERROR return value of `"cmse-nonsecure-entry"` function too large to pass via registers [E0798]
|
//~^ ERROR return value of `"cmse-nonsecure-entry"` function too large to pass via registers [E0798]
|
||||||
x
|
x
|
||||||
}
|
}
|
||||||
|
|
@ -63,14 +61,12 @@ extern "cmse-nonsecure-entry" fn static_trait_object(
|
||||||
#[repr(transparent)]
|
#[repr(transparent)]
|
||||||
struct WrapperTransparent<'a>(&'a dyn Trait);
|
struct WrapperTransparent<'a>(&'a dyn Trait);
|
||||||
|
|
||||||
extern "cmse-nonsecure-entry" fn wrapped_trait_object(
|
extern "cmse-nonsecure-entry" fn wrapped_trait_object(x: WrapperTransparent) -> WrapperTransparent {
|
||||||
x: WrapperTransparent,
|
|
||||||
) -> WrapperTransparent {
|
|
||||||
//~^ ERROR return value of `"cmse-nonsecure-entry"` function too large to pass via registers [E0798]
|
//~^ ERROR return value of `"cmse-nonsecure-entry"` function too large to pass via registers [E0798]
|
||||||
x
|
x
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "cmse-nonsecure-entry" fn c_variadic(_: u32, _: ...) {
|
unsafe extern "cmse-nonsecure-entry" fn c_variadic(_: u32, _: ...) {
|
||||||
//~^ ERROR defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention
|
//~^ ERROR `...` is not supported for `extern "cmse-nonsecure-entry"` functions
|
||||||
//~| ERROR requires `va_list` lang_item
|
//~| ERROR requires `va_list` lang_item
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,12 @@
|
||||||
error: defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention
|
error: `...` is not supported for `extern "cmse-nonsecure-entry"` functions
|
||||||
--> $DIR/generics.rs:73:53
|
--> $DIR/generics.rs:69:60
|
||||||
|
|
|
|
||||||
LL | extern "cmse-nonsecure-entry" fn c_variadic(_: u32, _: ...) {
|
LL | unsafe extern "cmse-nonsecure-entry" fn c_variadic(_: u32, _: ...) {
|
||||||
| ^^^^^^
|
| ----------------------------- ^^^^^^
|
||||||
|
| |
|
||||||
|
| `extern "cmse-nonsecure-entry"` because of this
|
||||||
|
|
|
||||||
|
= help: only `extern "C"` and `extern "C-unwind"` functions may have a C variable argument list
|
||||||
|
|
||||||
error[E0798]: functions with the `"cmse-nonsecure-entry"` ABI cannot contain generics in their type
|
error[E0798]: functions with the `"cmse-nonsecure-entry"` ABI cannot contain generics in their type
|
||||||
--> $DIR/generics.rs:30:1
|
--> $DIR/generics.rs:30:1
|
||||||
|
|
@ -50,28 +54,28 @@ LL | extern "cmse-nonsecure-entry" fn trait_object(x: &dyn Trait) -> &dyn Trait
|
||||||
= note: the result must either be a (transparently wrapped) i64, u64 or f64, or be at most 4 bytes in size
|
= note: the result must either be a (transparently wrapped) i64, u64 or f64, or be at most 4 bytes in size
|
||||||
|
|
||||||
error[E0798]: return value of `"cmse-nonsecure-entry"` function too large to pass via registers
|
error[E0798]: return value of `"cmse-nonsecure-entry"` function too large to pass via registers
|
||||||
--> $DIR/generics.rs:58:6
|
--> $DIR/generics.rs:56:80
|
||||||
|
|
|
|
||||||
LL | ) -> &'static dyn Trait {
|
LL | extern "cmse-nonsecure-entry" fn static_trait_object(x: &'static dyn Trait) -> &'static dyn Trait {
|
||||||
| ^^^^^^^^^^^^^^^^^^ this type doesn't fit in the available registers
|
| ^^^^^^^^^^^^^^^^^^ this type doesn't fit in the available registers
|
||||||
|
|
|
|
||||||
= note: functions with the `"cmse-nonsecure-entry"` ABI must pass their result via the available return registers
|
= note: functions with the `"cmse-nonsecure-entry"` ABI must pass their result via the available return registers
|
||||||
= note: the result must either be a (transparently wrapped) i64, u64 or f64, or be at most 4 bytes in size
|
= note: the result must either be a (transparently wrapped) i64, u64 or f64, or be at most 4 bytes in size
|
||||||
|
|
||||||
error[E0798]: return value of `"cmse-nonsecure-entry"` function too large to pass via registers
|
error[E0798]: return value of `"cmse-nonsecure-entry"` function too large to pass via registers
|
||||||
--> $DIR/generics.rs:68:6
|
--> $DIR/generics.rs:64:81
|
||||||
|
|
|
|
||||||
LL | ) -> WrapperTransparent {
|
LL | extern "cmse-nonsecure-entry" fn wrapped_trait_object(x: WrapperTransparent) -> WrapperTransparent {
|
||||||
| ^^^^^^^^^^^^^^^^^^ this type doesn't fit in the available registers
|
| ^^^^^^^^^^^^^^^^^^ this type doesn't fit in the available registers
|
||||||
|
|
|
|
||||||
= note: functions with the `"cmse-nonsecure-entry"` ABI must pass their result via the available return registers
|
= note: functions with the `"cmse-nonsecure-entry"` ABI must pass their result via the available return registers
|
||||||
= note: the result must either be a (transparently wrapped) i64, u64 or f64, or be at most 4 bytes in size
|
= note: the result must either be a (transparently wrapped) i64, u64 or f64, or be at most 4 bytes in size
|
||||||
|
|
||||||
error: requires `va_list` lang_item
|
error: requires `va_list` lang_item
|
||||||
--> $DIR/generics.rs:73:53
|
--> $DIR/generics.rs:69:60
|
||||||
|
|
|
|
||||||
LL | extern "cmse-nonsecure-entry" fn c_variadic(_: u32, _: ...) {
|
LL | unsafe extern "cmse-nonsecure-entry" fn c_variadic(_: u32, _: ...) {
|
||||||
| ^^^^^^
|
| ^^^^^^
|
||||||
|
|
||||||
error: aborting due to 9 previous errors
|
error: aborting due to 9 previous errors
|
||||||
|
|
||||||
|
|
|
||||||
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
|
//~^ ERROR C-variadic functions are unstable
|
||||||
|
|
||||||
trait Trait {
|
trait Trait {
|
||||||
unsafe extern "C" fn trait_test(_: i32, ap: ...) { }
|
unsafe extern "C" fn trait_test(_: i32, ap: ...) {}
|
||||||
//~^ ERROR C-variadic functions are unstable
|
//~^ ERROR C-variadic functions are unstable
|
||||||
//~| ERROR defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention
|
//~| ERROR associated functions cannot have a C variable argument list
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,14 +1,14 @@
|
||||||
error: defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention
|
error: associated functions cannot have a C variable argument list
|
||||||
--> $DIR/feature-gate-c_variadic.rs:7:45
|
--> $DIR/feature-gate-c_variadic.rs:7:45
|
||||||
|
|
|
|
||||||
LL | unsafe extern "C" fn trait_test(_: i32, ap: ...) { }
|
LL | unsafe extern "C" fn trait_test(_: i32, ap: ...) {}
|
||||||
| ^^^^^^^
|
| ^^^^^^^
|
||||||
|
|
||||||
error[E0658]: C-variadic functions are unstable
|
error[E0658]: C-variadic functions are unstable
|
||||||
--> $DIR/feature-gate-c_variadic.rs:3:1
|
--> $DIR/feature-gate-c_variadic.rs:3:1
|
||||||
|
|
|
|
||||||
LL | pub unsafe extern "C" fn test(_: i32, ap: ...) { }
|
LL | pub unsafe extern "C" fn test(_: i32, ap: ...) {}
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
|
||||||
= note: see issue #44930 <https://github.com/rust-lang/rust/issues/44930> for more information
|
= note: see issue #44930 <https://github.com/rust-lang/rust/issues/44930> for more information
|
||||||
= help: add `#![feature(c_variadic)]` to the crate attributes to enable
|
= help: add `#![feature(c_variadic)]` to the crate attributes to enable
|
||||||
|
|
@ -17,8 +17,8 @@ LL | pub unsafe extern "C" fn test(_: i32, ap: ...) { }
|
||||||
error[E0658]: C-variadic functions are unstable
|
error[E0658]: C-variadic functions are unstable
|
||||||
--> $DIR/feature-gate-c_variadic.rs:7:5
|
--> $DIR/feature-gate-c_variadic.rs:7:5
|
||||||
|
|
|
|
||||||
LL | unsafe extern "C" fn trait_test(_: i32, ap: ...) { }
|
LL | unsafe extern "C" fn trait_test(_: i32, ap: ...) {}
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
|
||||||
= note: see issue #44930 <https://github.com/rust-lang/rust/issues/44930> for more information
|
= note: see issue #44930 <https://github.com/rust-lang/rust/issues/44930> for more information
|
||||||
= help: add `#![feature(c_variadic)]` to the crate attributes to enable
|
= help: add `#![feature(c_variadic)]` to the crate attributes to enable
|
||||||
|
|
|
||||||
|
|
@ -62,6 +62,11 @@ LL | format!("", 1, 2);
|
||||||
| | |
|
| | |
|
||||||
| | argument never used
|
| | argument never used
|
||||||
| multiple missing formatting specifiers
|
| multiple missing formatting specifiers
|
||||||
|
|
|
||||||
|
help: format specifiers use curly braces, consider adding 2 format specifiers
|
||||||
|
|
|
||||||
|
LL | format!("{}{}", 1, 2);
|
||||||
|
| ++++
|
||||||
|
|
||||||
error: argument never used
|
error: argument never used
|
||||||
--> $DIR/ifmt-bad-arg.rs:33:22
|
--> $DIR/ifmt-bad-arg.rs:33:22
|
||||||
|
|
@ -102,6 +107,11 @@ LL | format!("", foo=2);
|
||||||
| -- ^ named argument never used
|
| -- ^ named argument never used
|
||||||
| |
|
| |
|
||||||
| formatting specifier missing
|
| formatting specifier missing
|
||||||
|
|
|
||||||
|
help: format specifiers use curly braces, consider adding a format specifier
|
||||||
|
|
|
||||||
|
LL | format!("{}", foo=2);
|
||||||
|
| ++
|
||||||
|
|
||||||
error: multiple unused formatting arguments
|
error: multiple unused formatting arguments
|
||||||
--> $DIR/ifmt-bad-arg.rs:38:32
|
--> $DIR/ifmt-bad-arg.rs:38:32
|
||||||
|
|
@ -111,6 +121,8 @@ LL | format!("{} {}", 1, 2, foo=1, bar=2);
|
||||||
| | |
|
| | |
|
||||||
| | named argument never used
|
| | named argument never used
|
||||||
| multiple missing formatting specifiers
|
| multiple missing formatting specifiers
|
||||||
|
|
|
||||||
|
= note: consider adding 2 format specifiers
|
||||||
|
|
||||||
error: duplicate argument named `foo`
|
error: duplicate argument named `foo`
|
||||||
--> $DIR/ifmt-bad-arg.rs:40:29
|
--> $DIR/ifmt-bad-arg.rs:40:29
|
||||||
|
|
|
||||||
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;
|
extern crate proc_macro;
|
||||||
use proc_macro::TokenStream;
|
use proc_macro::{Literal, TokenStream};
|
||||||
|
|
||||||
#[proc_macro]
|
#[proc_macro]
|
||||||
pub fn check(_: TokenStream) -> TokenStream {
|
pub fn check(_: TokenStream) -> TokenStream {
|
||||||
|
// In the following test cases, the `---` may look like the start of frontmatter but it is not!
|
||||||
|
// That's because it would be backward incompatible to interpret them as such in the latest
|
||||||
|
// stable edition. That's not only the case due to the feature gate error but also due to the
|
||||||
|
// fact that we "eagerly" emit errors on malformed frontmatter.
|
||||||
|
|
||||||
|
// issue: <https://github.com/rust-lang/rust/issues/145520>
|
||||||
|
_ = "---".parse::<TokenStream>();
|
||||||
|
// Just a sequence of regular Rust punctuation tokens.
|
||||||
assert_eq!(6, "---\n---".parse::<TokenStream>().unwrap().into_iter().count());
|
assert_eq!(6, "---\n---".parse::<TokenStream>().unwrap().into_iter().count());
|
||||||
|
|
||||||
|
// issue: <https://github.com/rust-lang/rust/issues/146132>
|
||||||
|
assert!("---".parse::<Literal>().is_err());
|
||||||
|
|
||||||
Default::default()
|
Default::default()
|
||||||
}
|
}
|
||||||
|
|
|
||||||
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
|
//@ proc-macro: makro.rs
|
||||||
//@ edition: 2021
|
//@ edition: 2021
|
||||||
|
|
||||||
|
// Check that a proc-macro doesn't try to parse frontmatter and instead treats
|
||||||
|
// it as a regular Rust token sequence. See `auxiliary/makro.rs` for details.
|
||||||
|
|
||||||
makro::check!();
|
makro::check!();
|
||||||
|
|
||||||
// checks that a proc-macro doesn't know or parse frontmatters at all and instead treats
|
|
||||||
// it as normal Rust code.
|
|
||||||
// see auxiliary/makro.rs for how it is tested.
|
|
||||||
|
|
||||||
fn main() {}
|
fn main() {}
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@
|
||||||
#![feature(c_variadic)]
|
#![feature(c_variadic)]
|
||||||
|
|
||||||
async unsafe extern "C" fn multiple_named_lifetimes<'a, 'b>(_: u8, ...) {}
|
async unsafe extern "C" fn multiple_named_lifetimes<'a, 'b>(_: u8, ...) {}
|
||||||
//~^ ERROR hidden type for `impl Future<Output = ()>` captures lifetime that does not appear in bounds
|
//~^ ERROR functions cannot be both `async` and C-variadic
|
||||||
|
//~| ERROR hidden type for `impl Future<Output = ()>` captures lifetime that does not appear in bounds
|
||||||
|
|
||||||
fn main() {}
|
fn main() {}
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,9 @@
|
||||||
|
error: functions cannot be both `async` and C-variadic
|
||||||
|
--> $DIR/note-and-explain-ReVar-124973.rs:5:1
|
||||||
|
|
|
||||||
|
LL | async unsafe extern "C" fn multiple_named_lifetimes<'a, 'b>(_: u8, ...) {}
|
||||||
|
| ^^^^^ `async` because of this ^^^ C-variadic because of this
|
||||||
|
|
||||||
error[E0700]: hidden type for `impl Future<Output = ()>` captures lifetime that does not appear in bounds
|
error[E0700]: hidden type for `impl Future<Output = ()>` captures lifetime that does not appear in bounds
|
||||||
--> $DIR/note-and-explain-ReVar-124973.rs:5:73
|
--> $DIR/note-and-explain-ReVar-124973.rs:5:73
|
||||||
|
|
|
|
||||||
|
|
@ -8,6 +14,6 @@ LL | async unsafe extern "C" fn multiple_named_lifetimes<'a, 'b>(_: u8, ...) {}
|
||||||
|
|
|
|
||||||
= note: hidden type `{async fn body of multiple_named_lifetimes<'a, 'b>()}` captures lifetime `'_`
|
= note: hidden type `{async fn body of multiple_named_lifetimes<'a, 'b>()}` captures lifetime `'_`
|
||||||
|
|
||||||
error: aborting due to 1 previous error
|
error: aborting due to 2 previous errors
|
||||||
|
|
||||||
For more information about this error, try `rustc --explain E0700`.
|
For more information about this error, try `rustc --explain E0700`.
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,11 @@ LL | println!("Test", 123, 456, 789);
|
||||||
| | | argument never used
|
| | | argument never used
|
||||||
| | argument never used
|
| | argument never used
|
||||||
| multiple missing formatting specifiers
|
| multiple missing formatting specifiers
|
||||||
|
|
|
||||||
|
help: format specifiers use curly braces, consider adding 3 format specifiers
|
||||||
|
|
|
||||||
|
LL | println!("Test{}{}{}", 123, 456, 789);
|
||||||
|
| ++++++
|
||||||
|
|
||||||
error: multiple unused formatting arguments
|
error: multiple unused formatting arguments
|
||||||
--> $DIR/format-unused-lables.rs:6:9
|
--> $DIR/format-unused-lables.rs:6:9
|
||||||
|
|
@ -19,6 +24,11 @@ LL | 456,
|
||||||
| ^^^ argument never used
|
| ^^^ argument never used
|
||||||
LL | 789
|
LL | 789
|
||||||
| ^^^ argument never used
|
| ^^^ argument never used
|
||||||
|
|
|
||||||
|
help: format specifiers use curly braces, consider adding 3 format specifiers
|
||||||
|
|
|
||||||
|
LL | println!("Test2{}{}{}",
|
||||||
|
| ++++++
|
||||||
|
|
||||||
error: named argument never used
|
error: named argument never used
|
||||||
--> $DIR/format-unused-lables.rs:11:35
|
--> $DIR/format-unused-lables.rs:11:35
|
||||||
|
|
@ -27,6 +37,11 @@ LL | println!("Some stuff", UNUSED="args");
|
||||||
| ------------ ^^^^^^ named argument never used
|
| ------------ ^^^^^^ named argument never used
|
||||||
| |
|
| |
|
||||||
| formatting specifier missing
|
| formatting specifier missing
|
||||||
|
|
|
||||||
|
help: format specifiers use curly braces, consider adding a format specifier
|
||||||
|
|
|
||||||
|
LL | println!("Some stuff{}", UNUSED="args");
|
||||||
|
| ++
|
||||||
|
|
||||||
error: multiple unused formatting arguments
|
error: multiple unused formatting arguments
|
||||||
--> $DIR/format-unused-lables.rs:14:9
|
--> $DIR/format-unused-lables.rs:14:9
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,6 @@
|
||||||
|
|
||||||
fn main() {}
|
fn main() {}
|
||||||
|
|
||||||
fn foo(_: Bar, ...) -> impl {}
|
unsafe extern "C" fn foo(_: Bar, ...) -> impl {}
|
||||||
//~^ ERROR defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention
|
//~^ ERROR cannot find type `Bar` in this scope
|
||||||
//~| ERROR cannot find type `Bar` in this scope
|
|
||||||
//~| ERROR at least one trait must be specified
|
//~| ERROR at least one trait must be specified
|
||||||
|
|
|
||||||
|
|
@ -1,21 +1,15 @@
|
||||||
error: defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention
|
|
||||||
--> $DIR/issue-83499-input-output-iteration-ice.rs:7:16
|
|
||||||
|
|
|
||||||
LL | fn foo(_: Bar, ...) -> impl {}
|
|
||||||
| ^^^
|
|
||||||
|
|
||||||
error: at least one trait must be specified
|
error: at least one trait must be specified
|
||||||
--> $DIR/issue-83499-input-output-iteration-ice.rs:7:24
|
--> $DIR/issue-83499-input-output-iteration-ice.rs:7:42
|
||||||
|
|
|
|
||||||
LL | fn foo(_: Bar, ...) -> impl {}
|
LL | unsafe extern "C" fn foo(_: Bar, ...) -> impl {}
|
||||||
| ^^^^
|
| ^^^^
|
||||||
|
|
||||||
error[E0412]: cannot find type `Bar` in this scope
|
error[E0412]: cannot find type `Bar` in this scope
|
||||||
--> $DIR/issue-83499-input-output-iteration-ice.rs:7:11
|
--> $DIR/issue-83499-input-output-iteration-ice.rs:7:29
|
||||||
|
|
|
|
||||||
LL | fn foo(_: Bar, ...) -> impl {}
|
LL | unsafe extern "C" fn foo(_: Bar, ...) -> impl {}
|
||||||
| ^^^ not found in this scope
|
| ^^^ not found in this scope
|
||||||
|
|
||||||
error: aborting due to 3 previous errors
|
error: aborting due to 2 previous errors
|
||||||
|
|
||||||
For more information about this error, try `rustc --explain E0412`.
|
For more information about this error, try `rustc --explain E0412`.
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,11 @@ LL | println!("C", unsafe { &symbol });
|
||||||
| --- ^^^^^^^^^^^^^^^^^^ argument never used
|
| --- ^^^^^^^^^^^^^^^^^^ argument never used
|
||||||
| |
|
| |
|
||||||
| formatting specifier missing
|
| formatting specifier missing
|
||||||
|
|
|
||||||
|
help: format specifiers use curly braces, consider adding a format specifier
|
||||||
|
|
|
||||||
|
LL | println!("C{}", unsafe { &symbol });
|
||||||
|
| ++
|
||||||
|
|
||||||
error[E0277]: the size for values of type `[i8]` cannot be known at compilation time
|
error[E0277]: the size for values of type `[i8]` cannot be known at compilation time
|
||||||
--> $DIR/unsized-extern-static.rs:6:5
|
--> $DIR/unsized-extern-static.rs:6:5
|
||||||
|
|
|
||||||
|
|
@ -4,25 +4,28 @@
|
||||||
fn main() {}
|
fn main() {}
|
||||||
|
|
||||||
fn f1_1(x: isize, ...) {}
|
fn f1_1(x: isize, ...) {}
|
||||||
//~^ ERROR defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention
|
//~^ ERROR `...` is not supported for non-extern functions
|
||||||
|
|
||||||
fn f1_2(...) {}
|
fn f1_2(...) {}
|
||||||
//~^ ERROR defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention
|
//~^ ERROR `...` is not supported for non-extern functions
|
||||||
|
|
||||||
|
unsafe extern "Rust" fn f1_3(...) {}
|
||||||
|
//~^ ERROR `...` is not supported for `extern "Rust"` functions
|
||||||
|
|
||||||
extern "C" fn f2_1(x: isize, ...) {}
|
extern "C" fn f2_1(x: isize, ...) {}
|
||||||
//~^ ERROR defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention
|
//~^ ERROR functions with a C variable argument list must be unsafe
|
||||||
|
|
||||||
extern "C" fn f2_2(...) {}
|
extern "C" fn f2_2(...) {}
|
||||||
//~^ ERROR defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention
|
//~^ ERROR functions with a C variable argument list must be unsafe
|
||||||
|
|
||||||
extern "C" fn f2_3(..., x: isize) {}
|
extern "C" fn f2_3(..., x: isize) {}
|
||||||
//~^ ERROR `...` must be the last argument of a C-variadic function
|
//~^ ERROR `...` must be the last argument of a C-variadic function
|
||||||
|
|
||||||
extern "C" fn f3_1(x: isize, ...) {}
|
extern "C" fn f3_1(x: isize, ...) {}
|
||||||
//~^ ERROR defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention
|
//~^ ERROR functions with a C variable argument list must be unsafe
|
||||||
|
|
||||||
extern "C" fn f3_2(...) {}
|
extern "C" fn f3_2(...) {}
|
||||||
//~^ ERROR defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention
|
//~^ ERROR functions with a C variable argument list must be unsafe
|
||||||
|
|
||||||
extern "C" fn f3_3(..., x: isize) {}
|
extern "C" fn f3_3(..., x: isize) {}
|
||||||
//~^ ERROR `...` must be the last argument of a C-variadic function
|
//~^ ERROR `...` must be the last argument of a C-variadic function
|
||||||
|
|
@ -33,12 +36,12 @@ const unsafe extern "C" fn f4_1(x: isize, ...) {}
|
||||||
|
|
||||||
const extern "C" fn f4_2(x: isize, ...) {}
|
const extern "C" fn f4_2(x: isize, ...) {}
|
||||||
//~^ ERROR functions cannot be both `const` and C-variadic
|
//~^ ERROR functions cannot be both `const` and C-variadic
|
||||||
//~| ERROR defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention
|
//~| ERROR functions with a C variable argument list must be unsafe
|
||||||
//~| ERROR destructor of `VaListImpl<'_>` cannot be evaluated at compile-time
|
//~| ERROR destructor of `VaListImpl<'_>` cannot be evaluated at compile-time
|
||||||
|
|
||||||
const extern "C" fn f4_3(..., x: isize, ...) {}
|
const extern "C" fn f4_3(..., x: isize, ...) {}
|
||||||
//~^ ERROR functions cannot be both `const` and C-variadic
|
//~^ ERROR functions cannot be both `const` and C-variadic
|
||||||
//~| ERROR defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention
|
//~| ERROR functions with a C variable argument list must be unsafe
|
||||||
//~| ERROR `...` must be the last argument of a C-variadic function
|
//~| ERROR `...` must be the last argument of a C-variadic function
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
|
|
@ -50,30 +53,30 @@ struct X;
|
||||||
|
|
||||||
impl X {
|
impl X {
|
||||||
fn i_f1(x: isize, ...) {}
|
fn i_f1(x: isize, ...) {}
|
||||||
//~^ ERROR defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention
|
//~^ ERROR associated functions cannot have a C variable argument list
|
||||||
fn i_f2(...) {}
|
fn i_f2(...) {}
|
||||||
//~^ ERROR defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention
|
//~^ ERROR associated functions cannot have a C variable argument list
|
||||||
fn i_f3(..., x: isize, ...) {}
|
fn i_f3(..., x: isize, ...) {}
|
||||||
//~^ ERROR defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention
|
//~^ ERROR associated functions cannot have a C variable argument list
|
||||||
//~| ERROR `...` must be the last argument of a C-variadic function
|
//~| ERROR `...` must be the last argument of a C-variadic function
|
||||||
fn i_f4(..., x: isize, ...) {}
|
fn i_f4(..., x: isize, ...) {}
|
||||||
//~^ ERROR defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention
|
//~^ ERROR associated functions cannot have a C variable argument list
|
||||||
//~| ERROR `...` must be the last argument of a C-variadic function
|
//~| ERROR `...` must be the last argument of a C-variadic function
|
||||||
const fn i_f5(x: isize, ...) {}
|
const fn i_f5(x: isize, ...) {}
|
||||||
//~^ ERROR defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention
|
//~^ ERROR associated functions cannot have a C variable argument list
|
||||||
//~| ERROR functions cannot be both `const` and C-variadic
|
//~| ERROR functions cannot be both `const` and C-variadic
|
||||||
//~| ERROR destructor of `VaListImpl<'_>` cannot be evaluated at compile-time
|
//~| ERROR destructor of `VaListImpl<'_>` cannot be evaluated at compile-time
|
||||||
}
|
}
|
||||||
|
|
||||||
trait T {
|
trait T {
|
||||||
fn t_f1(x: isize, ...) {}
|
fn t_f1(x: isize, ...) {}
|
||||||
//~^ ERROR defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention
|
//~^ ERROR associated functions cannot have a C variable argument list
|
||||||
fn t_f2(x: isize, ...);
|
fn t_f2(x: isize, ...);
|
||||||
//~^ ERROR defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention
|
//~^ ERROR associated functions cannot have a C variable argument list
|
||||||
fn t_f3(...) {}
|
fn t_f3(...) {}
|
||||||
//~^ ERROR defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention
|
//~^ ERROR associated functions cannot have a C variable argument list
|
||||||
fn t_f4(...);
|
fn t_f4(...);
|
||||||
//~^ ERROR defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention
|
//~^ ERROR associated functions cannot have a C variable argument list
|
||||||
fn t_f5(..., x: isize) {}
|
fn t_f5(..., x: isize) {}
|
||||||
//~^ ERROR `...` must be the last argument of a C-variadic function
|
//~^ ERROR `...` must be the last argument of a C-variadic function
|
||||||
fn t_f6(..., x: isize);
|
fn t_f6(..., x: isize);
|
||||||
|
|
|
||||||
|
|
@ -1,181 +1,225 @@
|
||||||
error: defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention
|
error: `...` is not supported for non-extern functions
|
||||||
--> $DIR/variadic-ffi-semantic-restrictions.rs:6:19
|
--> $DIR/variadic-ffi-semantic-restrictions.rs:6:19
|
||||||
|
|
|
|
||||||
LL | fn f1_1(x: isize, ...) {}
|
LL | fn f1_1(x: isize, ...) {}
|
||||||
| ^^^
|
| ^^^
|
||||||
|
|
|
||||||
|
= help: only `extern "C"` and `extern "C-unwind"` functions may have a C variable argument list
|
||||||
|
|
||||||
error: defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention
|
error: `...` is not supported for non-extern functions
|
||||||
--> $DIR/variadic-ffi-semantic-restrictions.rs:9:9
|
--> $DIR/variadic-ffi-semantic-restrictions.rs:9:9
|
||||||
|
|
|
|
||||||
LL | fn f1_2(...) {}
|
LL | fn f1_2(...) {}
|
||||||
| ^^^
|
| ^^^
|
||||||
|
|
|
||||||
|
= help: only `extern "C"` and `extern "C-unwind"` functions may have a C variable argument list
|
||||||
|
|
||||||
error: defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention
|
error: `...` is not supported for `extern "Rust"` functions
|
||||||
--> $DIR/variadic-ffi-semantic-restrictions.rs:12:30
|
--> $DIR/variadic-ffi-semantic-restrictions.rs:12:30
|
||||||
|
|
|
|
||||||
|
LL | unsafe extern "Rust" fn f1_3(...) {}
|
||||||
|
| ------------- ^^^
|
||||||
|
| |
|
||||||
|
| `extern "Rust"` because of this
|
||||||
|
|
|
||||||
|
= help: only `extern "C"` and `extern "C-unwind"` functions may have a C variable argument list
|
||||||
|
|
||||||
|
error: functions with a C variable argument list must be unsafe
|
||||||
|
--> $DIR/variadic-ffi-semantic-restrictions.rs:15:30
|
||||||
|
|
|
||||||
LL | extern "C" fn f2_1(x: isize, ...) {}
|
LL | extern "C" fn f2_1(x: isize, ...) {}
|
||||||
| ^^^
|
| ^^^
|
||||||
|
|
|
||||||
|
help: add the `unsafe` keyword to this definition
|
||||||
|
|
|
||||||
|
LL | unsafe extern "C" fn f2_1(x: isize, ...) {}
|
||||||
|
| ++++++
|
||||||
|
|
||||||
error: defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention
|
error: functions with a C variable argument list must be unsafe
|
||||||
--> $DIR/variadic-ffi-semantic-restrictions.rs:15:20
|
--> $DIR/variadic-ffi-semantic-restrictions.rs:18:20
|
||||||
|
|
|
|
||||||
LL | extern "C" fn f2_2(...) {}
|
LL | extern "C" fn f2_2(...) {}
|
||||||
| ^^^
|
| ^^^
|
||||||
|
|
|
||||||
|
help: add the `unsafe` keyword to this definition
|
||||||
|
|
|
||||||
|
LL | unsafe extern "C" fn f2_2(...) {}
|
||||||
|
| ++++++
|
||||||
|
|
||||||
error: `...` must be the last argument of a C-variadic function
|
error: `...` must be the last argument of a C-variadic function
|
||||||
--> $DIR/variadic-ffi-semantic-restrictions.rs:18:20
|
--> $DIR/variadic-ffi-semantic-restrictions.rs:21:20
|
||||||
|
|
|
|
||||||
LL | extern "C" fn f2_3(..., x: isize) {}
|
LL | extern "C" fn f2_3(..., x: isize) {}
|
||||||
| ^^^
|
| ^^^
|
||||||
|
|
||||||
error: defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention
|
error: functions with a C variable argument list must be unsafe
|
||||||
--> $DIR/variadic-ffi-semantic-restrictions.rs:21:30
|
--> $DIR/variadic-ffi-semantic-restrictions.rs:24:30
|
||||||
|
|
|
|
||||||
LL | extern "C" fn f3_1(x: isize, ...) {}
|
LL | extern "C" fn f3_1(x: isize, ...) {}
|
||||||
| ^^^
|
| ^^^
|
||||||
|
|
|
||||||
|
help: add the `unsafe` keyword to this definition
|
||||||
|
|
|
||||||
|
LL | unsafe extern "C" fn f3_1(x: isize, ...) {}
|
||||||
|
| ++++++
|
||||||
|
|
||||||
error: defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention
|
error: functions with a C variable argument list must be unsafe
|
||||||
--> $DIR/variadic-ffi-semantic-restrictions.rs:24:20
|
--> $DIR/variadic-ffi-semantic-restrictions.rs:27:20
|
||||||
|
|
|
|
||||||
LL | extern "C" fn f3_2(...) {}
|
LL | extern "C" fn f3_2(...) {}
|
||||||
| ^^^
|
| ^^^
|
||||||
|
|
|
||||||
|
help: add the `unsafe` keyword to this definition
|
||||||
|
|
|
||||||
|
LL | unsafe extern "C" fn f3_2(...) {}
|
||||||
|
| ++++++
|
||||||
|
|
||||||
error: `...` must be the last argument of a C-variadic function
|
error: `...` must be the last argument of a C-variadic function
|
||||||
--> $DIR/variadic-ffi-semantic-restrictions.rs:27:20
|
--> $DIR/variadic-ffi-semantic-restrictions.rs:30:20
|
||||||
|
|
|
|
||||||
LL | extern "C" fn f3_3(..., x: isize) {}
|
LL | extern "C" fn f3_3(..., x: isize) {}
|
||||||
| ^^^
|
| ^^^
|
||||||
|
|
||||||
error: functions cannot be both `const` and C-variadic
|
error: functions cannot be both `const` and C-variadic
|
||||||
--> $DIR/variadic-ffi-semantic-restrictions.rs:30:1
|
--> $DIR/variadic-ffi-semantic-restrictions.rs:33:1
|
||||||
|
|
|
|
||||||
LL | const unsafe extern "C" fn f4_1(x: isize, ...) {}
|
LL | const unsafe extern "C" fn f4_1(x: isize, ...) {}
|
||||||
| ^^^^^ `const` because of this ^^^ C-variadic because of this
|
| ^^^^^ `const` because of this ^^^ C-variadic because of this
|
||||||
|
|
||||||
error: functions cannot be both `const` and C-variadic
|
error: functions cannot be both `const` and C-variadic
|
||||||
--> $DIR/variadic-ffi-semantic-restrictions.rs:34:1
|
--> $DIR/variadic-ffi-semantic-restrictions.rs:37:1
|
||||||
|
|
|
|
||||||
LL | const extern "C" fn f4_2(x: isize, ...) {}
|
LL | const extern "C" fn f4_2(x: isize, ...) {}
|
||||||
| ^^^^^ `const` because of this ^^^ C-variadic because of this
|
| ^^^^^ `const` because of this ^^^ C-variadic because of this
|
||||||
|
|
||||||
error: defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention
|
error: functions with a C variable argument list must be unsafe
|
||||||
--> $DIR/variadic-ffi-semantic-restrictions.rs:34:36
|
--> $DIR/variadic-ffi-semantic-restrictions.rs:37:36
|
||||||
|
|
|
|
||||||
LL | const extern "C" fn f4_2(x: isize, ...) {}
|
LL | const extern "C" fn f4_2(x: isize, ...) {}
|
||||||
| ^^^
|
| ^^^
|
||||||
|
|
|
||||||
|
help: add the `unsafe` keyword to this definition
|
||||||
|
|
|
||||||
|
LL | const unsafe extern "C" fn f4_2(x: isize, ...) {}
|
||||||
|
| ++++++
|
||||||
|
|
||||||
error: `...` must be the last argument of a C-variadic function
|
error: `...` must be the last argument of a C-variadic function
|
||||||
--> $DIR/variadic-ffi-semantic-restrictions.rs:39:26
|
--> $DIR/variadic-ffi-semantic-restrictions.rs:42:26
|
||||||
|
|
|
|
||||||
LL | const extern "C" fn f4_3(..., x: isize, ...) {}
|
LL | const extern "C" fn f4_3(..., x: isize, ...) {}
|
||||||
| ^^^
|
| ^^^
|
||||||
|
|
||||||
error: functions cannot be both `const` and C-variadic
|
error: functions cannot be both `const` and C-variadic
|
||||||
--> $DIR/variadic-ffi-semantic-restrictions.rs:39:1
|
--> $DIR/variadic-ffi-semantic-restrictions.rs:42:1
|
||||||
|
|
|
|
||||||
LL | const extern "C" fn f4_3(..., x: isize, ...) {}
|
LL | const extern "C" fn f4_3(..., x: isize, ...) {}
|
||||||
| ^^^^^ `const` because of this ^^^ C-variadic because of this
|
| ^^^^^ `const` because of this ^^^ C-variadic because of this
|
||||||
|
|
||||||
error: defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention
|
error: functions with a C variable argument list must be unsafe
|
||||||
--> $DIR/variadic-ffi-semantic-restrictions.rs:39:41
|
--> $DIR/variadic-ffi-semantic-restrictions.rs:42:41
|
||||||
|
|
|
|
||||||
LL | const extern "C" fn f4_3(..., x: isize, ...) {}
|
LL | const extern "C" fn f4_3(..., x: isize, ...) {}
|
||||||
| ^^^
|
| ^^^
|
||||||
|
|
|
||||||
|
help: add the `unsafe` keyword to this definition
|
||||||
|
|
|
||||||
|
LL | const unsafe extern "C" fn f4_3(..., x: isize, ...) {}
|
||||||
|
| ++++++
|
||||||
|
|
||||||
error: `...` must be the last argument of a C-variadic function
|
error: `...` must be the last argument of a C-variadic function
|
||||||
--> $DIR/variadic-ffi-semantic-restrictions.rs:45:13
|
--> $DIR/variadic-ffi-semantic-restrictions.rs:48:13
|
||||||
|
|
|
|
||||||
LL | fn e_f2(..., x: isize);
|
LL | fn e_f2(..., x: isize);
|
||||||
| ^^^
|
| ^^^
|
||||||
|
|
||||||
error: defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention
|
error: associated functions cannot have a C variable argument list
|
||||||
--> $DIR/variadic-ffi-semantic-restrictions.rs:52:23
|
--> $DIR/variadic-ffi-semantic-restrictions.rs:55:23
|
||||||
|
|
|
|
||||||
LL | fn i_f1(x: isize, ...) {}
|
LL | fn i_f1(x: isize, ...) {}
|
||||||
| ^^^
|
| ^^^
|
||||||
|
|
||||||
error: defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention
|
error: associated functions cannot have a C variable argument list
|
||||||
--> $DIR/variadic-ffi-semantic-restrictions.rs:54:13
|
--> $DIR/variadic-ffi-semantic-restrictions.rs:57:13
|
||||||
|
|
|
|
||||||
LL | fn i_f2(...) {}
|
LL | fn i_f2(...) {}
|
||||||
| ^^^
|
| ^^^
|
||||||
|
|
||||||
error: `...` must be the last argument of a C-variadic function
|
error: `...` must be the last argument of a C-variadic function
|
||||||
--> $DIR/variadic-ffi-semantic-restrictions.rs:56:13
|
--> $DIR/variadic-ffi-semantic-restrictions.rs:59:13
|
||||||
|
|
|
|
||||||
LL | fn i_f3(..., x: isize, ...) {}
|
LL | fn i_f3(..., x: isize, ...) {}
|
||||||
| ^^^
|
| ^^^
|
||||||
|
|
||||||
error: defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention
|
error: associated functions cannot have a C variable argument list
|
||||||
--> $DIR/variadic-ffi-semantic-restrictions.rs:56:28
|
--> $DIR/variadic-ffi-semantic-restrictions.rs:59:28
|
||||||
|
|
|
|
||||||
LL | fn i_f3(..., x: isize, ...) {}
|
LL | fn i_f3(..., x: isize, ...) {}
|
||||||
| ^^^
|
| ^^^
|
||||||
|
|
||||||
error: `...` must be the last argument of a C-variadic function
|
error: `...` must be the last argument of a C-variadic function
|
||||||
--> $DIR/variadic-ffi-semantic-restrictions.rs:59:13
|
--> $DIR/variadic-ffi-semantic-restrictions.rs:62:13
|
||||||
|
|
|
|
||||||
LL | fn i_f4(..., x: isize, ...) {}
|
LL | fn i_f4(..., x: isize, ...) {}
|
||||||
| ^^^
|
| ^^^
|
||||||
|
|
||||||
error: defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention
|
error: associated functions cannot have a C variable argument list
|
||||||
--> $DIR/variadic-ffi-semantic-restrictions.rs:59:28
|
--> $DIR/variadic-ffi-semantic-restrictions.rs:62:28
|
||||||
|
|
|
|
||||||
LL | fn i_f4(..., x: isize, ...) {}
|
LL | fn i_f4(..., x: isize, ...) {}
|
||||||
| ^^^
|
| ^^^
|
||||||
|
|
||||||
error: functions cannot be both `const` and C-variadic
|
error: functions cannot be both `const` and C-variadic
|
||||||
--> $DIR/variadic-ffi-semantic-restrictions.rs:62:5
|
--> $DIR/variadic-ffi-semantic-restrictions.rs:65:5
|
||||||
|
|
|
|
||||||
LL | const fn i_f5(x: isize, ...) {}
|
LL | const fn i_f5(x: isize, ...) {}
|
||||||
| ^^^^^ ^^^ C-variadic because of this
|
| ^^^^^ ^^^ C-variadic because of this
|
||||||
| |
|
| |
|
||||||
| `const` because of this
|
| `const` because of this
|
||||||
|
|
||||||
error: defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention
|
error: associated functions cannot have a C variable argument list
|
||||||
--> $DIR/variadic-ffi-semantic-restrictions.rs:62:29
|
--> $DIR/variadic-ffi-semantic-restrictions.rs:65:29
|
||||||
|
|
|
|
||||||
LL | const fn i_f5(x: isize, ...) {}
|
LL | const fn i_f5(x: isize, ...) {}
|
||||||
| ^^^
|
| ^^^
|
||||||
|
|
||||||
error: defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention
|
error: associated functions cannot have a C variable argument list
|
||||||
--> $DIR/variadic-ffi-semantic-restrictions.rs:69:23
|
--> $DIR/variadic-ffi-semantic-restrictions.rs:72:23
|
||||||
|
|
|
|
||||||
LL | fn t_f1(x: isize, ...) {}
|
LL | fn t_f1(x: isize, ...) {}
|
||||||
| ^^^
|
| ^^^
|
||||||
|
|
||||||
error: defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention
|
error: associated functions cannot have a C variable argument list
|
||||||
--> $DIR/variadic-ffi-semantic-restrictions.rs:71:23
|
--> $DIR/variadic-ffi-semantic-restrictions.rs:74:23
|
||||||
|
|
|
|
||||||
LL | fn t_f2(x: isize, ...);
|
LL | fn t_f2(x: isize, ...);
|
||||||
| ^^^
|
| ^^^
|
||||||
|
|
||||||
error: defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention
|
error: associated functions cannot have a C variable argument list
|
||||||
--> $DIR/variadic-ffi-semantic-restrictions.rs:73:13
|
--> $DIR/variadic-ffi-semantic-restrictions.rs:76:13
|
||||||
|
|
|
|
||||||
LL | fn t_f3(...) {}
|
LL | fn t_f3(...) {}
|
||||||
| ^^^
|
| ^^^
|
||||||
|
|
||||||
error: defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention
|
error: associated functions cannot have a C variable argument list
|
||||||
--> $DIR/variadic-ffi-semantic-restrictions.rs:75:13
|
--> $DIR/variadic-ffi-semantic-restrictions.rs:78:13
|
||||||
|
|
|
|
||||||
LL | fn t_f4(...);
|
LL | fn t_f4(...);
|
||||||
| ^^^
|
| ^^^
|
||||||
|
|
||||||
error: `...` must be the last argument of a C-variadic function
|
error: `...` must be the last argument of a C-variadic function
|
||||||
--> $DIR/variadic-ffi-semantic-restrictions.rs:77:13
|
--> $DIR/variadic-ffi-semantic-restrictions.rs:80:13
|
||||||
|
|
|
|
||||||
LL | fn t_f5(..., x: isize) {}
|
LL | fn t_f5(..., x: isize) {}
|
||||||
| ^^^
|
| ^^^
|
||||||
|
|
||||||
error: `...` must be the last argument of a C-variadic function
|
error: `...` must be the last argument of a C-variadic function
|
||||||
--> $DIR/variadic-ffi-semantic-restrictions.rs:79:13
|
--> $DIR/variadic-ffi-semantic-restrictions.rs:82:13
|
||||||
|
|
|
|
||||||
LL | fn t_f6(..., x: isize);
|
LL | fn t_f6(..., x: isize);
|
||||||
| ^^^
|
| ^^^
|
||||||
|
|
||||||
error[E0493]: destructor of `VaListImpl<'_>` cannot be evaluated at compile-time
|
error[E0493]: destructor of `VaListImpl<'_>` cannot be evaluated at compile-time
|
||||||
--> $DIR/variadic-ffi-semantic-restrictions.rs:30:43
|
--> $DIR/variadic-ffi-semantic-restrictions.rs:33:43
|
||||||
|
|
|
|
||||||
LL | const unsafe extern "C" fn f4_1(x: isize, ...) {}
|
LL | const unsafe extern "C" fn f4_1(x: isize, ...) {}
|
||||||
| ^^^ - value is dropped here
|
| ^^^ - value is dropped here
|
||||||
|
|
@ -183,7 +227,7 @@ LL | const unsafe extern "C" fn f4_1(x: isize, ...) {}
|
||||||
| the destructor for this type cannot be evaluated in constant functions
|
| the destructor for this type cannot be evaluated in constant functions
|
||||||
|
|
||||||
error[E0493]: destructor of `VaListImpl<'_>` cannot be evaluated at compile-time
|
error[E0493]: destructor of `VaListImpl<'_>` cannot be evaluated at compile-time
|
||||||
--> $DIR/variadic-ffi-semantic-restrictions.rs:34:36
|
--> $DIR/variadic-ffi-semantic-restrictions.rs:37:36
|
||||||
|
|
|
|
||||||
LL | const extern "C" fn f4_2(x: isize, ...) {}
|
LL | const extern "C" fn f4_2(x: isize, ...) {}
|
||||||
| ^^^ - value is dropped here
|
| ^^^ - value is dropped here
|
||||||
|
|
@ -191,13 +235,13 @@ LL | const extern "C" fn f4_2(x: isize, ...) {}
|
||||||
| the destructor for this type cannot be evaluated in constant functions
|
| the destructor for this type cannot be evaluated in constant functions
|
||||||
|
|
||||||
error[E0493]: destructor of `VaListImpl<'_>` cannot be evaluated at compile-time
|
error[E0493]: destructor of `VaListImpl<'_>` cannot be evaluated at compile-time
|
||||||
--> $DIR/variadic-ffi-semantic-restrictions.rs:62:29
|
--> $DIR/variadic-ffi-semantic-restrictions.rs:65:29
|
||||||
|
|
|
|
||||||
LL | const fn i_f5(x: isize, ...) {}
|
LL | const fn i_f5(x: isize, ...) {}
|
||||||
| ^^^ - value is dropped here
|
| ^^^ - value is dropped here
|
||||||
| |
|
| |
|
||||||
| the destructor for this type cannot be evaluated in constant functions
|
| the destructor for this type cannot be evaluated in constant functions
|
||||||
|
|
||||||
error: aborting due to 32 previous errors
|
error: aborting due to 33 previous errors
|
||||||
|
|
||||||
For more information about this error, try `rustc --explain E0493`.
|
For more information about this error, try `rustc --explain E0493`.
|
||||||
|
|
|
||||||
|
|
@ -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"]`.
|
// FIXME: `?Trait1` should be rejected, `Trait1` isn't marked `#[lang = "default_traitN"]`.
|
||||||
fn baz<T>() where T: Iterator<Item: ?Trait1> {}
|
fn baz<T>() where T: Iterator<Item: ?Trait1> {}
|
||||||
|
//~^ ERROR this relaxed bound is not permitted here
|
||||||
|
|
||||||
|
struct S1<T>(T);
|
||||||
|
|
||||||
|
impl<T> S1<T> {
|
||||||
|
fn f() where T: ?Trait1 {}
|
||||||
|
//~^ ERROR this relaxed bound is not permitted here
|
||||||
|
}
|
||||||
|
|
||||||
|
trait Trait5<'a> {}
|
||||||
|
|
||||||
|
struct S2<T>(T) where for<'a> T: ?Trait5<'a>;
|
||||||
|
//~^ ERROR this relaxed bound is not permitted here
|
||||||
|
//~| ERROR bound modifier `?` can only be applied to default traits like `Sized`
|
||||||
|
|
||||||
struct S;
|
struct S;
|
||||||
impl !Trait2 for S {}
|
impl !Trait2 for S {}
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,27 @@
|
||||||
|
error: this relaxed bound is not permitted here
|
||||||
|
--> $DIR/more_maybe_bounds.rs:23:37
|
||||||
|
|
|
||||||
|
LL | fn baz<T>() where T: Iterator<Item: ?Trait1> {}
|
||||||
|
| ^^^^^^^
|
||||||
|
|
|
||||||
|
= note: in this context, relaxed bounds are only allowed on type parameters defined by the closest item
|
||||||
|
|
||||||
|
error: this relaxed bound is not permitted here
|
||||||
|
--> $DIR/more_maybe_bounds.rs:29:21
|
||||||
|
|
|
||||||
|
LL | fn f() where T: ?Trait1 {}
|
||||||
|
| ^^^^^^^
|
||||||
|
|
|
||||||
|
= note: in this context, relaxed bounds are only allowed on type parameters defined by the closest item
|
||||||
|
|
||||||
|
error: this relaxed bound is not permitted here
|
||||||
|
--> $DIR/more_maybe_bounds.rs:35:34
|
||||||
|
|
|
||||||
|
LL | struct S2<T>(T) where for<'a> T: ?Trait5<'a>;
|
||||||
|
| ^^^^^^^^^^^
|
||||||
|
|
|
||||||
|
= note: in this context, relaxed bounds are only allowed on type parameters defined by the closest item
|
||||||
|
|
||||||
error: bound modifier `?` can only be applied to default traits like `Sized`
|
error: bound modifier `?` can only be applied to default traits like `Sized`
|
||||||
--> $DIR/more_maybe_bounds.rs:17:20
|
--> $DIR/more_maybe_bounds.rs:17:20
|
||||||
|
|
|
|
||||||
|
|
@ -16,5 +40,11 @@ error: bound modifier `?` can only be applied to default traits like `Sized`
|
||||||
LL | fn bar<T: ?Sized + ?Trait2 + ?Trait1 + ?Trait4>(_: &T) {}
|
LL | fn bar<T: ?Sized + ?Trait2 + ?Trait1 + ?Trait4>(_: &T) {}
|
||||||
| ^^^^^^^
|
| ^^^^^^^
|
||||||
|
|
||||||
error: aborting due to 3 previous errors
|
error: bound modifier `?` can only be applied to default traits like `Sized`
|
||||||
|
--> $DIR/more_maybe_bounds.rs:35:34
|
||||||
|
|
|
||||||
|
LL | struct S2<T>(T) where for<'a> T: ?Trait5<'a>;
|
||||||
|
| ^^^^^^^^^^^
|
||||||
|
|
||||||
|
error: aborting due to 7 previous errors
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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]
|
#![no_core]
|
||||||
|
|
||||||
#[lang = "pointee_sized"]
|
#[lang = "pointee_sized"]
|
||||||
trait PointeeSized {}
|
trait PointeeSized: ?Leak {}
|
||||||
|
|
||||||
#[lang = "meta_sized"]
|
#[lang = "meta_sized"]
|
||||||
trait MetaSized: PointeeSized {}
|
trait MetaSized: PointeeSized + ?Leak {}
|
||||||
|
|
||||||
#[lang = "sized"]
|
#[lang = "sized"]
|
||||||
trait Sized: MetaSized {}
|
trait Sized: MetaSized + ?Leak {}
|
||||||
|
|
||||||
#[lang = "copy"]
|
#[lang = "copy"]
|
||||||
pub trait Copy {}
|
pub trait Copy: ?Leak {}
|
||||||
impl<'a, T: ?Sized> Copy for &'a T {}
|
impl<'a, T: ?Sized> Copy for &'a T {}
|
||||||
|
|
||||||
#[lang = "legacy_receiver"]
|
#[lang = "legacy_receiver"]
|
||||||
trait Receiver {}
|
trait Receiver: ?Leak {}
|
||||||
impl<T: ?Sized + ?Leak> Receiver for &T {}
|
impl<T: ?Sized + ?Leak> Receiver for &T {}
|
||||||
|
impl<T: ?Sized + ?Leak> Receiver for &mut T {}
|
||||||
|
|
||||||
#[lang = "unsize"]
|
#[lang = "unsize"]
|
||||||
trait Unsize<T: ?Sized + ?Leak> {}
|
trait Unsize<T: ?Sized + ?Leak>: ?Leak {}
|
||||||
|
|
||||||
#[lang = "coerce_unsized"]
|
#[lang = "coerce_unsized"]
|
||||||
trait CoerceUnsized<T: ?Leak + ?Sized> {}
|
trait CoerceUnsized<T: ?Leak + ?Sized>: ?Leak {}
|
||||||
impl<'a, 'b: 'a, T: ?Sized + ?Leak + Unsize<U>, U: ?Sized + ?Leak> CoerceUnsized<&'a U> for &'b T {}
|
impl<'a, 'b: 'a, T: ?Sized + ?Leak + Unsize<U>, U: ?Sized + ?Leak> CoerceUnsized<&'a U> for &'b T {}
|
||||||
|
// Omit `T: ?Leak` and `U: ?Leak`.
|
||||||
|
impl<'a, 'b: 'a, T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<&'a mut U> for &'b mut T {}
|
||||||
|
|
||||||
#[lang = "dispatch_from_dyn"]
|
#[lang = "dispatch_from_dyn"]
|
||||||
trait DispatchFromDyn<T: ?Leak> {}
|
trait DispatchFromDyn<T: ?Leak>: ?Leak {}
|
||||||
impl<'a, T: ?Sized + ?Leak + Unsize<U>, U: ?Sized + ?Leak> DispatchFromDyn<&'a U> for &'a T {}
|
impl<'a, T: ?Sized + ?Leak + Unsize<U>, U: ?Sized + ?Leak> DispatchFromDyn<&'a U> for &'a T {}
|
||||||
|
// Omit `T: ?Leak` and `U: ?Leak`.
|
||||||
|
impl<'a, T: ?Sized + Unsize<U>, U: ?Sized> DispatchFromDyn<&'a mut U> for &'a mut T {}
|
||||||
|
|
||||||
#[lang = "default_trait1"]
|
#[lang = "default_trait1"]
|
||||||
auto trait Leak {}
|
auto trait Leak {}
|
||||||
|
|
@ -47,25 +52,52 @@ struct NonLeakS;
|
||||||
impl !Leak for NonLeakS {}
|
impl !Leak for NonLeakS {}
|
||||||
struct LeakS;
|
struct LeakS;
|
||||||
|
|
||||||
trait Trait {
|
fn bounds_check() {
|
||||||
fn leak_foo(&self) {}
|
trait LeakTr {}
|
||||||
fn maybe_leak_foo(&self) where Self: ?Leak {}
|
|
||||||
|
trait MaybeLeakTr: ?Leak {}
|
||||||
|
|
||||||
|
impl MaybeLeakTr for NonLeakS {}
|
||||||
|
|
||||||
|
impl LeakTr for LeakS {}
|
||||||
|
impl MaybeLeakTr for LeakS {}
|
||||||
|
|
||||||
|
let _: &dyn LeakTr = &NonLeakS;
|
||||||
|
//~^ ERROR the trait bound `NonLeakS: bounds_check::LeakTr` is not satisfied
|
||||||
|
let _: &dyn LeakTr = &LeakS;
|
||||||
|
|
||||||
|
let _: &(dyn LeakTr + ?Leak) = &NonLeakS;
|
||||||
|
let _: &(dyn LeakTr + ?Leak) = &LeakS;
|
||||||
|
|
||||||
|
let _: &dyn MaybeLeakTr = &NonLeakS;
|
||||||
|
let _: &dyn MaybeLeakTr = &LeakS;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Trait for NonLeakS {}
|
fn dyn_compat_check() {
|
||||||
impl Trait for LeakS {}
|
trait DynCompatCheck1: ?Leak {
|
||||||
|
fn foo(&self) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
trait DynCompatCheck2: ?Leak {
|
||||||
|
fn mut_foo(&mut self) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl DynCompatCheck1 for NonLeakS {}
|
||||||
|
impl DynCompatCheck2 for NonLeakS {}
|
||||||
|
|
||||||
|
let _: &(dyn DynCompatCheck1 + ?Leak) = &NonLeakS;
|
||||||
|
// There is no `?Leak` bound on corresponding `DispatchFromDyn` impl.
|
||||||
|
let _: &dyn DynCompatCheck2 = &NonLeakS;
|
||||||
|
//~^ ERROR the trait `DynCompatCheck2` is not dyn compatible
|
||||||
|
}
|
||||||
|
|
||||||
|
fn args_check() {
|
||||||
|
trait LeakTr {}
|
||||||
|
|
||||||
fn main() {
|
|
||||||
let _: &dyn Trait = &NonLeakS;
|
|
||||||
//~^ ERROR the trait bound `NonLeakS: Leak` is not satisfied
|
|
||||||
let _: &dyn Trait = &LeakS;
|
|
||||||
let _: &(dyn Trait + ?Leak) = &LeakS;
|
|
||||||
let x: &(dyn Trait + ?Leak) = &NonLeakS;
|
|
||||||
x.leak_foo();
|
|
||||||
//~^ ERROR the trait bound `dyn Trait: Leak` is not satisfied
|
|
||||||
x.maybe_leak_foo();
|
|
||||||
// Ensure that we validate the generic args of relaxed bounds in trait object types.
|
// Ensure that we validate the generic args of relaxed bounds in trait object types.
|
||||||
let _: dyn Trait + ?Leak<(), Undefined = ()>;
|
let _: dyn LeakTr + ?Leak<(), Undefined = ()>;
|
||||||
//~^ ERROR trait takes 0 generic arguments but 1 generic argument was supplied
|
//~^ ERROR trait takes 0 generic arguments but 1 generic argument was supplied
|
||||||
//~| ERROR associated type `Undefined` not found for `Leak`
|
//~| ERROR associated type `Undefined` not found for `Leak`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn main() {}
|
||||||
|
|
|
||||||
|
|
@ -1,49 +1,57 @@
|
||||||
error[E0277]: the trait bound `NonLeakS: Leak` is not satisfied
|
error[E0277]: the trait bound `NonLeakS: bounds_check::LeakTr` is not satisfied
|
||||||
--> $DIR/maybe-bounds-in-dyn-traits.rs:59:25
|
--> $DIR/maybe-bounds-in-dyn-traits.rs:65:26
|
||||||
|
|
|
|
||||||
LL | let _: &dyn Trait = &NonLeakS;
|
LL | let _: &dyn LeakTr = &NonLeakS;
|
||||||
| ^^^^^^^^^ unsatisfied trait bound
|
| ^^^^^^^^^ unsatisfied trait bound
|
||||||
|
|
|
|
||||||
help: the trait `Leak` is not implemented for `NonLeakS`
|
help: the trait `bounds_check::LeakTr` is not implemented for `NonLeakS`
|
||||||
--> $DIR/maybe-bounds-in-dyn-traits.rs:46:1
|
--> $DIR/maybe-bounds-in-dyn-traits.rs:51:1
|
||||||
|
|
|
|
||||||
LL | struct NonLeakS;
|
LL | struct NonLeakS;
|
||||||
| ^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^
|
||||||
= note: required for the cast from `&NonLeakS` to `&dyn Trait + Leak`
|
= help: the trait `bounds_check::LeakTr` is implemented for `LeakS`
|
||||||
|
= note: required for the cast from `&NonLeakS` to `&dyn bounds_check::LeakTr + Leak`
|
||||||
|
|
||||||
error[E0277]: the trait bound `dyn Trait: Leak` is not satisfied
|
error[E0038]: the trait `DynCompatCheck2` is not dyn compatible
|
||||||
--> $DIR/maybe-bounds-in-dyn-traits.rs:64:7
|
--> $DIR/maybe-bounds-in-dyn-traits.rs:90:17
|
||||||
|
|
|
|
||||||
LL | x.leak_foo();
|
LL | fn mut_foo(&mut self) {}
|
||||||
| ^^^^^^^^ the trait `Leak` is not implemented for `dyn Trait`
|
| --------- help: consider changing method `mut_foo`'s `self` parameter to be `&self`: `&Self`
|
||||||
|
...
|
||||||
|
LL | let _: &dyn DynCompatCheck2 = &NonLeakS;
|
||||||
|
| ^^^^^^^^^^^^^^^ `DynCompatCheck2` is not dyn compatible
|
||||||
|
|
|
|
||||||
note: required by a bound in `Trait::leak_foo`
|
note: for a trait to be dyn compatible it needs to allow building a vtable
|
||||||
--> $DIR/maybe-bounds-in-dyn-traits.rs:51:5
|
for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
|
||||||
|
--> $DIR/maybe-bounds-in-dyn-traits.rs:82:20
|
||||||
|
|
|
|
||||||
LL | fn leak_foo(&self) {}
|
LL | trait DynCompatCheck2: ?Leak {
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Trait::leak_foo`
|
| --------------- this trait is not dyn compatible...
|
||||||
|
LL | fn mut_foo(&mut self) {}
|
||||||
|
| ^^^^^^^^^ ...because method `mut_foo`'s `self` parameter cannot be dispatched on
|
||||||
|
= help: only type `NonLeakS` implements `DynCompatCheck2`; consider using it directly instead.
|
||||||
|
|
||||||
error[E0107]: trait takes 0 generic arguments but 1 generic argument was supplied
|
error[E0107]: trait takes 0 generic arguments but 1 generic argument was supplied
|
||||||
--> $DIR/maybe-bounds-in-dyn-traits.rs:68:25
|
--> $DIR/maybe-bounds-in-dyn-traits.rs:98:26
|
||||||
|
|
|
|
||||||
LL | let _: dyn Trait + ?Leak<(), Undefined = ()>;
|
LL | let _: dyn LeakTr + ?Leak<(), Undefined = ()>;
|
||||||
| ^^^^-------------------- help: remove the unnecessary generics
|
| ^^^^-------------------- help: remove the unnecessary generics
|
||||||
| |
|
| |
|
||||||
| expected 0 generic arguments
|
| expected 0 generic arguments
|
||||||
|
|
|
|
||||||
note: trait defined here, with 0 generic parameters
|
note: trait defined here, with 0 generic parameters
|
||||||
--> $DIR/maybe-bounds-in-dyn-traits.rs:44:12
|
--> $DIR/maybe-bounds-in-dyn-traits.rs:49:12
|
||||||
|
|
|
|
||||||
LL | auto trait Leak {}
|
LL | auto trait Leak {}
|
||||||
| ^^^^
|
| ^^^^
|
||||||
|
|
||||||
error[E0220]: associated type `Undefined` not found for `Leak`
|
error[E0220]: associated type `Undefined` not found for `Leak`
|
||||||
--> $DIR/maybe-bounds-in-dyn-traits.rs:68:34
|
--> $DIR/maybe-bounds-in-dyn-traits.rs:98:35
|
||||||
|
|
|
|
||||||
LL | let _: dyn Trait + ?Leak<(), Undefined = ()>;
|
LL | let _: dyn LeakTr + ?Leak<(), Undefined = ()>;
|
||||||
| ^^^^^^^^^ associated type `Undefined` not found
|
| ^^^^^^^^^ associated type `Undefined` not found
|
||||||
|
|
||||||
error: aborting due to 4 previous errors
|
error: aborting due to 4 previous errors
|
||||||
|
|
||||||
Some errors have detailed explanations: E0107, E0220, E0277.
|
Some errors have detailed explanations: E0038, E0107, E0220, E0277.
|
||||||
For more information about an error, try `rustc --explain E0107`.
|
For more information about an error, try `rustc --explain E0038`.
|
||||||
|
|
|
||||||
|
|
@ -14,18 +14,22 @@
|
||||||
#![no_std]
|
#![no_std]
|
||||||
#![no_core]
|
#![no_core]
|
||||||
|
|
||||||
|
#[lang = "copy"]
|
||||||
|
pub trait Copy: ?Leak {}
|
||||||
|
|
||||||
#[lang = "pointee_sized"]
|
#[lang = "pointee_sized"]
|
||||||
trait PointeeSized {}
|
trait PointeeSized: ?Leak {}
|
||||||
|
|
||||||
#[lang = "meta_sized"]
|
#[lang = "meta_sized"]
|
||||||
trait MetaSized: PointeeSized {}
|
trait MetaSized: PointeeSized + ?Leak {}
|
||||||
|
|
||||||
#[lang = "sized"]
|
#[lang = "sized"]
|
||||||
trait Sized: MetaSized {}
|
trait Sized: MetaSized + ?Leak {}
|
||||||
|
|
||||||
#[lang = "legacy_receiver"]
|
#[lang = "legacy_receiver"]
|
||||||
trait LegacyReceiver {}
|
trait LegacyReceiver: ?Leak {}
|
||||||
impl<T: ?Sized + ?Leak> LegacyReceiver for &T {}
|
impl<T: ?Sized + ?Leak> LegacyReceiver for &T {}
|
||||||
|
// Omit `T: ?Leak`.
|
||||||
impl<T: ?Sized> LegacyReceiver for &mut T {}
|
impl<T: ?Sized> LegacyReceiver for &mut T {}
|
||||||
|
|
||||||
#[lang = "default_trait1"]
|
#[lang = "default_trait1"]
|
||||||
|
|
@ -38,83 +42,40 @@ struct LeakS;
|
||||||
mod supertraits {
|
mod supertraits {
|
||||||
use crate::*;
|
use crate::*;
|
||||||
|
|
||||||
trait MaybeLeakT1: ?Leak {}
|
trait MaybeLeak: ?Leak {}
|
||||||
trait MaybeLeakT2 where Self: ?Leak {}
|
impl MaybeLeak for NonLeakS {}
|
||||||
|
|
||||||
impl MaybeLeakT1 for NonLeakS {}
|
trait LeakT {}
|
||||||
impl MaybeLeakT2 for NonLeakS {}
|
impl LeakT for NonLeakS {}
|
||||||
|
//~^ ERROR the trait bound `NonLeakS: Leak` is not satisfied
|
||||||
}
|
}
|
||||||
|
|
||||||
mod maybe_self_assoc_type {
|
mod assoc_type_maybe_bounds {
|
||||||
use crate::*;
|
use crate::*;
|
||||||
|
|
||||||
trait TestBase1<T: ?Sized> {}
|
trait Test1 {
|
||||||
trait TestBase2<T: ?Leak + ?Sized> {}
|
|
||||||
|
|
||||||
trait Test1<T> {
|
|
||||||
type MaybeLeakSelf: TestBase1<Self> where Self: ?Leak;
|
|
||||||
//~^ ERROR the trait bound `Self: Leak` is not satisfied
|
|
||||||
type LeakSelf: TestBase1<Self>;
|
|
||||||
}
|
|
||||||
|
|
||||||
trait Test2<T> {
|
|
||||||
type MaybeLeakSelf: TestBase2<Self> where Self: ?Leak;
|
|
||||||
type LeakSelf: TestBase2<Self>;
|
|
||||||
}
|
|
||||||
|
|
||||||
trait Test3 {
|
|
||||||
type Leak1 = LeakS;
|
type Leak1 = LeakS;
|
||||||
type Leak2 = NonLeakS;
|
type Leak2 = NonLeakS;
|
||||||
//~^ ERROR the trait bound `NonLeakS: Leak` is not satisfied
|
//~^ ERROR the trait bound `NonLeakS: Leak` is not satisfied
|
||||||
}
|
}
|
||||||
|
|
||||||
trait Test4 {
|
trait Test2 {
|
||||||
type MaybeLeak1: ?Leak = LeakS;
|
type MaybeLeak1: ?Leak = LeakS;
|
||||||
type MaybeLeak2: ?Leak = NonLeakS;
|
type MaybeLeak2: ?Leak = NonLeakS;
|
||||||
}
|
}
|
||||||
|
|
||||||
trait Test5: ?Leak {
|
|
||||||
// ok, because assoc types have implicit where Self: Leak
|
|
||||||
type MaybeLeakSelf1: TestBase1<Self>;
|
|
||||||
type MaybeLeakSelf2: TestBase2<Self>;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
mod maybe_self_assoc_const {
|
|
||||||
use crate::*;
|
|
||||||
|
|
||||||
const fn size_of<T: ?Sized>() -> usize {
|
|
||||||
0
|
|
||||||
}
|
|
||||||
|
|
||||||
trait Trait {
|
|
||||||
const CLeak: usize = size_of::<Self>();
|
|
||||||
const CNonLeak: usize = size_of::<Self>() where Self: ?Leak;
|
|
||||||
//~^ ERROR the trait bound `Self: Leak` is not satisfied
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
mod methods {
|
mod methods {
|
||||||
use crate::*;
|
use crate::*;
|
||||||
|
|
||||||
trait Trait {
|
trait ReceiveCheck1: ?Leak {
|
||||||
fn leak_foo(&self) {}
|
fn foo(&self) {}
|
||||||
fn maybe_leak_foo(&self) where Self: ?Leak {}
|
|
||||||
fn mut_leak_foo(&mut self) {}
|
|
||||||
// there is no relax bound on corresponding Receiver impl
|
|
||||||
fn mut_maybe_leak_foo(&mut self) where Self: ?Leak {}
|
|
||||||
//~^ ERROR `&mut Self` cannot be used as the type of `self` without the `arbitrary_self_types`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Trait for NonLeakS {}
|
trait ReceiveCheck2: ?Leak {
|
||||||
impl Trait for LeakS {}
|
// There is no `?Leak` bound on corresponding `LegacyReceiver` impl.
|
||||||
|
fn mut_foo(&mut self) {}
|
||||||
fn foo() {
|
//~^ ERROR `&mut Self` cannot be used as the type of `self` without the `arbitrary_self_types`
|
||||||
LeakS.leak_foo();
|
|
||||||
LeakS.maybe_leak_foo();
|
|
||||||
NonLeakS.leak_foo();
|
|
||||||
//~^ ERROR the trait bound `NonLeakS: Leak` is not satisfied
|
|
||||||
NonLeakS.maybe_leak_foo();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,81 +1,49 @@
|
||||||
error[E0277]: the trait bound `NonLeakS: Leak` is not satisfied
|
error[E0277]: the trait bound `NonLeakS: Leak` is not satisfied
|
||||||
--> $DIR/maybe-bounds-in-traits.rs:67:22
|
--> $DIR/maybe-bounds-in-traits.rs:49:20
|
||||||
|
|
|
||||||
|
LL | impl LeakT for NonLeakS {}
|
||||||
|
| ^^^^^^^^ unsatisfied trait bound
|
||||||
|
|
|
||||||
|
help: the trait `Leak` is not implemented for `NonLeakS`
|
||||||
|
--> $DIR/maybe-bounds-in-traits.rs:38:1
|
||||||
|
|
|
||||||
|
LL | struct NonLeakS;
|
||||||
|
| ^^^^^^^^^^^^^^^
|
||||||
|
note: required by a bound in `LeakT`
|
||||||
|
--> $DIR/maybe-bounds-in-traits.rs:48:5
|
||||||
|
|
|
||||||
|
LL | trait LeakT {}
|
||||||
|
| ^^^^^^^^^^^^^^ required by this bound in `LeakT`
|
||||||
|
|
||||||
|
error[E0277]: the trait bound `NonLeakS: Leak` is not satisfied
|
||||||
|
--> $DIR/maybe-bounds-in-traits.rs:58:22
|
||||||
|
|
|
|
||||||
LL | type Leak2 = NonLeakS;
|
LL | type Leak2 = NonLeakS;
|
||||||
| ^^^^^^^^ unsatisfied trait bound
|
| ^^^^^^^^ unsatisfied trait bound
|
||||||
|
|
|
|
||||||
help: the trait `Leak` is not implemented for `NonLeakS`
|
help: the trait `Leak` is not implemented for `NonLeakS`
|
||||||
--> $DIR/maybe-bounds-in-traits.rs:34:1
|
--> $DIR/maybe-bounds-in-traits.rs:38:1
|
||||||
|
|
|
|
||||||
LL | struct NonLeakS;
|
LL | struct NonLeakS;
|
||||||
| ^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^
|
||||||
note: required by a bound in `Test3::Leak2`
|
note: required by a bound in `Test1::Leak2`
|
||||||
--> $DIR/maybe-bounds-in-traits.rs:67:9
|
--> $DIR/maybe-bounds-in-traits.rs:58:9
|
||||||
|
|
|
|
||||||
LL | type Leak2 = NonLeakS;
|
LL | type Leak2 = NonLeakS;
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Test3::Leak2`
|
| ^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Test1::Leak2`
|
||||||
|
|
||||||
error[E0277]: the trait bound `Self: Leak` is not satisfied
|
|
||||||
--> $DIR/maybe-bounds-in-traits.rs:55:29
|
|
||||||
|
|
|
||||||
LL | type MaybeLeakSelf: TestBase1<Self> where Self: ?Leak;
|
|
||||||
| ^^^^^^^^^^^^^^^ the trait `Leak` is not implemented for `Self`
|
|
||||||
|
|
|
||||||
note: required by a bound in `TestBase1`
|
|
||||||
--> $DIR/maybe-bounds-in-traits.rs:51:21
|
|
||||||
|
|
|
||||||
LL | trait TestBase1<T: ?Sized> {}
|
|
||||||
| ^ required by this bound in `TestBase1`
|
|
||||||
help: consider further restricting `Self`
|
|
||||||
|
|
|
||||||
LL | trait Test1<T>: Leak {
|
|
||||||
| ++++++
|
|
||||||
|
|
||||||
error[E0658]: `&mut Self` cannot be used as the type of `self` without the `arbitrary_self_types` feature
|
error[E0658]: `&mut Self` cannot be used as the type of `self` without the `arbitrary_self_types` feature
|
||||||
--> $DIR/maybe-bounds-in-traits.rs:105:31
|
--> $DIR/maybe-bounds-in-traits.rs:77:20
|
||||||
|
|
|
|
||||||
LL | fn mut_maybe_leak_foo(&mut self) where Self: ?Leak {}
|
LL | fn mut_foo(&mut self) {}
|
||||||
| ^^^^^^^^^
|
| ^^^^^^^^^
|
||||||
|
|
|
|
||||||
= note: see issue #44874 <https://github.com/rust-lang/rust/issues/44874> for more information
|
= note: see issue #44874 <https://github.com/rust-lang/rust/issues/44874> for more information
|
||||||
= help: add `#![feature(arbitrary_self_types)]` to the crate attributes to enable
|
= help: add `#![feature(arbitrary_self_types)]` to the crate attributes to enable
|
||||||
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
|
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
|
||||||
= help: consider changing to `self`, `&self`, `&mut self`, or a type implementing `Receiver` such as `self: Box<Self>`, `self: Rc<Self>`, or `self: Arc<Self>`
|
= help: consider changing to `self`, `&self`, `&mut self`, or a type implementing `Receiver` such as `self: Box<Self>`, `self: Rc<Self>`, or `self: Arc<Self>`
|
||||||
|
|
||||||
error[E0277]: the trait bound `Self: Leak` is not satisfied
|
error: aborting due to 3 previous errors
|
||||||
--> $DIR/maybe-bounds-in-traits.rs:92:43
|
|
||||||
|
|
|
||||||
LL | const CNonLeak: usize = size_of::<Self>() where Self: ?Leak;
|
|
||||||
| ^^^^ the trait `Leak` is not implemented for `Self`
|
|
||||||
|
|
|
||||||
note: required by a bound in `size_of`
|
|
||||||
--> $DIR/maybe-bounds-in-traits.rs:86:22
|
|
||||||
|
|
|
||||||
LL | const fn size_of<T: ?Sized>() -> usize {
|
|
||||||
| ^ required by this bound in `size_of`
|
|
||||||
help: consider further restricting `Self`
|
|
||||||
|
|
|
||||||
LL | trait Trait: Leak {
|
|
||||||
| ++++++
|
|
||||||
|
|
||||||
error[E0277]: the trait bound `NonLeakS: Leak` is not satisfied
|
|
||||||
--> $DIR/maybe-bounds-in-traits.rs:115:18
|
|
||||||
|
|
|
||||||
LL | NonLeakS.leak_foo();
|
|
||||||
| ^^^^^^^^ unsatisfied trait bound
|
|
||||||
|
|
|
||||||
help: the trait `Leak` is not implemented for `NonLeakS`
|
|
||||||
--> $DIR/maybe-bounds-in-traits.rs:34:1
|
|
||||||
|
|
|
||||||
LL | struct NonLeakS;
|
|
||||||
| ^^^^^^^^^^^^^^^
|
|
||||||
note: required by a bound in `methods::Trait::leak_foo`
|
|
||||||
--> $DIR/maybe-bounds-in-traits.rs:101:9
|
|
||||||
|
|
|
||||||
LL | fn leak_foo(&self) {}
|
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Trait::leak_foo`
|
|
||||||
|
|
||||||
error: aborting due to 5 previous errors
|
|
||||||
|
|
||||||
Some errors have detailed explanations: E0277, E0658.
|
Some errors have detailed explanations: E0277, E0658.
|
||||||
For more information about an error, try `rustc --explain E0277`.
|
For more information about an error, try `rustc --explain E0277`.
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue