Auto merge of #95501 - Dylan-DPC:rollup-arx6sdc, r=Dylan-DPC
Rollup of 6 pull requests Successful merges: - #93901 (Stabilize native library modifier syntax and the `whole-archive` modifier specifically) - #94806 (Fix `cargo run tidy`) - #94869 (Add the generic_associated_types_extended feature) - #95011 (async: Give predictable name to binding generated from .await expressions.) - #95251 (Reduce max hash in raw strings from u16 to u8) - #95298 (Fix double drop of allocator in IntoIter impl of Vec) Failed merges: r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
a39ac5ae17
@ -1616,7 +1616,7 @@ pub enum StrStyle {
|
|||||||
/// A raw string, like `r##"foo"##`.
|
/// A raw string, like `r##"foo"##`.
|
||||||
///
|
///
|
||||||
/// The value is the number of `#` symbols used.
|
/// The value is the number of `#` symbols used.
|
||||||
Raw(u16),
|
Raw(u8),
|
||||||
}
|
}
|
||||||
|
|
||||||
/// An AST literal.
|
/// An AST literal.
|
||||||
|
@ -59,9 +59,9 @@ pub enum LitKind {
|
|||||||
Integer,
|
Integer,
|
||||||
Float,
|
Float,
|
||||||
Str,
|
Str,
|
||||||
StrRaw(u16), // raw string delimited by `n` hash symbols
|
StrRaw(u8), // raw string delimited by `n` hash symbols
|
||||||
ByteStr,
|
ByteStr,
|
||||||
ByteStrRaw(u16), // raw byte string delimited by `n` hash symbols
|
ByteStrRaw(u8), // raw byte string delimited by `n` hash symbols
|
||||||
Err,
|
Err,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -618,9 +618,9 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||||||
/// Desugar `<expr>.await` into:
|
/// Desugar `<expr>.await` into:
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// match ::std::future::IntoFuture::into_future(<expr>) {
|
/// match ::std::future::IntoFuture::into_future(<expr>) {
|
||||||
/// mut pinned => loop {
|
/// mut __awaitee => loop {
|
||||||
/// match unsafe { ::std::future::Future::poll(
|
/// match unsafe { ::std::future::Future::poll(
|
||||||
/// <::std::pin::Pin>::new_unchecked(&mut pinned),
|
/// <::std::pin::Pin>::new_unchecked(&mut __awaitee),
|
||||||
/// ::std::future::get_context(task_context),
|
/// ::std::future::get_context(task_context),
|
||||||
/// ) } {
|
/// ) } {
|
||||||
/// ::std::task::Poll::Ready(result) => break result,
|
/// ::std::task::Poll::Ready(result) => break result,
|
||||||
@ -657,21 +657,24 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||||||
let expr = self.lower_expr_mut(expr);
|
let expr = self.lower_expr_mut(expr);
|
||||||
let expr_hir_id = expr.hir_id;
|
let expr_hir_id = expr.hir_id;
|
||||||
|
|
||||||
let pinned_ident = Ident::with_dummy_span(sym::pinned);
|
// Note that the name of this binding must not be changed to something else because
|
||||||
let (pinned_pat, pinned_pat_hid) =
|
// debuggers and debugger extensions expect it to be called `__awaitee`. They use
|
||||||
self.pat_ident_binding_mode(span, pinned_ident, hir::BindingAnnotation::Mutable);
|
// this name to identify what is being awaited by a suspended async functions.
|
||||||
|
let awaitee_ident = Ident::with_dummy_span(sym::__awaitee);
|
||||||
|
let (awaitee_pat, awaitee_pat_hid) =
|
||||||
|
self.pat_ident_binding_mode(span, awaitee_ident, hir::BindingAnnotation::Mutable);
|
||||||
|
|
||||||
let task_context_ident = Ident::with_dummy_span(sym::_task_context);
|
let task_context_ident = Ident::with_dummy_span(sym::_task_context);
|
||||||
|
|
||||||
// unsafe {
|
// unsafe {
|
||||||
// ::std::future::Future::poll(
|
// ::std::future::Future::poll(
|
||||||
// ::std::pin::Pin::new_unchecked(&mut pinned),
|
// ::std::pin::Pin::new_unchecked(&mut __awaitee),
|
||||||
// ::std::future::get_context(task_context),
|
// ::std::future::get_context(task_context),
|
||||||
// )
|
// )
|
||||||
// }
|
// }
|
||||||
let poll_expr = {
|
let poll_expr = {
|
||||||
let pinned = self.expr_ident(span, pinned_ident, pinned_pat_hid);
|
let awaitee = self.expr_ident(span, awaitee_ident, awaitee_pat_hid);
|
||||||
let ref_mut_pinned = self.expr_mut_addr_of(span, pinned);
|
let ref_mut_awaitee = self.expr_mut_addr_of(span, awaitee);
|
||||||
let task_context = if let Some(task_context_hid) = self.task_context {
|
let task_context = if let Some(task_context_hid) = self.task_context {
|
||||||
self.expr_ident_mut(span, task_context_ident, task_context_hid)
|
self.expr_ident_mut(span, task_context_ident, task_context_hid)
|
||||||
} else {
|
} else {
|
||||||
@ -681,7 +684,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||||||
let new_unchecked = self.expr_call_lang_item_fn_mut(
|
let new_unchecked = self.expr_call_lang_item_fn_mut(
|
||||||
span,
|
span,
|
||||||
hir::LangItem::PinNewUnchecked,
|
hir::LangItem::PinNewUnchecked,
|
||||||
arena_vec![self; ref_mut_pinned],
|
arena_vec![self; ref_mut_awaitee],
|
||||||
Some(expr_hir_id),
|
Some(expr_hir_id),
|
||||||
);
|
);
|
||||||
let get_context = self.expr_call_lang_item_fn_mut(
|
let get_context = self.expr_call_lang_item_fn_mut(
|
||||||
@ -782,8 +785,8 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||||||
span: self.lower_span(span),
|
span: self.lower_span(span),
|
||||||
});
|
});
|
||||||
|
|
||||||
// mut pinned => loop { ... }
|
// mut __awaitee => loop { ... }
|
||||||
let pinned_arm = self.arm(pinned_pat, loop_expr);
|
let awaitee_arm = self.arm(awaitee_pat, loop_expr);
|
||||||
|
|
||||||
// `match ::std::future::IntoFuture::into_future(<expr>) { ... }`
|
// `match ::std::future::IntoFuture::into_future(<expr>) { ... }`
|
||||||
let into_future_span = self.mark_span_with_reason(
|
let into_future_span = self.mark_span_with_reason(
|
||||||
@ -799,11 +802,11 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||||||
);
|
);
|
||||||
|
|
||||||
// match <into_future_expr> {
|
// match <into_future_expr> {
|
||||||
// mut pinned => loop { .. }
|
// mut __awaitee => loop { .. }
|
||||||
// }
|
// }
|
||||||
hir::ExprKind::Match(
|
hir::ExprKind::Match(
|
||||||
into_future_expr,
|
into_future_expr,
|
||||||
arena_vec![self; pinned_arm],
|
arena_vec![self; awaitee_arm],
|
||||||
hir::MatchSource::AwaitDesugar,
|
hir::MatchSource::AwaitDesugar,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -387,13 +387,6 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
|
|||||||
if attr.has_name(sym::link) {
|
if attr.has_name(sym::link) {
|
||||||
for nested_meta in attr.meta_item_list().unwrap_or_default() {
|
for nested_meta in attr.meta_item_list().unwrap_or_default() {
|
||||||
if nested_meta.has_name(sym::modifiers) {
|
if nested_meta.has_name(sym::modifiers) {
|
||||||
gate_feature_post!(
|
|
||||||
self,
|
|
||||||
native_link_modifiers,
|
|
||||||
nested_meta.span(),
|
|
||||||
"native link modifiers are experimental"
|
|
||||||
);
|
|
||||||
|
|
||||||
if let Some(modifiers) = nested_meta.value_str() {
|
if let Some(modifiers) = nested_meta.value_str() {
|
||||||
for modifier in modifiers.as_str().split(',') {
|
for modifier in modifiers.as_str().split(',') {
|
||||||
if let Some(modifier) = modifier.strip_prefix(&['+', '-']) {
|
if let Some(modifier) = modifier.strip_prefix(&['+', '-']) {
|
||||||
@ -412,7 +405,6 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
|
|||||||
gate_modifier!(
|
gate_modifier!(
|
||||||
"bundle" => native_link_modifiers_bundle
|
"bundle" => native_link_modifiers_bundle
|
||||||
"verbatim" => native_link_modifiers_verbatim
|
"verbatim" => native_link_modifiers_verbatim
|
||||||
"whole-archive" => native_link_modifiers_whole_archive
|
|
||||||
"as-needed" => native_link_modifiers_as_needed
|
"as-needed" => native_link_modifiers_as_needed
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -1844,7 +1844,7 @@ fn linker_with_args<'a, B: ArchiveBuilder<'a>>(
|
|||||||
// This change is somewhat breaking in practice due to local static libraries being linked
|
// This change is somewhat breaking in practice due to local static libraries being linked
|
||||||
// as whole-archive (#85144), so removing whole-archive may be a pre-requisite.
|
// as whole-archive (#85144), so removing whole-archive may be a pre-requisite.
|
||||||
if sess.opts.debugging_opts.link_native_libraries {
|
if sess.opts.debugging_opts.link_native_libraries {
|
||||||
add_local_native_libraries(cmd, sess, codegen_results);
|
add_local_native_libraries(cmd, sess, codegen_results, crate_type);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Upstream rust libraries and their nobundle static libraries
|
// Upstream rust libraries and their nobundle static libraries
|
||||||
@ -2016,6 +2016,16 @@ fn add_order_independent_options(
|
|||||||
add_rpath_args(cmd, sess, codegen_results, out_filename);
|
add_rpath_args(cmd, sess, codegen_results, out_filename);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// A dylib may reexport symbols from the linked rlib or native static library.
|
||||||
|
// Even if some symbol is reexported it's still not necessarily counted as used and may be
|
||||||
|
// dropped, at least with `ld`-like ELF linkers. So we have to link some rlibs and static
|
||||||
|
// libraries as whole-archive to avoid losing reexported symbols.
|
||||||
|
// FIXME: Find a way to mark reexported symbols as used and avoid this use of whole-archive.
|
||||||
|
fn default_to_whole_archive(sess: &Session, crate_type: CrateType, cmd: &dyn Linker) -> bool {
|
||||||
|
crate_type == CrateType::Dylib
|
||||||
|
&& !(sess.target.limit_rdylib_exports && cmd.exported_symbol_means_used_symbol())
|
||||||
|
}
|
||||||
|
|
||||||
/// # Native library linking
|
/// # Native library linking
|
||||||
///
|
///
|
||||||
/// User-supplied library search paths (-L on the command line). These are the same paths used to
|
/// User-supplied library search paths (-L on the command line). These are the same paths used to
|
||||||
@ -2029,6 +2039,7 @@ fn add_local_native_libraries(
|
|||||||
cmd: &mut dyn Linker,
|
cmd: &mut dyn Linker,
|
||||||
sess: &Session,
|
sess: &Session,
|
||||||
codegen_results: &CodegenResults,
|
codegen_results: &CodegenResults,
|
||||||
|
crate_type: CrateType,
|
||||||
) {
|
) {
|
||||||
let filesearch = sess.target_filesearch(PathKind::All);
|
let filesearch = sess.target_filesearch(PathKind::All);
|
||||||
for search_path in filesearch.search_paths() {
|
for search_path in filesearch.search_paths() {
|
||||||
@ -2046,14 +2057,18 @@ fn add_local_native_libraries(
|
|||||||
codegen_results.crate_info.used_libraries.iter().filter(|l| relevant_lib(sess, l));
|
codegen_results.crate_info.used_libraries.iter().filter(|l| relevant_lib(sess, l));
|
||||||
|
|
||||||
let search_path = OnceCell::new();
|
let search_path = OnceCell::new();
|
||||||
let mut last = (NativeLibKind::Unspecified, None);
|
let mut last = (None, NativeLibKind::Unspecified, None);
|
||||||
for lib in relevant_libs {
|
for lib in relevant_libs {
|
||||||
let Some(name) = lib.name else {
|
let Some(name) = lib.name else {
|
||||||
continue;
|
continue;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Skip if this library is the same as the last.
|
// Skip if this library is the same as the last.
|
||||||
last = if (lib.kind, lib.name) == last { continue } else { (lib.kind, lib.name) };
|
last = if (lib.name, lib.kind, lib.verbatim) == last {
|
||||||
|
continue;
|
||||||
|
} else {
|
||||||
|
(lib.name, lib.kind, lib.verbatim)
|
||||||
|
};
|
||||||
|
|
||||||
let verbatim = lib.verbatim.unwrap_or(false);
|
let verbatim = lib.verbatim.unwrap_or(false);
|
||||||
match lib.kind {
|
match lib.kind {
|
||||||
@ -2064,15 +2079,19 @@ fn add_local_native_libraries(
|
|||||||
NativeLibKind::Framework { as_needed } => {
|
NativeLibKind::Framework { as_needed } => {
|
||||||
cmd.link_framework(name, as_needed.unwrap_or(true))
|
cmd.link_framework(name, as_needed.unwrap_or(true))
|
||||||
}
|
}
|
||||||
NativeLibKind::Static { bundle: None | Some(true), .. }
|
NativeLibKind::Static { whole_archive, .. } => {
|
||||||
| NativeLibKind::Static { whole_archive: Some(true), .. } => {
|
if whole_archive == Some(true)
|
||||||
cmd.link_whole_staticlib(
|
|| (whole_archive == None && default_to_whole_archive(sess, crate_type, cmd))
|
||||||
name,
|
{
|
||||||
verbatim,
|
cmd.link_whole_staticlib(
|
||||||
&search_path.get_or_init(|| archive_search_paths(sess)),
|
name,
|
||||||
);
|
verbatim,
|
||||||
|
&search_path.get_or_init(|| archive_search_paths(sess)),
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
cmd.link_staticlib(name, verbatim)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
NativeLibKind::Static { .. } => cmd.link_staticlib(name, verbatim),
|
|
||||||
NativeLibKind::RawDylib => {
|
NativeLibKind::RawDylib => {
|
||||||
// FIXME(#58713): Proper handling for raw dylibs.
|
// FIXME(#58713): Proper handling for raw dylibs.
|
||||||
bug!("raw_dylib feature not yet implemented");
|
bug!("raw_dylib feature not yet implemented");
|
||||||
@ -2197,34 +2216,37 @@ fn add_upstream_rust_crates<'a, B: ArchiveBuilder<'a>>(
|
|||||||
// external build system already has the native dependencies defined, and it
|
// external build system already has the native dependencies defined, and it
|
||||||
// will provide them to the linker itself.
|
// will provide them to the linker itself.
|
||||||
if sess.opts.debugging_opts.link_native_libraries {
|
if sess.opts.debugging_opts.link_native_libraries {
|
||||||
let mut last = None;
|
let mut last = (None, NativeLibKind::Unspecified, None);
|
||||||
for lib in &codegen_results.crate_info.native_libraries[&cnum] {
|
for lib in &codegen_results.crate_info.native_libraries[&cnum] {
|
||||||
|
let Some(name) = lib.name else {
|
||||||
|
continue;
|
||||||
|
};
|
||||||
if !relevant_lib(sess, lib) {
|
if !relevant_lib(sess, lib) {
|
||||||
// Skip libraries if they are disabled by `#[link(cfg=...)]`
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Skip if this library is the same as the last.
|
// Skip if this library is the same as the last.
|
||||||
if last == lib.name {
|
last = if (lib.name, lib.kind, lib.verbatim) == last {
|
||||||
continue;
|
continue;
|
||||||
}
|
} else {
|
||||||
|
(lib.name, lib.kind, lib.verbatim)
|
||||||
|
};
|
||||||
|
|
||||||
if let Some(static_lib_name) = lib.name {
|
if let NativeLibKind::Static { bundle: Some(false), whole_archive } =
|
||||||
if let NativeLibKind::Static { bundle: Some(false), whole_archive } =
|
lib.kind
|
||||||
lib.kind
|
{
|
||||||
|
let verbatim = lib.verbatim.unwrap_or(false);
|
||||||
|
if whole_archive == Some(true)
|
||||||
|
|| (whole_archive == None
|
||||||
|
&& default_to_whole_archive(sess, crate_type, cmd))
|
||||||
{
|
{
|
||||||
let verbatim = lib.verbatim.unwrap_or(false);
|
cmd.link_whole_staticlib(
|
||||||
if whole_archive == Some(true) {
|
name,
|
||||||
cmd.link_whole_staticlib(
|
verbatim,
|
||||||
static_lib_name,
|
search_path.get_or_init(|| archive_search_paths(sess)),
|
||||||
verbatim,
|
);
|
||||||
search_path.get_or_init(|| archive_search_paths(sess)),
|
} else {
|
||||||
);
|
cmd.link_staticlib(name, verbatim);
|
||||||
} else {
|
|
||||||
cmd.link_staticlib(static_lib_name, verbatim);
|
|
||||||
}
|
|
||||||
|
|
||||||
last = lib.name;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2282,15 +2304,10 @@ fn add_upstream_rust_crates<'a, B: ArchiveBuilder<'a>>(
|
|||||||
let cratepath = &src.rlib.as_ref().unwrap().0;
|
let cratepath = &src.rlib.as_ref().unwrap().0;
|
||||||
|
|
||||||
let mut link_upstream = |path: &Path| {
|
let mut link_upstream = |path: &Path| {
|
||||||
// If we're creating a dylib, then we need to include the
|
// We don't want to include the whole compiler-builtins crate (e.g., compiler-rt)
|
||||||
// whole of each object in our archive into that artifact. This is
|
// regardless of the default because it'll get repeatedly linked anyway.
|
||||||
// because a `dylib` can be reused as an intermediate artifact.
|
|
||||||
//
|
|
||||||
// Note, though, that we don't want to include the whole of a
|
|
||||||
// compiler-builtins crate (e.g., compiler-rt) because it'll get
|
|
||||||
// repeatedly linked anyway.
|
|
||||||
let path = fix_windows_verbatim_for_gcc(path);
|
let path = fix_windows_verbatim_for_gcc(path);
|
||||||
if crate_type == CrateType::Dylib
|
if default_to_whole_archive(sess, crate_type, cmd)
|
||||||
&& codegen_results.crate_info.compiler_builtins != Some(cnum)
|
&& codegen_results.crate_info.compiler_builtins != Some(cnum)
|
||||||
{
|
{
|
||||||
cmd.link_whole_rlib(&path);
|
cmd.link_whole_rlib(&path);
|
||||||
@ -2401,7 +2418,7 @@ fn add_upstream_native_libraries(
|
|||||||
sess: &Session,
|
sess: &Session,
|
||||||
codegen_results: &CodegenResults,
|
codegen_results: &CodegenResults,
|
||||||
) {
|
) {
|
||||||
let mut last = (NativeLibKind::Unspecified, None);
|
let mut last = (None, NativeLibKind::Unspecified, None);
|
||||||
for &cnum in &codegen_results.crate_info.used_crates {
|
for &cnum in &codegen_results.crate_info.used_crates {
|
||||||
for lib in codegen_results.crate_info.native_libraries[&cnum].iter() {
|
for lib in codegen_results.crate_info.native_libraries[&cnum].iter() {
|
||||||
let Some(name) = lib.name else {
|
let Some(name) = lib.name else {
|
||||||
@ -2412,7 +2429,11 @@ fn add_upstream_native_libraries(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Skip if this library is the same as the last.
|
// Skip if this library is the same as the last.
|
||||||
last = if (lib.kind, lib.name) == last { continue } else { (lib.kind, lib.name) };
|
last = if (lib.name, lib.kind, lib.verbatim) == last {
|
||||||
|
continue;
|
||||||
|
} else {
|
||||||
|
(lib.name, lib.kind, lib.verbatim)
|
||||||
|
};
|
||||||
|
|
||||||
let verbatim = lib.verbatim.unwrap_or(false);
|
let verbatim = lib.verbatim.unwrap_or(false);
|
||||||
match lib.kind {
|
match lib.kind {
|
||||||
|
@ -186,6 +186,9 @@ pub trait Linker {
|
|||||||
fn no_crt_objects(&mut self);
|
fn no_crt_objects(&mut self);
|
||||||
fn no_default_libraries(&mut self);
|
fn no_default_libraries(&mut self);
|
||||||
fn export_symbols(&mut self, tmpdir: &Path, crate_type: CrateType, symbols: &[String]);
|
fn export_symbols(&mut self, tmpdir: &Path, crate_type: CrateType, symbols: &[String]);
|
||||||
|
fn exported_symbol_means_used_symbol(&self) -> bool {
|
||||||
|
true
|
||||||
|
}
|
||||||
fn subsystem(&mut self, subsystem: &str);
|
fn subsystem(&mut self, subsystem: &str);
|
||||||
fn group_start(&mut self);
|
fn group_start(&mut self);
|
||||||
fn group_end(&mut self);
|
fn group_end(&mut self);
|
||||||
@ -724,6 +727,10 @@ impl<'a> Linker for GccLinker<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn exported_symbol_means_used_symbol(&self) -> bool {
|
||||||
|
self.sess.target.is_like_windows || self.sess.target.is_like_osx
|
||||||
|
}
|
||||||
|
|
||||||
fn subsystem(&mut self, subsystem: &str) {
|
fn subsystem(&mut self, subsystem: &str) {
|
||||||
self.linker_arg("--subsystem");
|
self.linker_arg("--subsystem");
|
||||||
self.linker_arg(&subsystem);
|
self.linker_arg(&subsystem);
|
||||||
@ -1471,6 +1478,10 @@ impl<'a> Linker for L4Bender<'a> {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn exported_symbol_means_used_symbol(&self) -> bool {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|
||||||
fn subsystem(&mut self, subsystem: &str) {
|
fn subsystem(&mut self, subsystem: &str) {
|
||||||
self.cmd.arg(&format!("--subsystem {}", subsystem));
|
self.cmd.arg(&format!("--subsystem {}", subsystem));
|
||||||
}
|
}
|
||||||
|
@ -215,6 +215,10 @@ declare_features! (
|
|||||||
/// Allows patterns with concurrent by-move and by-ref bindings.
|
/// Allows patterns with concurrent by-move and by-ref bindings.
|
||||||
/// For example, you can write `Foo(a, ref b)` where `a` is by-move and `b` is by-ref.
|
/// For example, you can write `Foo(a, ref b)` where `a` is by-move and `b` is by-ref.
|
||||||
(accepted, move_ref_pattern, "1.49.0", Some(68354), None),
|
(accepted, move_ref_pattern, "1.49.0", Some(68354), None),
|
||||||
|
/// Allows specifying modifiers in the link attribute: `#[link(modifiers = "...")]`
|
||||||
|
(accepted, native_link_modifiers, "1.61.0", Some(81490), None),
|
||||||
|
/// Allows specifying the whole-archive link modifier
|
||||||
|
(accepted, native_link_modifiers_whole_archive, "1.61.0", Some(81490), None),
|
||||||
/// Allows using `#![no_std]`.
|
/// Allows using `#![no_std]`.
|
||||||
(accepted, no_std, "1.6.0", None, None),
|
(accepted, no_std, "1.6.0", None, None),
|
||||||
/// Allows defining identifiers beyond ASCII.
|
/// Allows defining identifiers beyond ASCII.
|
||||||
|
@ -400,6 +400,8 @@ declare_features! (
|
|||||||
(active, generic_arg_infer, "1.55.0", Some(85077), None),
|
(active, generic_arg_infer, "1.55.0", Some(85077), None),
|
||||||
/// Allows associated types to be generic, e.g., `type Foo<T>;` (RFC 1598).
|
/// Allows associated types to be generic, e.g., `type Foo<T>;` (RFC 1598).
|
||||||
(active, generic_associated_types, "1.23.0", Some(44265), None),
|
(active, generic_associated_types, "1.23.0", Some(44265), None),
|
||||||
|
/// An extension to the `generic_associated_types` feature, allowing incomplete features.
|
||||||
|
(incomplete, generic_associated_types_extended, "1.61.0", Some(95451), None),
|
||||||
/// Allows non-trivial generic constants which have to have wfness manually propagated to callers
|
/// Allows non-trivial generic constants which have to have wfness manually propagated to callers
|
||||||
(incomplete, generic_const_exprs, "1.56.0", Some(76560), None),
|
(incomplete, generic_const_exprs, "1.56.0", Some(76560), None),
|
||||||
/// Allows using `..X`, `..=X`, `...X`, and `X..` as a pattern.
|
/// Allows using `..X`, `..=X`, `...X`, and `X..` as a pattern.
|
||||||
@ -446,16 +448,12 @@ declare_features! (
|
|||||||
(active, must_not_suspend, "1.57.0", Some(83310), None),
|
(active, must_not_suspend, "1.57.0", Some(83310), None),
|
||||||
/// Allows using `#[naked]` on functions.
|
/// Allows using `#[naked]` on functions.
|
||||||
(active, naked_functions, "1.9.0", Some(32408), None),
|
(active, naked_functions, "1.9.0", Some(32408), None),
|
||||||
/// Allows specifying modifiers in the link attribute: `#[link(modifiers = "...")]`
|
|
||||||
(active, native_link_modifiers, "1.53.0", Some(81490), None),
|
|
||||||
/// Allows specifying the as-needed link modifier
|
/// Allows specifying the as-needed link modifier
|
||||||
(active, native_link_modifiers_as_needed, "1.53.0", Some(81490), None),
|
(active, native_link_modifiers_as_needed, "1.53.0", Some(81490), None),
|
||||||
/// Allows specifying the bundle link modifier
|
/// Allows specifying the bundle link modifier
|
||||||
(active, native_link_modifiers_bundle, "1.53.0", Some(81490), None),
|
(active, native_link_modifiers_bundle, "1.53.0", Some(81490), None),
|
||||||
/// Allows specifying the verbatim link modifier
|
/// Allows specifying the verbatim link modifier
|
||||||
(active, native_link_modifiers_verbatim, "1.53.0", Some(81490), None),
|
(active, native_link_modifiers_verbatim, "1.53.0", Some(81490), None),
|
||||||
/// Allows specifying the whole-archive link modifier
|
|
||||||
(active, native_link_modifiers_whole_archive, "1.53.0", Some(81490), None),
|
|
||||||
/// Allow negative trait implementations.
|
/// Allow negative trait implementations.
|
||||||
(active, negative_impls, "1.44.0", Some(68318), None),
|
(active, negative_impls, "1.44.0", Some(68318), None),
|
||||||
/// Allows the `!` type. Does not imply 'exhaustive_patterns' (below) any more.
|
/// Allows the `!` type. Does not imply 'exhaustive_patterns' (below) any more.
|
||||||
|
@ -161,15 +161,15 @@ pub enum LiteralKind {
|
|||||||
/// "b"abc"", "b"abc"
|
/// "b"abc"", "b"abc"
|
||||||
ByteStr { terminated: bool },
|
ByteStr { terminated: bool },
|
||||||
/// "r"abc"", "r#"abc"#", "r####"ab"###"c"####", "r#"a"
|
/// "r"abc"", "r#"abc"#", "r####"ab"###"c"####", "r#"a"
|
||||||
RawStr { n_hashes: u16, err: Option<RawStrError> },
|
RawStr { n_hashes: u8, err: Option<RawStrError> },
|
||||||
/// "br"abc"", "br#"abc"#", "br####"ab"###"c"####", "br#"a"
|
/// "br"abc"", "br#"abc"#", "br####"ab"###"c"####", "br#"a"
|
||||||
RawByteStr { n_hashes: u16, err: Option<RawStrError> },
|
RawByteStr { n_hashes: u8, err: Option<RawStrError> },
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Error produced validating a raw string. Represents cases like:
|
/// Error produced validating a raw string. Represents cases like:
|
||||||
/// - `r##~"abcde"##`: `InvalidStarter`
|
/// - `r##~"abcde"##`: `InvalidStarter`
|
||||||
/// - `r###"abcde"##`: `NoTerminator { expected: 3, found: 2, possible_terminator_offset: Some(11)`
|
/// - `r###"abcde"##`: `NoTerminator { expected: 3, found: 2, possible_terminator_offset: Some(11)`
|
||||||
/// - Too many `#`s (>65535): `TooManyDelimiters`
|
/// - Too many `#`s (>255): `TooManyDelimiters`
|
||||||
// perf note: It doesn't matter that this makes `Token` 36 bytes bigger. See #77629
|
// perf note: It doesn't matter that this makes `Token` 36 bytes bigger. See #77629
|
||||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)]
|
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)]
|
||||||
pub enum RawStrError {
|
pub enum RawStrError {
|
||||||
@ -178,7 +178,7 @@ pub enum RawStrError {
|
|||||||
/// The string was never terminated. `possible_terminator_offset` is the number of characters after `r` or `br` where they
|
/// The string was never terminated. `possible_terminator_offset` is the number of characters after `r` or `br` where they
|
||||||
/// may have intended to terminate it.
|
/// may have intended to terminate it.
|
||||||
NoTerminator { expected: usize, found: usize, possible_terminator_offset: Option<usize> },
|
NoTerminator { expected: usize, found: usize, possible_terminator_offset: Option<usize> },
|
||||||
/// More than 65535 `#`s exist.
|
/// More than 255 `#`s exist.
|
||||||
TooManyDelimiters { found: usize },
|
TooManyDelimiters { found: usize },
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -698,12 +698,12 @@ impl Cursor<'_> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Eats the double-quoted string and returns `n_hashes` and an error if encountered.
|
/// Eats the double-quoted string and returns `n_hashes` and an error if encountered.
|
||||||
fn raw_double_quoted_string(&mut self, prefix_len: usize) -> (u16, Option<RawStrError>) {
|
fn raw_double_quoted_string(&mut self, prefix_len: usize) -> (u8, Option<RawStrError>) {
|
||||||
// Wrap the actual function to handle the error with too many hashes.
|
// Wrap the actual function to handle the error with too many hashes.
|
||||||
// This way, it eats the whole raw string.
|
// This way, it eats the whole raw string.
|
||||||
let (n_hashes, err) = self.raw_string_unvalidated(prefix_len);
|
let (n_hashes, err) = self.raw_string_unvalidated(prefix_len);
|
||||||
// Only up to 65535 `#`s are allowed in raw strings
|
// Only up to 255 `#`s are allowed in raw strings
|
||||||
match u16::try_from(n_hashes) {
|
match u8::try_from(n_hashes) {
|
||||||
Ok(num) => (num, err),
|
Ok(num) => (num, err),
|
||||||
// We lie about the number of hashes here :P
|
// We lie about the number of hashes here :P
|
||||||
Err(_) => (0, Some(RawStrError::TooManyDelimiters { found: n_hashes })),
|
Err(_) => (0, Some(RawStrError::TooManyDelimiters { found: n_hashes })),
|
||||||
|
@ -2,7 +2,7 @@ use super::*;
|
|||||||
|
|
||||||
use expect_test::{expect, Expect};
|
use expect_test::{expect, Expect};
|
||||||
|
|
||||||
fn check_raw_str(s: &str, expected_hashes: u16, expected_err: Option<RawStrError>) {
|
fn check_raw_str(s: &str, expected_hashes: u8, expected_err: Option<RawStrError>) {
|
||||||
let s = &format!("r{}", s);
|
let s = &format!("r{}", s);
|
||||||
let mut cursor = Cursor::new(s);
|
let mut cursor = Cursor::new(s);
|
||||||
cursor.bump();
|
cursor.bump();
|
||||||
@ -68,13 +68,13 @@ fn test_unterminated_no_pound() {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_too_many_hashes() {
|
fn test_too_many_hashes() {
|
||||||
let max_count = u16::MAX;
|
let max_count = u8::MAX;
|
||||||
let mut hashes: String = "#".repeat(max_count.into());
|
let mut hashes: String = "#".repeat(max_count.into());
|
||||||
|
|
||||||
// Valid number of hashes (65535 = 2^16 - 1), but invalid string.
|
// Valid number of hashes (255 = 2^8 - 1 = u8::MAX), but invalid string.
|
||||||
check_raw_str(&hashes, max_count, Some(RawStrError::InvalidStarter { bad_char: '\u{0}' }));
|
check_raw_str(&hashes, max_count, Some(RawStrError::InvalidStarter { bad_char: '\u{0}' }));
|
||||||
|
|
||||||
// One more hash sign (65536 = 2^16) becomes too many.
|
// One more hash sign (256 = 2^8) becomes too many.
|
||||||
hashes.push('#');
|
hashes.push('#');
|
||||||
check_raw_str(
|
check_raw_str(
|
||||||
&hashes,
|
&hashes,
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
#![feature(nll)]
|
#![feature(nll)]
|
||||||
#![feature(native_link_modifiers)]
|
#![cfg_attr(bootstrap, feature(native_link_modifiers))]
|
||||||
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
|
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
|
||||||
|
|
||||||
// NOTE: This crate only exists to allow linking on mingw targets.
|
// NOTE: This crate only exists to allow linking on mingw targets.
|
||||||
|
@ -125,13 +125,18 @@ impl<'tcx> ItemLikeVisitor<'tcx> for Collector<'tcx> {
|
|||||||
|
|
||||||
// Do this outside the above loop so we don't depend on modifiers coming
|
// Do this outside the above loop so we don't depend on modifiers coming
|
||||||
// after kinds
|
// after kinds
|
||||||
if let Some(item) = items.iter().find(|item| item.has_name(sym::modifiers)) {
|
let mut modifiers_count = 0;
|
||||||
|
for item in items.iter().filter(|item| item.has_name(sym::modifiers)) {
|
||||||
if let Some(modifiers) = item.value_str() {
|
if let Some(modifiers) = item.value_str() {
|
||||||
|
modifiers_count += 1;
|
||||||
let span = item.name_value_literal_span().unwrap();
|
let span = item.name_value_literal_span().unwrap();
|
||||||
|
let mut has_duplicate_modifiers = false;
|
||||||
for modifier in modifiers.as_str().split(',') {
|
for modifier in modifiers.as_str().split(',') {
|
||||||
let (modifier, value) = match modifier.strip_prefix(&['+', '-']) {
|
let (modifier, value) = match modifier.strip_prefix(&['+', '-']) {
|
||||||
Some(m) => (m, modifier.starts_with('+')),
|
Some(m) => (m, modifier.starts_with('+')),
|
||||||
None => {
|
None => {
|
||||||
|
// Note: this error also excludes the case with empty modifier
|
||||||
|
// string, like `modifiers = ""`.
|
||||||
sess.span_err(
|
sess.span_err(
|
||||||
span,
|
span,
|
||||||
"invalid linking modifier syntax, expected '+' or '-' prefix \
|
"invalid linking modifier syntax, expected '+' or '-' prefix \
|
||||||
@ -143,6 +148,9 @@ impl<'tcx> ItemLikeVisitor<'tcx> for Collector<'tcx> {
|
|||||||
|
|
||||||
match (modifier, &mut lib.kind) {
|
match (modifier, &mut lib.kind) {
|
||||||
("bundle", NativeLibKind::Static { bundle, .. }) => {
|
("bundle", NativeLibKind::Static { bundle, .. }) => {
|
||||||
|
if bundle.is_some() {
|
||||||
|
has_duplicate_modifiers = true;
|
||||||
|
}
|
||||||
*bundle = Some(value);
|
*bundle = Some(value);
|
||||||
}
|
}
|
||||||
("bundle", _) => {
|
("bundle", _) => {
|
||||||
@ -153,9 +161,17 @@ impl<'tcx> ItemLikeVisitor<'tcx> for Collector<'tcx> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
("verbatim", _) => lib.verbatim = Some(value),
|
("verbatim", _) => {
|
||||||
|
if lib.verbatim.is_some() {
|
||||||
|
has_duplicate_modifiers = true;
|
||||||
|
}
|
||||||
|
lib.verbatim = Some(value);
|
||||||
|
}
|
||||||
|
|
||||||
("whole-archive", NativeLibKind::Static { whole_archive, .. }) => {
|
("whole-archive", NativeLibKind::Static { whole_archive, .. }) => {
|
||||||
|
if whole_archive.is_some() {
|
||||||
|
has_duplicate_modifiers = true;
|
||||||
|
}
|
||||||
*whole_archive = Some(value);
|
*whole_archive = Some(value);
|
||||||
}
|
}
|
||||||
("whole-archive", _) => {
|
("whole-archive", _) => {
|
||||||
@ -168,6 +184,9 @@ impl<'tcx> ItemLikeVisitor<'tcx> for Collector<'tcx> {
|
|||||||
|
|
||||||
("as-needed", NativeLibKind::Dylib { as_needed })
|
("as-needed", NativeLibKind::Dylib { as_needed })
|
||||||
| ("as-needed", NativeLibKind::Framework { as_needed }) => {
|
| ("as-needed", NativeLibKind::Framework { as_needed }) => {
|
||||||
|
if as_needed.is_some() {
|
||||||
|
has_duplicate_modifiers = true;
|
||||||
|
}
|
||||||
*as_needed = Some(value);
|
*as_needed = Some(value);
|
||||||
}
|
}
|
||||||
("as-needed", _) => {
|
("as-needed", _) => {
|
||||||
@ -190,12 +209,22 @@ impl<'tcx> ItemLikeVisitor<'tcx> for Collector<'tcx> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if has_duplicate_modifiers {
|
||||||
|
let msg =
|
||||||
|
"same modifier is used multiple times in a single `modifiers` argument";
|
||||||
|
sess.span_err(item.span(), msg);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
let msg = "must be of the form `#[link(modifiers = \"...\")]`";
|
let msg = "must be of the form `#[link(modifiers = \"...\")]`";
|
||||||
sess.span_err(item.span(), msg);
|
sess.span_err(item.span(), msg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if modifiers_count > 1 {
|
||||||
|
let msg = "multiple `modifiers` arguments in a single `#[link]` attribute";
|
||||||
|
sess.span_err(m.span, msg);
|
||||||
|
}
|
||||||
|
|
||||||
// In general we require #[link(name = "...")] but we allow
|
// In general we require #[link(name = "...")] but we allow
|
||||||
// #[link(wasm_import_module = "...")] without the `name`.
|
// #[link(wasm_import_module = "...")] without the `name`.
|
||||||
let requires_name = kind_specified || lib.wasm_import_module.is_none();
|
let requires_name = kind_specified || lib.wasm_import_module.is_none();
|
||||||
@ -349,6 +378,15 @@ impl Collector<'_> {
|
|||||||
.drain_filter(|lib| {
|
.drain_filter(|lib| {
|
||||||
if let Some(lib_name) = lib.name {
|
if let Some(lib_name) = lib.name {
|
||||||
if lib_name.as_str() == passed_lib.name {
|
if lib_name.as_str() == passed_lib.name {
|
||||||
|
// FIXME: This whole logic is questionable, whether modifiers are
|
||||||
|
// involved or not, library reordering and kind overriding without
|
||||||
|
// explicit `:rename` in particular.
|
||||||
|
if lib.has_modifiers() || passed_lib.has_modifiers() {
|
||||||
|
self.tcx.sess.span_err(
|
||||||
|
self.tcx.def_span(lib.foreign_module.unwrap()),
|
||||||
|
"overriding linking modifiers from command line is not supported"
|
||||||
|
);
|
||||||
|
}
|
||||||
if passed_lib.kind != NativeLibKind::Unspecified {
|
if passed_lib.kind != NativeLibKind::Unspecified {
|
||||||
lib.kind = passed_lib.kind;
|
lib.kind = passed_lib.kind;
|
||||||
}
|
}
|
||||||
|
@ -1379,3 +1379,50 @@ impl<'tcx> TypeVisitor<'tcx> for LateBoundRegionsCollector {
|
|||||||
ControlFlow::CONTINUE
|
ControlFlow::CONTINUE
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Finds the max universe present
|
||||||
|
pub struct MaxUniverse {
|
||||||
|
max_universe: ty::UniverseIndex,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl MaxUniverse {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
MaxUniverse { max_universe: ty::UniverseIndex::ROOT }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn max_universe(self) -> ty::UniverseIndex {
|
||||||
|
self.max_universe
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'tcx> TypeVisitor<'tcx> for MaxUniverse {
|
||||||
|
fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
|
||||||
|
if let ty::Placeholder(placeholder) = t.kind() {
|
||||||
|
self.max_universe = ty::UniverseIndex::from_u32(
|
||||||
|
self.max_universe.as_u32().max(placeholder.universe.as_u32()),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
t.super_visit_with(self)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_const(&mut self, c: ty::consts::Const<'tcx>) -> ControlFlow<Self::BreakTy> {
|
||||||
|
if let ty::ConstKind::Placeholder(placeholder) = c.val() {
|
||||||
|
self.max_universe = ty::UniverseIndex::from_u32(
|
||||||
|
self.max_universe.as_u32().max(placeholder.universe.as_u32()),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
c.super_visit_with(self)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow<Self::BreakTy> {
|
||||||
|
if let ty::RePlaceholder(placeholder) = *r {
|
||||||
|
self.max_universe = ty::UniverseIndex::from_u32(
|
||||||
|
self.max_universe.as_u32().max(placeholder.universe.as_u32()),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
ControlFlow::CONTINUE
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -597,15 +597,13 @@ impl<'a> StringReader<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Note: It was decided to not add a test case, because it would be too big.
|
|
||||||
/// <https://github.com/rust-lang/rust/pull/50296#issuecomment-392135180>
|
|
||||||
fn report_too_many_hashes(&self, start: BytePos, found: usize) -> ! {
|
fn report_too_many_hashes(&self, start: BytePos, found: usize) -> ! {
|
||||||
self.fatal_span_(
|
self.fatal_span_(
|
||||||
start,
|
start,
|
||||||
self.pos,
|
self.pos,
|
||||||
&format!(
|
&format!(
|
||||||
"too many `#` symbols: raw strings may be delimited \
|
"too many `#` symbols: raw strings may be delimited \
|
||||||
by up to 65535 `#` symbols, but found {}",
|
by up to 255 `#` symbols, but found {}",
|
||||||
found
|
found
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
@ -1948,9 +1948,6 @@ fn parse_native_lib_kind(
|
|||||||
kind: &str,
|
kind: &str,
|
||||||
error_format: ErrorOutputType,
|
error_format: ErrorOutputType,
|
||||||
) -> (NativeLibKind, Option<bool>) {
|
) -> (NativeLibKind, Option<bool>) {
|
||||||
let is_nightly = nightly_options::match_is_nightly_build(matches);
|
|
||||||
let enable_unstable = nightly_options::is_unstable_enabled(matches);
|
|
||||||
|
|
||||||
let (kind, modifiers) = match kind.split_once(':') {
|
let (kind, modifiers) = match kind.split_once(':') {
|
||||||
None => (kind, None),
|
None => (kind, None),
|
||||||
Some((kind, modifiers)) => (kind, Some(modifiers)),
|
Some((kind, modifiers)) => (kind, Some(modifiers)),
|
||||||
@ -1972,7 +1969,7 @@ fn parse_native_lib_kind(
|
|||||||
"linking modifier can't be used with library kind `static-nobundle`",
|
"linking modifier can't be used with library kind `static-nobundle`",
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
if !is_nightly {
|
if !nightly_options::match_is_nightly_build(matches) {
|
||||||
early_error(
|
early_error(
|
||||||
error_format,
|
error_format,
|
||||||
"library kind `static-nobundle` are currently unstable and only accepted on \
|
"library kind `static-nobundle` are currently unstable and only accepted on \
|
||||||
@ -1988,23 +1985,7 @@ fn parse_native_lib_kind(
|
|||||||
};
|
};
|
||||||
match modifiers {
|
match modifiers {
|
||||||
None => (kind, None),
|
None => (kind, None),
|
||||||
Some(modifiers) => {
|
Some(modifiers) => parse_native_lib_modifiers(kind, modifiers, error_format, matches),
|
||||||
if !is_nightly {
|
|
||||||
early_error(
|
|
||||||
error_format,
|
|
||||||
"linking modifiers are currently unstable and only accepted on \
|
|
||||||
the nightly compiler",
|
|
||||||
);
|
|
||||||
}
|
|
||||||
if !enable_unstable {
|
|
||||||
early_error(
|
|
||||||
error_format,
|
|
||||||
"linking modifiers are currently unstable, \
|
|
||||||
the `-Z unstable-options` flag must also be passed to use it",
|
|
||||||
)
|
|
||||||
}
|
|
||||||
parse_native_lib_modifiers(kind, modifiers, error_format)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2012,7 +1993,23 @@ fn parse_native_lib_modifiers(
|
|||||||
mut kind: NativeLibKind,
|
mut kind: NativeLibKind,
|
||||||
modifiers: &str,
|
modifiers: &str,
|
||||||
error_format: ErrorOutputType,
|
error_format: ErrorOutputType,
|
||||||
|
matches: &getopts::Matches,
|
||||||
) -> (NativeLibKind, Option<bool>) {
|
) -> (NativeLibKind, Option<bool>) {
|
||||||
|
let report_unstable_modifier = |modifier| {
|
||||||
|
if !nightly_options::is_unstable_enabled(matches) {
|
||||||
|
let why = if nightly_options::match_is_nightly_build(matches) {
|
||||||
|
" and only accepted on the nightly compiler"
|
||||||
|
} else {
|
||||||
|
", the `-Z unstable-options` flag must also be passed to use it"
|
||||||
|
};
|
||||||
|
early_error(
|
||||||
|
error_format,
|
||||||
|
&format!("{modifier} linking modifier is currently unstable{why}"),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut has_duplicate_modifiers = false;
|
||||||
let mut verbatim = None;
|
let mut verbatim = None;
|
||||||
for modifier in modifiers.split(',') {
|
for modifier in modifiers.split(',') {
|
||||||
let (modifier, value) = match modifier.strip_prefix(&['+', '-']) {
|
let (modifier, value) = match modifier.strip_prefix(&['+', '-']) {
|
||||||
@ -2026,6 +2023,10 @@ fn parse_native_lib_modifiers(
|
|||||||
|
|
||||||
match (modifier, &mut kind) {
|
match (modifier, &mut kind) {
|
||||||
("bundle", NativeLibKind::Static { bundle, .. }) => {
|
("bundle", NativeLibKind::Static { bundle, .. }) => {
|
||||||
|
report_unstable_modifier(modifier);
|
||||||
|
if bundle.is_some() {
|
||||||
|
has_duplicate_modifiers = true;
|
||||||
|
}
|
||||||
*bundle = Some(value);
|
*bundle = Some(value);
|
||||||
}
|
}
|
||||||
("bundle", _) => early_error(
|
("bundle", _) => early_error(
|
||||||
@ -2034,9 +2035,18 @@ fn parse_native_lib_modifiers(
|
|||||||
`static` linking kind",
|
`static` linking kind",
|
||||||
),
|
),
|
||||||
|
|
||||||
("verbatim", _) => verbatim = Some(value),
|
("verbatim", _) => {
|
||||||
|
report_unstable_modifier(modifier);
|
||||||
|
if verbatim.is_some() {
|
||||||
|
has_duplicate_modifiers = true;
|
||||||
|
}
|
||||||
|
verbatim = Some(value);
|
||||||
|
}
|
||||||
|
|
||||||
("whole-archive", NativeLibKind::Static { whole_archive, .. }) => {
|
("whole-archive", NativeLibKind::Static { whole_archive, .. }) => {
|
||||||
|
if whole_archive.is_some() {
|
||||||
|
has_duplicate_modifiers = true;
|
||||||
|
}
|
||||||
*whole_archive = Some(value);
|
*whole_archive = Some(value);
|
||||||
}
|
}
|
||||||
("whole-archive", _) => early_error(
|
("whole-archive", _) => early_error(
|
||||||
@ -2047,6 +2057,10 @@ fn parse_native_lib_modifiers(
|
|||||||
|
|
||||||
("as-needed", NativeLibKind::Dylib { as_needed })
|
("as-needed", NativeLibKind::Dylib { as_needed })
|
||||||
| ("as-needed", NativeLibKind::Framework { as_needed }) => {
|
| ("as-needed", NativeLibKind::Framework { as_needed }) => {
|
||||||
|
report_unstable_modifier(modifier);
|
||||||
|
if as_needed.is_some() {
|
||||||
|
has_duplicate_modifiers = true;
|
||||||
|
}
|
||||||
*as_needed = Some(value);
|
*as_needed = Some(value);
|
||||||
}
|
}
|
||||||
("as-needed", _) => early_error(
|
("as-needed", _) => early_error(
|
||||||
@ -2055,6 +2069,8 @@ fn parse_native_lib_modifiers(
|
|||||||
`dylib` and `framework` linking kinds",
|
`dylib` and `framework` linking kinds",
|
||||||
),
|
),
|
||||||
|
|
||||||
|
// Note: this error also excludes the case with empty modifier
|
||||||
|
// string, like `modifiers = ""`.
|
||||||
_ => early_error(
|
_ => early_error(
|
||||||
error_format,
|
error_format,
|
||||||
&format!(
|
&format!(
|
||||||
@ -2064,6 +2080,9 @@ fn parse_native_lib_modifiers(
|
|||||||
),
|
),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if has_duplicate_modifiers {
|
||||||
|
report_unstable_modifier("duplicating")
|
||||||
|
}
|
||||||
|
|
||||||
(kind, verbatim)
|
(kind, verbatim)
|
||||||
}
|
}
|
||||||
|
@ -75,6 +75,12 @@ pub struct NativeLib {
|
|||||||
pub dll_imports: Vec<DllImport>,
|
pub dll_imports: Vec<DllImport>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl NativeLib {
|
||||||
|
pub fn has_modifiers(&self) -> bool {
|
||||||
|
self.verbatim.is_some() || self.kind.has_modifiers()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Encodable, Decodable, HashStable_Generic)]
|
#[derive(Clone, Debug, Encodable, Decodable, HashStable_Generic)]
|
||||||
pub struct DllImport {
|
pub struct DllImport {
|
||||||
pub name: Symbol,
|
pub name: Symbol,
|
||||||
|
@ -43,6 +43,20 @@ pub enum NativeLibKind {
|
|||||||
Unspecified,
|
Unspecified,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl NativeLibKind {
|
||||||
|
pub fn has_modifiers(&self) -> bool {
|
||||||
|
match self {
|
||||||
|
NativeLibKind::Static { bundle, whole_archive } => {
|
||||||
|
bundle.is_some() || whole_archive.is_some()
|
||||||
|
}
|
||||||
|
NativeLibKind::Dylib { as_needed } | NativeLibKind::Framework { as_needed } => {
|
||||||
|
as_needed.is_some()
|
||||||
|
}
|
||||||
|
NativeLibKind::RawDylib | NativeLibKind::Unspecified => false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
rustc_data_structures::impl_stable_hash_via_hash!(NativeLibKind);
|
rustc_data_structures::impl_stable_hash_via_hash!(NativeLibKind);
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Encodable, Decodable)]
|
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Encodable, Decodable)]
|
||||||
@ -53,6 +67,12 @@ pub struct NativeLib {
|
|||||||
pub verbatim: Option<bool>,
|
pub verbatim: Option<bool>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl NativeLib {
|
||||||
|
pub fn has_modifiers(&self) -> bool {
|
||||||
|
self.verbatim.is_some() || self.kind.has_modifiers()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
rustc_data_structures::impl_stable_hash_via_hash!(NativeLib);
|
rustc_data_structures::impl_stable_hash_via_hash!(NativeLib);
|
||||||
|
|
||||||
/// A path that has been canonicalized along with its original, non-canonicalized form
|
/// A path that has been canonicalized along with its original, non-canonicalized form
|
||||||
|
@ -272,6 +272,7 @@ symbols! {
|
|||||||
__D,
|
__D,
|
||||||
__H,
|
__H,
|
||||||
__S,
|
__S,
|
||||||
|
__awaitee,
|
||||||
__try_var,
|
__try_var,
|
||||||
_d,
|
_d,
|
||||||
_e,
|
_e,
|
||||||
@ -722,6 +723,7 @@ symbols! {
|
|||||||
generators,
|
generators,
|
||||||
generic_arg_infer,
|
generic_arg_infer,
|
||||||
generic_associated_types,
|
generic_associated_types,
|
||||||
|
generic_associated_types_extended,
|
||||||
generic_const_exprs,
|
generic_const_exprs,
|
||||||
generic_param_attrs,
|
generic_param_attrs,
|
||||||
get_context,
|
get_context,
|
||||||
@ -1018,7 +1020,6 @@ symbols! {
|
|||||||
pattern_parentheses,
|
pattern_parentheses,
|
||||||
phantom_data,
|
phantom_data,
|
||||||
pin,
|
pin,
|
||||||
pinned,
|
|
||||||
platform_intrinsics,
|
platform_intrinsics,
|
||||||
plugin,
|
plugin,
|
||||||
plugin_registrar,
|
plugin_registrar,
|
||||||
|
@ -5,6 +5,7 @@ use super::*;
|
|||||||
|
|
||||||
use crate::infer::region_constraints::{Constraint, RegionConstraintData};
|
use crate::infer::region_constraints::{Constraint, RegionConstraintData};
|
||||||
use crate::infer::InferCtxt;
|
use crate::infer::InferCtxt;
|
||||||
|
use crate::traits::project::ProjectAndUnifyResult;
|
||||||
use rustc_middle::ty::fold::TypeFolder;
|
use rustc_middle::ty::fold::TypeFolder;
|
||||||
use rustc_middle::ty::{Region, RegionVid, Term};
|
use rustc_middle::ty::{Region, RegionVid, Term};
|
||||||
|
|
||||||
@ -751,7 +752,7 @@ impl<'tcx> AutoTraitFinder<'tcx> {
|
|||||||
debug!("Projecting and unifying projection predicate {:?}", predicate);
|
debug!("Projecting and unifying projection predicate {:?}", predicate);
|
||||||
|
|
||||||
match project::poly_project_and_unify_type(select, &obligation.with(p)) {
|
match project::poly_project_and_unify_type(select, &obligation.with(p)) {
|
||||||
Err(e) => {
|
ProjectAndUnifyResult::MismatchedProjectionTypes(e) => {
|
||||||
debug!(
|
debug!(
|
||||||
"evaluate_nested_obligations: Unable to unify predicate \
|
"evaluate_nested_obligations: Unable to unify predicate \
|
||||||
'{:?}' '{:?}', bailing out",
|
'{:?}' '{:?}', bailing out",
|
||||||
@ -759,11 +760,11 @@ impl<'tcx> AutoTraitFinder<'tcx> {
|
|||||||
);
|
);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
Ok(Err(project::InProgress)) => {
|
ProjectAndUnifyResult::Recursive => {
|
||||||
debug!("evaluate_nested_obligations: recursive projection predicate");
|
debug!("evaluate_nested_obligations: recursive projection predicate");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
Ok(Ok(Some(v))) => {
|
ProjectAndUnifyResult::Holds(v) => {
|
||||||
// We only care about sub-obligations
|
// We only care about sub-obligations
|
||||||
// when we started out trying to unify
|
// when we started out trying to unify
|
||||||
// some inference variables. See the comment above
|
// some inference variables. See the comment above
|
||||||
@ -782,7 +783,7 @@ impl<'tcx> AutoTraitFinder<'tcx> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(Ok(None)) => {
|
ProjectAndUnifyResult::FailedNormalization => {
|
||||||
// It's ok not to make progress when have no inference variables -
|
// It's ok not to make progress when have no inference variables -
|
||||||
// in that case, we were only performing unification to check if an
|
// in that case, we were only performing unification to check if an
|
||||||
// error occurred (which would indicate that it's impossible for our
|
// error occurred (which would indicate that it's impossible for our
|
||||||
|
@ -14,7 +14,7 @@ use rustc_middle::ty::{self, Binder, Const, Ty, TypeFoldable};
|
|||||||
use std::marker::PhantomData;
|
use std::marker::PhantomData;
|
||||||
|
|
||||||
use super::const_evaluatable;
|
use super::const_evaluatable;
|
||||||
use super::project;
|
use super::project::{self, ProjectAndUnifyResult};
|
||||||
use super::select::SelectionContext;
|
use super::select::SelectionContext;
|
||||||
use super::wf;
|
use super::wf;
|
||||||
use super::CodeAmbiguity;
|
use super::CodeAmbiguity;
|
||||||
@ -753,8 +753,8 @@ impl<'a, 'b, 'tcx> FulfillProcessor<'a, 'b, 'tcx> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
match project::poly_project_and_unify_type(self.selcx, &project_obligation) {
|
match project::poly_project_and_unify_type(self.selcx, &project_obligation) {
|
||||||
Ok(Ok(Some(os))) => ProcessResult::Changed(mk_pending(os)),
|
ProjectAndUnifyResult::Holds(os) => ProcessResult::Changed(mk_pending(os)),
|
||||||
Ok(Ok(None)) => {
|
ProjectAndUnifyResult::FailedNormalization => {
|
||||||
stalled_on.clear();
|
stalled_on.clear();
|
||||||
stalled_on.extend(substs_infer_vars(
|
stalled_on.extend(substs_infer_vars(
|
||||||
self.selcx,
|
self.selcx,
|
||||||
@ -763,10 +763,12 @@ impl<'a, 'b, 'tcx> FulfillProcessor<'a, 'b, 'tcx> {
|
|||||||
ProcessResult::Unchanged
|
ProcessResult::Unchanged
|
||||||
}
|
}
|
||||||
// Let the caller handle the recursion
|
// Let the caller handle the recursion
|
||||||
Ok(Err(project::InProgress)) => ProcessResult::Changed(mk_pending(vec![
|
ProjectAndUnifyResult::Recursive => ProcessResult::Changed(mk_pending(vec![
|
||||||
project_obligation.with(project_obligation.predicate.to_predicate(tcx)),
|
project_obligation.with(project_obligation.predicate.to_predicate(tcx)),
|
||||||
])),
|
])),
|
||||||
Err(e) => ProcessResult::Error(CodeProjectionError(e)),
|
ProjectAndUnifyResult::MismatchedProjectionTypes(e) => {
|
||||||
|
ProcessResult::Error(CodeProjectionError(e))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -28,7 +28,7 @@ use rustc_hir::def_id::DefId;
|
|||||||
use rustc_hir::lang_items::LangItem;
|
use rustc_hir::lang_items::LangItem;
|
||||||
use rustc_infer::infer::resolve::OpportunisticRegionResolver;
|
use rustc_infer::infer::resolve::OpportunisticRegionResolver;
|
||||||
use rustc_middle::traits::select::OverflowError;
|
use rustc_middle::traits::select::OverflowError;
|
||||||
use rustc_middle::ty::fold::{TypeFoldable, TypeFolder};
|
use rustc_middle::ty::fold::{MaxUniverse, TypeFoldable, TypeFolder};
|
||||||
use rustc_middle::ty::subst::Subst;
|
use rustc_middle::ty::subst::Subst;
|
||||||
use rustc_middle::ty::{self, Term, ToPredicate, Ty, TyCtxt};
|
use rustc_middle::ty::{self, Term, ToPredicate, Ty, TyCtxt};
|
||||||
use rustc_span::symbol::sym;
|
use rustc_span::symbol::sym;
|
||||||
@ -144,6 +144,18 @@ impl<'tcx> ProjectionCandidateSet<'tcx> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Takes the place of a
|
||||||
|
/// Result<
|
||||||
|
/// Result<Option<Vec<PredicateObligation<'tcx>>>, InProgress>,
|
||||||
|
/// MismatchedProjectionTypes<'tcx>,
|
||||||
|
/// >
|
||||||
|
pub(super) enum ProjectAndUnifyResult<'tcx> {
|
||||||
|
Holds(Vec<PredicateObligation<'tcx>>),
|
||||||
|
FailedNormalization,
|
||||||
|
Recursive,
|
||||||
|
MismatchedProjectionTypes(MismatchedProjectionTypes<'tcx>),
|
||||||
|
}
|
||||||
|
|
||||||
/// Evaluates constraints of the form:
|
/// Evaluates constraints of the form:
|
||||||
///
|
///
|
||||||
/// for<...> <T as Trait>::U == V
|
/// for<...> <T as Trait>::U == V
|
||||||
@ -167,19 +179,47 @@ impl<'tcx> ProjectionCandidateSet<'tcx> {
|
|||||||
pub(super) fn poly_project_and_unify_type<'cx, 'tcx>(
|
pub(super) fn poly_project_and_unify_type<'cx, 'tcx>(
|
||||||
selcx: &mut SelectionContext<'cx, 'tcx>,
|
selcx: &mut SelectionContext<'cx, 'tcx>,
|
||||||
obligation: &PolyProjectionObligation<'tcx>,
|
obligation: &PolyProjectionObligation<'tcx>,
|
||||||
) -> Result<
|
) -> ProjectAndUnifyResult<'tcx> {
|
||||||
Result<Option<Vec<PredicateObligation<'tcx>>>, InProgress>,
|
|
||||||
MismatchedProjectionTypes<'tcx>,
|
|
||||||
> {
|
|
||||||
let infcx = selcx.infcx();
|
let infcx = selcx.infcx();
|
||||||
infcx.commit_if_ok(|_snapshot| {
|
let r = infcx.commit_if_ok(|_snapshot| {
|
||||||
|
let old_universe = infcx.universe();
|
||||||
let placeholder_predicate =
|
let placeholder_predicate =
|
||||||
infcx.replace_bound_vars_with_placeholders(obligation.predicate);
|
infcx.replace_bound_vars_with_placeholders(obligation.predicate);
|
||||||
|
let new_universe = infcx.universe();
|
||||||
|
|
||||||
let placeholder_obligation = obligation.with(placeholder_predicate);
|
let placeholder_obligation = obligation.with(placeholder_predicate);
|
||||||
let result = project_and_unify_type(selcx, &placeholder_obligation)?;
|
match project_and_unify_type(selcx, &placeholder_obligation) {
|
||||||
Ok(result)
|
ProjectAndUnifyResult::MismatchedProjectionTypes(e) => Err(e),
|
||||||
})
|
ProjectAndUnifyResult::Holds(obligations)
|
||||||
|
if old_universe != new_universe
|
||||||
|
&& selcx.tcx().features().generic_associated_types_extended =>
|
||||||
|
{
|
||||||
|
// If the `generic_associated_types_extended` feature is active, then we ignore any
|
||||||
|
// obligations references lifetimes from any universe greater than or equal to the
|
||||||
|
// universe just created. Otherwise, we can end up with something like `for<'a> I: 'a`,
|
||||||
|
// which isn't quite what we want. Ideally, we want either an implied
|
||||||
|
// `for<'a where I: 'a> I: 'a` or we want to "lazily" check these hold when we
|
||||||
|
// substitute concrete regions. There is design work to be done here; until then,
|
||||||
|
// however, this allows experimenting potential GAT features without running into
|
||||||
|
// well-formedness issues.
|
||||||
|
let new_obligations = obligations
|
||||||
|
.into_iter()
|
||||||
|
.filter(|obligation| {
|
||||||
|
let mut visitor = MaxUniverse::new();
|
||||||
|
obligation.predicate.visit_with(&mut visitor);
|
||||||
|
visitor.max_universe() < new_universe
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
Ok(ProjectAndUnifyResult::Holds(new_obligations))
|
||||||
|
}
|
||||||
|
other => Ok(other),
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
match r {
|
||||||
|
Ok(inner) => inner,
|
||||||
|
Err(err) => ProjectAndUnifyResult::MismatchedProjectionTypes(err),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Evaluates constraints of the form:
|
/// Evaluates constraints of the form:
|
||||||
@ -189,15 +229,11 @@ pub(super) fn poly_project_and_unify_type<'cx, 'tcx>(
|
|||||||
/// If successful, this may result in additional obligations.
|
/// If successful, this may result in additional obligations.
|
||||||
///
|
///
|
||||||
/// See [poly_project_and_unify_type] for an explanation of the return value.
|
/// See [poly_project_and_unify_type] for an explanation of the return value.
|
||||||
|
#[tracing::instrument(level = "debug", skip(selcx))]
|
||||||
fn project_and_unify_type<'cx, 'tcx>(
|
fn project_and_unify_type<'cx, 'tcx>(
|
||||||
selcx: &mut SelectionContext<'cx, 'tcx>,
|
selcx: &mut SelectionContext<'cx, 'tcx>,
|
||||||
obligation: &ProjectionObligation<'tcx>,
|
obligation: &ProjectionObligation<'tcx>,
|
||||||
) -> Result<
|
) -> ProjectAndUnifyResult<'tcx> {
|
||||||
Result<Option<Vec<PredicateObligation<'tcx>>>, InProgress>,
|
|
||||||
MismatchedProjectionTypes<'tcx>,
|
|
||||||
> {
|
|
||||||
debug!(?obligation, "project_and_unify_type");
|
|
||||||
|
|
||||||
let mut obligations = vec![];
|
let mut obligations = vec![];
|
||||||
|
|
||||||
let infcx = selcx.infcx();
|
let infcx = selcx.infcx();
|
||||||
@ -210,8 +246,8 @@ fn project_and_unify_type<'cx, 'tcx>(
|
|||||||
&mut obligations,
|
&mut obligations,
|
||||||
) {
|
) {
|
||||||
Ok(Some(n)) => n,
|
Ok(Some(n)) => n,
|
||||||
Ok(None) => return Ok(Ok(None)),
|
Ok(None) => return ProjectAndUnifyResult::FailedNormalization,
|
||||||
Err(InProgress) => return Ok(Err(InProgress)),
|
Err(InProgress) => return ProjectAndUnifyResult::Recursive,
|
||||||
};
|
};
|
||||||
debug!(?normalized, ?obligations, "project_and_unify_type result");
|
debug!(?normalized, ?obligations, "project_and_unify_type result");
|
||||||
let actual = obligation.predicate.term;
|
let actual = obligation.predicate.term;
|
||||||
@ -231,11 +267,11 @@ fn project_and_unify_type<'cx, 'tcx>(
|
|||||||
match infcx.at(&obligation.cause, obligation.param_env).eq(normalized, actual) {
|
match infcx.at(&obligation.cause, obligation.param_env).eq(normalized, actual) {
|
||||||
Ok(InferOk { obligations: inferred_obligations, value: () }) => {
|
Ok(InferOk { obligations: inferred_obligations, value: () }) => {
|
||||||
obligations.extend(inferred_obligations);
|
obligations.extend(inferred_obligations);
|
||||||
Ok(Ok(Some(obligations)))
|
ProjectAndUnifyResult::Holds(obligations)
|
||||||
}
|
}
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
debug!("project_and_unify_type: equating types encountered error {:?}", err);
|
debug!("equating types encountered error {:?}", err);
|
||||||
Err(MismatchedProjectionTypes { err })
|
ProjectAndUnifyResult::MismatchedProjectionTypes(MismatchedProjectionTypes { err })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -21,6 +21,7 @@ use super::{
|
|||||||
|
|
||||||
use crate::infer::{InferCtxt, InferOk, TypeFreshener};
|
use crate::infer::{InferCtxt, InferOk, TypeFreshener};
|
||||||
use crate::traits::error_reporting::InferCtxtExt;
|
use crate::traits::error_reporting::InferCtxtExt;
|
||||||
|
use crate::traits::project::ProjectAndUnifyResult;
|
||||||
use crate::traits::project::ProjectionCacheKeyExt;
|
use crate::traits::project::ProjectionCacheKeyExt;
|
||||||
use crate::traits::ProjectionCacheKey;
|
use crate::traits::ProjectionCacheKey;
|
||||||
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
|
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
|
||||||
@ -525,7 +526,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
|||||||
let data = bound_predicate.rebind(data);
|
let data = bound_predicate.rebind(data);
|
||||||
let project_obligation = obligation.with(data);
|
let project_obligation = obligation.with(data);
|
||||||
match project::poly_project_and_unify_type(self, &project_obligation) {
|
match project::poly_project_and_unify_type(self, &project_obligation) {
|
||||||
Ok(Ok(Some(mut subobligations))) => {
|
ProjectAndUnifyResult::Holds(mut subobligations) => {
|
||||||
'compute_res: {
|
'compute_res: {
|
||||||
// If we've previously marked this projection as 'complete', then
|
// If we've previously marked this projection as 'complete', then
|
||||||
// use the final cached result (either `EvaluatedToOk` or
|
// use the final cached result (either `EvaluatedToOk` or
|
||||||
@ -573,9 +574,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
|||||||
res
|
res
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(Ok(None)) => Ok(EvaluatedToAmbig),
|
ProjectAndUnifyResult::FailedNormalization => Ok(EvaluatedToAmbig),
|
||||||
Ok(Err(project::InProgress)) => Ok(EvaluatedToRecur),
|
ProjectAndUnifyResult::Recursive => Ok(EvaluatedToRecur),
|
||||||
Err(_) => Ok(EvaluatedToErr),
|
ProjectAndUnifyResult::MismatchedProjectionTypes(_) => Ok(EvaluatedToErr),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -8,7 +8,8 @@ use core::iter::{
|
|||||||
FusedIterator, InPlaceIterable, SourceIter, TrustedLen, TrustedRandomAccessNoCoerce,
|
FusedIterator, InPlaceIterable, SourceIter, TrustedLen, TrustedRandomAccessNoCoerce,
|
||||||
};
|
};
|
||||||
use core::marker::PhantomData;
|
use core::marker::PhantomData;
|
||||||
use core::mem::{self};
|
use core::mem::{self, ManuallyDrop};
|
||||||
|
use core::ops::Deref;
|
||||||
use core::ptr::{self, NonNull};
|
use core::ptr::{self, NonNull};
|
||||||
use core::slice::{self};
|
use core::slice::{self};
|
||||||
|
|
||||||
@ -32,7 +33,9 @@ pub struct IntoIter<
|
|||||||
pub(super) buf: NonNull<T>,
|
pub(super) buf: NonNull<T>,
|
||||||
pub(super) phantom: PhantomData<T>,
|
pub(super) phantom: PhantomData<T>,
|
||||||
pub(super) cap: usize,
|
pub(super) cap: usize,
|
||||||
pub(super) alloc: A,
|
// the drop impl reconstructs a RawVec from buf, cap and alloc
|
||||||
|
// to avoid dropping the allocator twice we need to wrap it into ManuallyDrop
|
||||||
|
pub(super) alloc: ManuallyDrop<A>,
|
||||||
pub(super) ptr: *const T,
|
pub(super) ptr: *const T,
|
||||||
pub(super) end: *const T,
|
pub(super) end: *const T,
|
||||||
}
|
}
|
||||||
@ -295,11 +298,11 @@ where
|
|||||||
impl<T: Clone, A: Allocator + Clone> Clone for IntoIter<T, A> {
|
impl<T: Clone, A: Allocator + Clone> Clone for IntoIter<T, A> {
|
||||||
#[cfg(not(test))]
|
#[cfg(not(test))]
|
||||||
fn clone(&self) -> Self {
|
fn clone(&self) -> Self {
|
||||||
self.as_slice().to_vec_in(self.alloc.clone()).into_iter()
|
self.as_slice().to_vec_in(self.alloc.deref().clone()).into_iter()
|
||||||
}
|
}
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
fn clone(&self) -> Self {
|
fn clone(&self) -> Self {
|
||||||
crate::slice::to_vec(self.as_slice(), self.alloc.clone()).into_iter()
|
crate::slice::to_vec(self.as_slice(), self.alloc.deref().clone()).into_iter()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -311,8 +314,8 @@ unsafe impl<#[may_dangle] T, A: Allocator> Drop for IntoIter<T, A> {
|
|||||||
impl<T, A: Allocator> Drop for DropGuard<'_, T, A> {
|
impl<T, A: Allocator> Drop for DropGuard<'_, T, A> {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
unsafe {
|
unsafe {
|
||||||
// `IntoIter::alloc` is not used anymore after this
|
// `IntoIter::alloc` is not used anymore after this and will be dropped by RawVec
|
||||||
let alloc = ptr::read(&self.0.alloc);
|
let alloc = ManuallyDrop::take(&mut self.0.alloc);
|
||||||
// RawVec handles deallocation
|
// RawVec handles deallocation
|
||||||
let _ = RawVec::from_raw_parts_in(self.0.buf.as_ptr(), self.0.cap, alloc);
|
let _ = RawVec::from_raw_parts_in(self.0.buf.as_ptr(), self.0.cap, alloc);
|
||||||
}
|
}
|
||||||
|
@ -2579,7 +2579,7 @@ impl<T, A: Allocator> IntoIterator for Vec<T, A> {
|
|||||||
fn into_iter(self) -> IntoIter<T, A> {
|
fn into_iter(self) -> IntoIter<T, A> {
|
||||||
unsafe {
|
unsafe {
|
||||||
let mut me = ManuallyDrop::new(self);
|
let mut me = ManuallyDrop::new(self);
|
||||||
let alloc = ptr::read(me.allocator());
|
let alloc = ManuallyDrop::new(ptr::read(me.allocator()));
|
||||||
let begin = me.as_mut_ptr();
|
let begin = me.as_mut_ptr();
|
||||||
let end = if mem::size_of::<T>() == 0 {
|
let end = if mem::size_of::<T>() == 0 {
|
||||||
arith_offset(begin as *const i8, me.len() as isize) as *const T
|
arith_offset(begin as *const i8, me.len() as isize) as *const T
|
||||||
|
@ -1,3 +1,6 @@
|
|||||||
|
use core::alloc::{Allocator, Layout};
|
||||||
|
use core::ptr::NonNull;
|
||||||
|
use std::alloc::System;
|
||||||
use std::assert_matches::assert_matches;
|
use std::assert_matches::assert_matches;
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
use std::cell::Cell;
|
use std::cell::Cell;
|
||||||
@ -991,6 +994,31 @@ fn test_into_iter_advance_by() {
|
|||||||
assert_eq!(i.len(), 0);
|
assert_eq!(i.len(), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_into_iter_drop_allocator() {
|
||||||
|
struct ReferenceCountedAllocator<'a>(DropCounter<'a>);
|
||||||
|
|
||||||
|
unsafe impl Allocator for ReferenceCountedAllocator<'_> {
|
||||||
|
fn allocate(&self, layout: Layout) -> Result<NonNull<[u8]>, core::alloc::AllocError> {
|
||||||
|
System.allocate(layout)
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe fn deallocate(&self, ptr: NonNull<u8>, layout: Layout) {
|
||||||
|
System.deallocate(ptr, layout)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut drop_count = 0;
|
||||||
|
|
||||||
|
let allocator = ReferenceCountedAllocator(DropCounter { count: &mut drop_count });
|
||||||
|
let _ = Vec::<u32, _>::new_in(allocator);
|
||||||
|
assert_eq!(drop_count, 1);
|
||||||
|
|
||||||
|
let allocator = ReferenceCountedAllocator(DropCounter { count: &mut drop_count });
|
||||||
|
let _ = Vec::<u32, _>::new_in(allocator).into_iter();
|
||||||
|
assert_eq!(drop_count, 2);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_from_iter_specialization() {
|
fn test_from_iter_specialization() {
|
||||||
let src: Vec<usize> = vec![0usize; 1];
|
let src: Vec<usize> = vec![0usize; 1];
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
#![no_std]
|
#![no_std]
|
||||||
#![unstable(feature = "panic_unwind", issue = "32837")]
|
#![unstable(feature = "panic_unwind", issue = "32837")]
|
||||||
#![feature(link_cfg)]
|
#![feature(link_cfg)]
|
||||||
#![feature(native_link_modifiers)]
|
#![cfg_attr(bootstrap, feature(native_link_modifiers))]
|
||||||
#![feature(native_link_modifiers_bundle)]
|
#![feature(native_link_modifiers_bundle)]
|
||||||
#![feature(nll)]
|
#![feature(nll)]
|
||||||
#![feature(staged_api)]
|
#![feature(staged_api)]
|
||||||
|
@ -117,6 +117,7 @@ use std::os::unix::fs::symlink as symlink_file;
|
|||||||
use std::os::windows::fs::symlink_file;
|
use std::os::windows::fs::symlink_file;
|
||||||
|
|
||||||
use filetime::FileTime;
|
use filetime::FileTime;
|
||||||
|
use once_cell::sync::OnceCell;
|
||||||
|
|
||||||
use crate::builder::Kind;
|
use crate::builder::Kind;
|
||||||
use crate::config::{LlvmLibunwind, TargetSelection};
|
use crate::config::{LlvmLibunwind, TargetSelection};
|
||||||
@ -904,7 +905,12 @@ impl Build {
|
|||||||
|
|
||||||
/// Returns the sysroot of the snapshot compiler.
|
/// Returns the sysroot of the snapshot compiler.
|
||||||
fn rustc_snapshot_sysroot(&self) -> &Path {
|
fn rustc_snapshot_sysroot(&self) -> &Path {
|
||||||
self.initial_rustc.parent().unwrap().parent().unwrap()
|
static SYSROOT_CACHE: OnceCell<PathBuf> = once_cell::sync::OnceCell::new();
|
||||||
|
SYSROOT_CACHE.get_or_init(|| {
|
||||||
|
let mut rustc = Command::new(&self.initial_rustc);
|
||||||
|
rustc.args(&["--print", "sysroot"]);
|
||||||
|
output(&mut rustc).trim().into()
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Runs a command, printing out nice contextual information if it fails.
|
/// Runs a command, printing out nice contextual information if it fails.
|
||||||
|
@ -37,6 +37,8 @@ KIND=PATH` where `KIND` may be one of:
|
|||||||
<a id="option-l-link-lib"></a>
|
<a id="option-l-link-lib"></a>
|
||||||
## `-l`: link the generated crate to a native library
|
## `-l`: link the generated crate to a native library
|
||||||
|
|
||||||
|
Syntax: `-l [KIND[:MODIFIERS]=]NAME[:RENAME]`.
|
||||||
|
|
||||||
This flag allows you to specify linking to a specific native library when building
|
This flag allows you to specify linking to a specific native library when building
|
||||||
a crate.
|
a crate.
|
||||||
|
|
||||||
@ -47,7 +49,13 @@ where `KIND` may be one of:
|
|||||||
- `static` — A native static library (such as a `.a` archive).
|
- `static` — A native static library (such as a `.a` archive).
|
||||||
- `framework` — A macOS framework.
|
- `framework` — A macOS framework.
|
||||||
|
|
||||||
The kind of library can be specified in a [`#[link]`
|
If the kind is specified, then linking modifiers can be attached to it.
|
||||||
|
Modifiers are specified as a comma-delimited string with each modifier prefixed with
|
||||||
|
either a `+` or `-` to indicate that the modifier is enabled or disabled, respectively.
|
||||||
|
The last boolean value specified for a given modifier wins. \
|
||||||
|
Example: `-l static:+whole-archive=mylib`.
|
||||||
|
|
||||||
|
The kind of library and the modifiers can also be specified in a [`#[link]`
|
||||||
attribute][link-attribute]. If the kind is not specified in the `link`
|
attribute][link-attribute]. If the kind is not specified in the `link`
|
||||||
attribute or on the command-line, it will link a dynamic library if available,
|
attribute or on the command-line, it will link a dynamic library if available,
|
||||||
otherwise it will use a static library. If the kind is specified on the
|
otherwise it will use a static library. If the kind is specified on the
|
||||||
@ -59,6 +67,22 @@ and `LINK_NAME` is the name of the actual library that will be linked.
|
|||||||
|
|
||||||
[link-attribute]: ../reference/items/external-blocks.html#the-link-attribute
|
[link-attribute]: ../reference/items/external-blocks.html#the-link-attribute
|
||||||
|
|
||||||
|
### Linking modifiers: `whole-archive`
|
||||||
|
|
||||||
|
This modifier is only compatible with the `static` linking kind.
|
||||||
|
Using any other kind will result in a compiler error.
|
||||||
|
|
||||||
|
`+whole-archive` means that the static library is linked as a whole archive
|
||||||
|
without throwing any object files away.
|
||||||
|
|
||||||
|
This modifier translates to `--whole-archive` for `ld`-like linkers,
|
||||||
|
to `/WHOLEARCHIVE` for `link.exe`, and to `-force_load` for `ld64`.
|
||||||
|
The modifier does nothing for linkers that don't support it.
|
||||||
|
|
||||||
|
The default for this modifier is `-whole-archive`. \
|
||||||
|
NOTE: The default may currently be different when building dylibs for some targets,
|
||||||
|
but it is not guaranteed.
|
||||||
|
|
||||||
<a id="option-crate-type"></a>
|
<a id="option-crate-type"></a>
|
||||||
## `--crate-type`: a list of types of crates for the compiler to emit
|
## `--crate-type`: a list of types of crates for the compiler to emit
|
||||||
|
|
||||||
|
@ -1,18 +0,0 @@
|
|||||||
# `native_link_modifiers_whole_archive`
|
|
||||||
|
|
||||||
The tracking issue for this feature is: [#81490]
|
|
||||||
|
|
||||||
[#81490]: https://github.com/rust-lang/rust/issues/81490
|
|
||||||
|
|
||||||
------------------------
|
|
||||||
|
|
||||||
The `native_link_modifiers_whole_archive` feature allows you to use the `whole-archive` modifier.
|
|
||||||
|
|
||||||
Only compatible with the `static` linking kind. Using any other kind will result in a compiler error.
|
|
||||||
|
|
||||||
`+whole-archive` means that the static library is linked as a whole archive without throwing any object files away.
|
|
||||||
|
|
||||||
This modifier translates to `--whole-archive` for `ld`-like linkers, to `/WHOLEARCHIVE` for `link.exe`, and to `-force_load` for `ld64`.
|
|
||||||
The modifier does nothing for linkers that don't support it.
|
|
||||||
|
|
||||||
The default for this modifier is `-whole-archive`.
|
|
@ -1,11 +0,0 @@
|
|||||||
# `native_link_modifiers`
|
|
||||||
|
|
||||||
The tracking issue for this feature is: [#81490]
|
|
||||||
|
|
||||||
[#81490]: https://github.com/rust-lang/rust/issues/81490
|
|
||||||
|
|
||||||
------------------------
|
|
||||||
|
|
||||||
The `native_link_modifiers` feature allows you to use the `modifiers` syntax with the `#[link(..)]` attribute.
|
|
||||||
|
|
||||||
Modifiers are specified as a comma-delimited string with each modifier prefixed with either a `+` or `-` to indicate that the modifier is enabled or disabled, respectively. The last boolean value specified for a given modifier wins.
|
|
23
src/test/codegen/async-fn-debug-awaitee-field.rs
Normal file
23
src/test/codegen/async-fn-debug-awaitee-field.rs
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
// This test makes sure that the generator field capturing the awaitee in a `.await` expression
|
||||||
|
// is called "__awaitee" in debuginfo. This name must not be changed since debuggers and debugger
|
||||||
|
// extensions rely on the field having this name.
|
||||||
|
|
||||||
|
// ignore-tidy-linelength
|
||||||
|
// compile-flags: -C debuginfo=2 --edition=2018
|
||||||
|
|
||||||
|
async fn foo() {}
|
||||||
|
|
||||||
|
async fn async_fn_test() {
|
||||||
|
foo().await;
|
||||||
|
}
|
||||||
|
|
||||||
|
// NONMSVC: [[GEN:!.*]] = !DICompositeType(tag: DW_TAG_structure_type, name: "{async_fn_env#0}",
|
||||||
|
// MSVC: [[GEN:!.*]] = !DICompositeType(tag: DW_TAG_union_type, name: "enum$<async_fn_debug_awaitee_field::async_fn_test::async_fn_env$0>",
|
||||||
|
// CHECK: [[SUSPEND_STRUCT:!.*]] = !DICompositeType(tag: DW_TAG_structure_type, name: "Suspend0", scope: [[GEN]],
|
||||||
|
// CHECK: !DIDerivedType(tag: DW_TAG_member, name: "__awaitee", scope: [[SUSPEND_STRUCT]], {{.*}}, baseType: [[AWAITEE_TYPE:![0-9]*]],
|
||||||
|
// NONMSVC: [[AWAITEE_TYPE]] = !DICompositeType(tag: DW_TAG_structure_type, name: "GenFuture<async_fn_debug_awaitee_field::foo::{async_fn_env#0}>",
|
||||||
|
// MSVC: [[AWAITEE_TYPE]] = !DICompositeType(tag: DW_TAG_structure_type, name: "GenFuture<enum$<async_fn_debug_awaitee_field::foo::async_fn_env$0> >",
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let _fn = async_fn_test();
|
||||||
|
}
|
@ -1,6 +1,4 @@
|
|||||||
#![feature(native_link_modifiers_bundle)]
|
#![feature(native_link_modifiers_bundle)]
|
||||||
#![feature(native_link_modifiers_whole_archive)]
|
|
||||||
#![feature(native_link_modifiers)]
|
|
||||||
|
|
||||||
use std::io::Write;
|
use std::io::Write;
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
#![feature(raw_dylib, native_link_modifiers, native_link_modifiers_verbatim)]
|
#![feature(raw_dylib, native_link_modifiers_verbatim)]
|
||||||
|
|
||||||
#[link(name = "extern_1.dll", kind = "raw-dylib", modifiers = "+verbatim")]
|
#[link(name = "extern_1.dll", kind = "raw-dylib", modifiers = "+verbatim")]
|
||||||
extern {
|
extern {
|
||||||
|
@ -0,0 +1,6 @@
|
|||||||
|
#![feature(generic_associated_types)]
|
||||||
|
|
||||||
|
// This feature doesn't *currently* fire on any specific code; it's just a
|
||||||
|
// behavior change. Future changes might.
|
||||||
|
#[rustc_error] //~ the
|
||||||
|
fn main() {}
|
@ -0,0 +1,11 @@
|
|||||||
|
error[E0658]: the `#[rustc_error]` attribute is just used for rustc unit tests and will never be stable
|
||||||
|
--> $DIR/feature-gate-generic_associated_types_extended.rs:5:1
|
||||||
|
|
|
||||||
|
LL | #[rustc_error]
|
||||||
|
| ^^^^^^^^^^^^^^
|
||||||
|
|
|
||||||
|
= help: add `#![feature(rustc_attrs)]` to the crate attributes to enable
|
||||||
|
|
||||||
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0658`.
|
@ -1,5 +0,0 @@
|
|||||||
#[link(name = "foo", modifiers = "")]
|
|
||||||
//~^ ERROR: native link modifiers are experimental
|
|
||||||
extern "C" {}
|
|
||||||
|
|
||||||
fn main() {}
|
|
@ -1,12 +0,0 @@
|
|||||||
error[E0658]: native link modifiers are experimental
|
|
||||||
--> $DIR/feature-gate-native_link_modifiers.rs:1:22
|
|
||||||
|
|
|
||||||
LL | #[link(name = "foo", modifiers = "")]
|
|
||||||
| ^^^^^^^^^^^^^^
|
|
||||||
|
|
|
||||||
= note: see issue #81490 <https://github.com/rust-lang/rust/issues/81490> for more information
|
|
||||||
= help: add `#![feature(native_link_modifiers)]` to the crate attributes to enable
|
|
||||||
|
|
||||||
error: aborting due to previous error
|
|
||||||
|
|
||||||
For more information about this error, try `rustc --explain E0658`.
|
|
@ -1,6 +1,3 @@
|
|||||||
#![allow(incomplete_features)]
|
|
||||||
#![feature(native_link_modifiers)]
|
|
||||||
|
|
||||||
#[link(name = "foo", modifiers = "+as-needed")]
|
#[link(name = "foo", modifiers = "+as-needed")]
|
||||||
//~^ ERROR: `#[link(modifiers="as-needed")]` is unstable
|
//~^ ERROR: `#[link(modifiers="as-needed")]` is unstable
|
||||||
extern "C" {}
|
extern "C" {}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
error[E0658]: `#[link(modifiers="as-needed")]` is unstable
|
error[E0658]: `#[link(modifiers="as-needed")]` is unstable
|
||||||
--> $DIR/feature-gate-native_link_modifiers_as_needed.rs:4:34
|
--> $DIR/feature-gate-native_link_modifiers_as_needed.rs:1:34
|
||||||
|
|
|
|
||||||
LL | #[link(name = "foo", modifiers = "+as-needed")]
|
LL | #[link(name = "foo", modifiers = "+as-needed")]
|
||||||
| ^^^^^^^^^^^^
|
| ^^^^^^^^^^^^
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
// Test native_link_modifiers_bundle don't need static-nobundle
|
// Test native_link_modifiers_bundle don't need static-nobundle
|
||||||
// check-pass
|
// check-pass
|
||||||
|
|
||||||
#![feature(native_link_modifiers)]
|
|
||||||
#![feature(native_link_modifiers_bundle)]
|
#![feature(native_link_modifiers_bundle)]
|
||||||
|
|
||||||
#[link(name = "foo", kind = "static", modifiers = "-bundle")]
|
#[link(name = "foo", kind = "static", modifiers = "-bundle")]
|
||||||
|
@ -1,2 +1,2 @@
|
|||||||
error: linking modifiers are currently unstable, the `-Z unstable-options` flag must also be passed to use it
|
error: bundle linking modifier is currently unstable and only accepted on the nightly compiler
|
||||||
|
|
||||||
|
@ -1,6 +1,3 @@
|
|||||||
#![allow(incomplete_features)]
|
|
||||||
#![feature(native_link_modifiers)]
|
|
||||||
|
|
||||||
#[link(name = "foo", modifiers = "+bundle")]
|
#[link(name = "foo", modifiers = "+bundle")]
|
||||||
//~^ ERROR: `#[link(modifiers="bundle")]` is unstable
|
//~^ ERROR: `#[link(modifiers="bundle")]` is unstable
|
||||||
extern "C" {}
|
extern "C" {}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
error[E0658]: `#[link(modifiers="bundle")]` is unstable
|
error[E0658]: `#[link(modifiers="bundle")]` is unstable
|
||||||
--> $DIR/feature-gate-native_link_modifiers_bundle.rs:4:34
|
--> $DIR/feature-gate-native_link_modifiers_bundle.rs:1:34
|
||||||
|
|
|
|
||||||
LL | #[link(name = "foo", modifiers = "+bundle")]
|
LL | #[link(name = "foo", modifiers = "+bundle")]
|
||||||
| ^^^^^^^^^
|
| ^^^^^^^^^
|
||||||
|
@ -1,6 +1,3 @@
|
|||||||
#![allow(incomplete_features)]
|
|
||||||
#![feature(native_link_modifiers)]
|
|
||||||
|
|
||||||
#[link(name = "foo", modifiers = "+verbatim")]
|
#[link(name = "foo", modifiers = "+verbatim")]
|
||||||
//~^ ERROR: `#[link(modifiers="verbatim")]` is unstable
|
//~^ ERROR: `#[link(modifiers="verbatim")]` is unstable
|
||||||
extern "C" {}
|
extern "C" {}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
error[E0658]: `#[link(modifiers="verbatim")]` is unstable
|
error[E0658]: `#[link(modifiers="verbatim")]` is unstable
|
||||||
--> $DIR/feature-gate-native_link_modifiers_verbatim.rs:4:34
|
--> $DIR/feature-gate-native_link_modifiers_verbatim.rs:1:34
|
||||||
|
|
|
|
||||||
LL | #[link(name = "foo", modifiers = "+verbatim")]
|
LL | #[link(name = "foo", modifiers = "+verbatim")]
|
||||||
| ^^^^^^^^^^^
|
| ^^^^^^^^^^^
|
||||||
|
@ -1,8 +0,0 @@
|
|||||||
#![allow(incomplete_features)]
|
|
||||||
#![feature(native_link_modifiers)]
|
|
||||||
|
|
||||||
#[link(name = "foo", modifiers = "+whole-archive")]
|
|
||||||
//~^ ERROR: `#[link(modifiers="whole-archive")]` is unstable
|
|
||||||
extern "C" {}
|
|
||||||
|
|
||||||
fn main() {}
|
|
@ -1,12 +0,0 @@
|
|||||||
error[E0658]: `#[link(modifiers="whole-archive")]` is unstable
|
|
||||||
--> $DIR/feature-gate-native_link_modifiers_whole_archive.rs:4:34
|
|
||||||
|
|
|
||||||
LL | #[link(name = "foo", modifiers = "+whole-archive")]
|
|
||||||
| ^^^^^^^^^^^^^^^^
|
|
||||||
|
|
|
||||||
= note: see issue #81490 <https://github.com/rust-lang/rust/issues/81490> for more information
|
|
||||||
= help: add `#![feature(native_link_modifiers_whole_archive)]` to the crate attributes to enable
|
|
||||||
|
|
||||||
error: aborting due to previous error
|
|
||||||
|
|
||||||
For more information about this error, try `rustc --explain E0658`.
|
|
@ -0,0 +1,12 @@
|
|||||||
|
error[E0276]: impl has stricter requirements than trait
|
||||||
|
--> $DIR/lending_iterator.rs:14:45
|
||||||
|
|
|
||||||
|
LL | fn from_iter<T: for<'x> LendingIterator<Item<'x> = A>>(iter: T) -> Self;
|
||||||
|
| ------------------------------------------------------------------------ definition of `from_iter` from trait
|
||||||
|
...
|
||||||
|
LL | fn from_iter<I: for<'x> LendingIterator<Item<'x> = A>>(mut iter: I) -> Self {
|
||||||
|
| ^^^^^^^^^^^^ impl has extra requirement `I: 'x`
|
||||||
|
|
||||||
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0276`.
|
@ -0,0 +1,26 @@
|
|||||||
|
error[E0276]: impl has stricter requirements than trait
|
||||||
|
--> $DIR/lending_iterator.rs:14:45
|
||||||
|
|
|
||||||
|
LL | fn from_iter<T: for<'x> LendingIterator<Item<'x> = A>>(iter: T) -> Self;
|
||||||
|
| ------------------------------------------------------------------------ definition of `from_iter` from trait
|
||||||
|
...
|
||||||
|
LL | fn from_iter<I: for<'x> LendingIterator<Item<'x> = A>>(mut iter: I) -> Self {
|
||||||
|
| ^^^^^^^^^^^^ impl has extra requirement `I: 'x`
|
||||||
|
|
||||||
|
error[E0311]: the parameter type `Self` may not live long enough
|
||||||
|
--> $DIR/lending_iterator.rs:35:9
|
||||||
|
|
|
||||||
|
LL | <B as FromLendingIterator<A>>::from_iter(self)
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
||||||
|
= help: consider adding an explicit lifetime bound `Self: 'a`...
|
||||||
|
= note: ...so that the type `Self` will meet its required lifetime bounds...
|
||||||
|
note: ...that is required by this bound
|
||||||
|
--> $DIR/lending_iterator.rs:10:45
|
||||||
|
|
|
||||||
|
LL | fn from_iter<T: for<'x> LendingIterator<Item<'x> = A>>(iter: T) -> Self;
|
||||||
|
| ^^^^^^^^^^^^
|
||||||
|
|
||||||
|
error: aborting due to 2 previous errors
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0276`.
|
@ -0,0 +1,40 @@
|
|||||||
|
// revisions: base extended
|
||||||
|
//[base] check-fail
|
||||||
|
//[extended] check-pass
|
||||||
|
|
||||||
|
#![feature(generic_associated_types)]
|
||||||
|
#![cfg_attr(extended, feature(generic_associated_types_extended))]
|
||||||
|
#![cfg_attr(extended, allow(incomplete_features))]
|
||||||
|
|
||||||
|
pub trait FromLendingIterator<A>: Sized {
|
||||||
|
fn from_iter<T: for<'x> LendingIterator<Item<'x> = A>>(iter: T) -> Self;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<A> FromLendingIterator<A> for Vec<A> {
|
||||||
|
fn from_iter<I: for<'x> LendingIterator<Item<'x> = A>>(mut iter: I) -> Self {
|
||||||
|
//[base]~^ impl has stricter
|
||||||
|
let mut v = vec![];
|
||||||
|
while let Some(item) = iter.next() {
|
||||||
|
v.push(item);
|
||||||
|
}
|
||||||
|
v
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait LendingIterator {
|
||||||
|
type Item<'z>
|
||||||
|
where
|
||||||
|
Self: 'z;
|
||||||
|
fn next(&mut self) -> Option<Self::Item<'_>>;
|
||||||
|
|
||||||
|
fn collect<A, B: FromLendingIterator<A>>(self) -> B
|
||||||
|
where
|
||||||
|
Self: Sized,
|
||||||
|
Self: for<'q> LendingIterator<Item<'q> = A>,
|
||||||
|
{
|
||||||
|
<B as FromLendingIterator<A>>::from_iter(self)
|
||||||
|
//[base]~^ the parameter type
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {}
|
@ -0,0 +1,12 @@
|
|||||||
|
error[E0276]: impl has stricter requirements than trait
|
||||||
|
--> $DIR/lending_iterator_2.rs:14:45
|
||||||
|
|
|
||||||
|
LL | fn from_iter<T: for<'x> LendingIterator<Item<'x> = A>>(iter: T) -> Self;
|
||||||
|
| ------------------------------------------------------------------------ definition of `from_iter` from trait
|
||||||
|
...
|
||||||
|
LL | fn from_iter<I: for<'x> LendingIterator<Item<'x> = A>>(mut iter: I) -> Self {
|
||||||
|
| ^^^^^^^^^^^^ impl has extra requirement `I: 'x`
|
||||||
|
|
||||||
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0276`.
|
@ -0,0 +1,31 @@
|
|||||||
|
// revisions: base extended
|
||||||
|
//[base] check-fail
|
||||||
|
//[extended] check-pass
|
||||||
|
|
||||||
|
#![feature(generic_associated_types)]
|
||||||
|
#![cfg_attr(extended, feature(generic_associated_types_extended))]
|
||||||
|
#![cfg_attr(extended, allow(incomplete_features))]
|
||||||
|
|
||||||
|
pub trait FromLendingIterator<A>: Sized {
|
||||||
|
fn from_iter<T: for<'x> LendingIterator<Item<'x> = A>>(iter: T) -> Self;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<A> FromLendingIterator<A> for Vec<A> {
|
||||||
|
fn from_iter<I: for<'x> LendingIterator<Item<'x> = A>>(mut iter: I) -> Self {
|
||||||
|
//[base]~^ impl has stricter
|
||||||
|
let mut v = vec![];
|
||||||
|
while let Some(item) = iter.next() {
|
||||||
|
v.push(item);
|
||||||
|
}
|
||||||
|
v
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait LendingIterator {
|
||||||
|
type Item<'a>
|
||||||
|
where
|
||||||
|
Self: 'a;
|
||||||
|
fn next(&mut self) -> Option<Self::Item<'_>>;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {}
|
@ -2,9 +2,7 @@
|
|||||||
// build-fail
|
// build-fail
|
||||||
// error-pattern: the linking modifiers `+bundle` and `+whole-archive` are not compatible with each other when generating rlibs
|
// error-pattern: the linking modifiers `+bundle` and `+whole-archive` are not compatible with each other when generating rlibs
|
||||||
|
|
||||||
#![feature(native_link_modifiers)]
|
|
||||||
#![feature(native_link_modifiers_bundle)]
|
#![feature(native_link_modifiers_bundle)]
|
||||||
#![feature(native_link_modifiers_whole_archive)]
|
|
||||||
|
|
||||||
#[link(name = "mylib", kind = "static", modifiers = "+bundle,+whole-archive")]
|
#[link(name = "mylib", kind = "static", modifiers = "+bundle,+whole-archive")]
|
||||||
extern "C" { }
|
extern "C" { }
|
||||||
|
@ -0,0 +1,3 @@
|
|||||||
|
// compile-flags:-lstatic:+whole-archive,-whole-archive=foo
|
||||||
|
|
||||||
|
fn main() {}
|
@ -0,0 +1,2 @@
|
|||||||
|
error: duplicating linking modifier is currently unstable and only accepted on the nightly compiler
|
||||||
|
|
17
src/test/ui/native-library-link-flags/modifiers-override.rs
Normal file
17
src/test/ui/native-library-link-flags/modifiers-override.rs
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
// compile-flags:-ldylib:+as-needed=foo -lstatic=bar -Zunstable-options
|
||||||
|
|
||||||
|
#![feature(native_link_modifiers_bundle)]
|
||||||
|
|
||||||
|
#[link(name = "foo")]
|
||||||
|
#[link( //~ ERROR multiple `modifiers` arguments in a single `#[link]` attribute
|
||||||
|
name = "bar",
|
||||||
|
kind = "static",
|
||||||
|
modifiers = "+whole-archive,-whole-archive",
|
||||||
|
//~^ ERROR same modifier is used multiple times in a single `modifiers` argument
|
||||||
|
modifiers = "+bundle"
|
||||||
|
)]
|
||||||
|
extern "C" {}
|
||||||
|
//~^ ERROR overriding linking modifiers from command line is not supported
|
||||||
|
//~| ERROR overriding linking modifiers from command line is not supported
|
||||||
|
|
||||||
|
fn main() {}
|
@ -0,0 +1,32 @@
|
|||||||
|
error: same modifier is used multiple times in a single `modifiers` argument
|
||||||
|
--> $DIR/modifiers-override.rs:9:5
|
||||||
|
|
|
||||||
|
LL | modifiers = "+whole-archive,-whole-archive",
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
error: multiple `modifiers` arguments in a single `#[link]` attribute
|
||||||
|
--> $DIR/modifiers-override.rs:6:1
|
||||||
|
|
|
||||||
|
LL | / #[link(
|
||||||
|
LL | | name = "bar",
|
||||||
|
LL | | kind = "static",
|
||||||
|
LL | | modifiers = "+whole-archive,-whole-archive",
|
||||||
|
LL | |
|
||||||
|
LL | | modifiers = "+bundle"
|
||||||
|
LL | | )]
|
||||||
|
| |__^
|
||||||
|
|
||||||
|
error: overriding linking modifiers from command line is not supported
|
||||||
|
--> $DIR/modifiers-override.rs:13:1
|
||||||
|
|
|
||||||
|
LL | extern "C" {}
|
||||||
|
| ^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
error: overriding linking modifiers from command line is not supported
|
||||||
|
--> $DIR/modifiers-override.rs:13:1
|
||||||
|
|
|
||||||
|
LL | extern "C" {}
|
||||||
|
| ^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
error: aborting due to 4 previous errors
|
||||||
|
|
@ -81,7 +81,7 @@ impl<'tcx> LateLintPass<'tcx> for Regex {
|
|||||||
|
|
||||||
#[allow(clippy::cast_possible_truncation)] // truncation very unlikely here
|
#[allow(clippy::cast_possible_truncation)] // truncation very unlikely here
|
||||||
#[must_use]
|
#[must_use]
|
||||||
fn str_span(base: Span, c: regex_syntax::ast::Span, offset: u16) -> Span {
|
fn str_span(base: Span, c: regex_syntax::ast::Span, offset: u8) -> Span {
|
||||||
let offset = u32::from(offset);
|
let offset = u32::from(offset);
|
||||||
let end = base.lo() + BytePos(u32::try_from(c.end.offset).expect("offset too large") + offset);
|
let end = base.lo() + BytePos(u32::try_from(c.end.offset).expect("offset too large") + offset);
|
||||||
let start = base.lo() + BytePos(u32::try_from(c.start.offset).expect("offset too large") + offset);
|
let start = base.lo() + BytePos(u32::try_from(c.start.offset).expect("offset too large") + offset);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user