diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index f5c4affdce2d1..75ccbc92be1f6 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -1616,7 +1616,7 @@ pub enum StrStyle { /// A raw string, like `r##"foo"##`. /// /// The value is the number of `#` symbols used. - Raw(u16), + Raw(u8), } /// An AST literal. diff --git a/compiler/rustc_ast/src/token.rs b/compiler/rustc_ast/src/token.rs index 7df385873c116..2132cdfc001b6 100644 --- a/compiler/rustc_ast/src/token.rs +++ b/compiler/rustc_ast/src/token.rs @@ -59,9 +59,9 @@ pub enum LitKind { Integer, Float, Str, - StrRaw(u16), // raw string delimited by `n` hash symbols + StrRaw(u8), // raw string delimited by `n` hash symbols ByteStr, - ByteStrRaw(u16), // raw byte string delimited by `n` hash symbols + ByteStrRaw(u8), // raw byte string delimited by `n` hash symbols Err, } diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs index d64f1a05712a9..9442e0f1a1f35 100644 --- a/compiler/rustc_ast_lowering/src/expr.rs +++ b/compiler/rustc_ast_lowering/src/expr.rs @@ -618,9 +618,9 @@ impl<'hir> LoweringContext<'_, 'hir> { /// Desugar `.await` into: /// ```rust /// match ::std::future::IntoFuture::into_future() { - /// mut pinned => loop { + /// mut __awaitee => loop { /// 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::task::Poll::Ready(result) => break result, @@ -657,21 +657,24 @@ impl<'hir> LoweringContext<'_, 'hir> { let expr = self.lower_expr_mut(expr); let expr_hir_id = expr.hir_id; - let pinned_ident = Ident::with_dummy_span(sym::pinned); - let (pinned_pat, pinned_pat_hid) = - self.pat_ident_binding_mode(span, pinned_ident, hir::BindingAnnotation::Mutable); + // Note that the name of this binding must not be changed to something else because + // debuggers and debugger extensions expect it to be called `__awaitee`. They use + // 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); // 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), // ) // } let poll_expr = { - let pinned = self.expr_ident(span, pinned_ident, pinned_pat_hid); - let ref_mut_pinned = self.expr_mut_addr_of(span, pinned); + let awaitee = self.expr_ident(span, awaitee_ident, awaitee_pat_hid); + let ref_mut_awaitee = self.expr_mut_addr_of(span, awaitee); let task_context = if let Some(task_context_hid) = self.task_context { self.expr_ident_mut(span, task_context_ident, task_context_hid) } else { @@ -681,7 +684,7 @@ impl<'hir> LoweringContext<'_, 'hir> { let new_unchecked = self.expr_call_lang_item_fn_mut( span, hir::LangItem::PinNewUnchecked, - arena_vec![self; ref_mut_pinned], + arena_vec![self; ref_mut_awaitee], Some(expr_hir_id), ); let get_context = self.expr_call_lang_item_fn_mut( @@ -782,8 +785,8 @@ impl<'hir> LoweringContext<'_, 'hir> { span: self.lower_span(span), }); - // mut pinned => loop { ... } - let pinned_arm = self.arm(pinned_pat, loop_expr); + // mut __awaitee => loop { ... } + let awaitee_arm = self.arm(awaitee_pat, loop_expr); // `match ::std::future::IntoFuture::into_future() { ... }` let into_future_span = self.mark_span_with_reason( @@ -799,11 +802,11 @@ impl<'hir> LoweringContext<'_, 'hir> { ); // match { - // mut pinned => loop { .. } + // mut __awaitee => loop { .. } // } hir::ExprKind::Match( into_future_expr, - arena_vec![self; pinned_arm], + arena_vec![self; awaitee_arm], hir::MatchSource::AwaitDesugar, ) } diff --git a/compiler/rustc_ast_passes/src/feature_gate.rs b/compiler/rustc_ast_passes/src/feature_gate.rs index 5b6147c72230d..a778d8c547084 100644 --- a/compiler/rustc_ast_passes/src/feature_gate.rs +++ b/compiler/rustc_ast_passes/src/feature_gate.rs @@ -387,13 +387,6 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { if attr.has_name(sym::link) { for nested_meta in attr.meta_item_list().unwrap_or_default() { 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() { for modifier in modifiers.as_str().split(',') { if let Some(modifier) = modifier.strip_prefix(&['+', '-']) { @@ -412,7 +405,6 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { gate_modifier!( "bundle" => native_link_modifiers_bundle "verbatim" => native_link_modifiers_verbatim - "whole-archive" => native_link_modifiers_whole_archive "as-needed" => native_link_modifiers_as_needed ); } diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index dbbbbd5ecc020..548ae0e411da7 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -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 // as whole-archive (#85144), so removing whole-archive may be a pre-requisite. 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 @@ -2016,6 +2016,16 @@ fn add_order_independent_options( 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 /// /// 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, sess: &Session, codegen_results: &CodegenResults, + crate_type: CrateType, ) { let filesearch = sess.target_filesearch(PathKind::All); 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)); let search_path = OnceCell::new(); - let mut last = (NativeLibKind::Unspecified, None); + let mut last = (None, NativeLibKind::Unspecified, None); for lib in relevant_libs { let Some(name) = lib.name else { continue; }; // 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); match lib.kind { @@ -2064,15 +2079,19 @@ fn add_local_native_libraries( NativeLibKind::Framework { as_needed } => { cmd.link_framework(name, as_needed.unwrap_or(true)) } - NativeLibKind::Static { bundle: None | Some(true), .. } - | NativeLibKind::Static { whole_archive: Some(true), .. } => { - cmd.link_whole_staticlib( - name, - verbatim, - &search_path.get_or_init(|| archive_search_paths(sess)), - ); + NativeLibKind::Static { whole_archive, .. } => { + if whole_archive == Some(true) + || (whole_archive == None && default_to_whole_archive(sess, crate_type, cmd)) + { + cmd.link_whole_staticlib( + 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 => { // FIXME(#58713): Proper handling for raw dylibs. 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 // will provide them to the linker itself. 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] { + let Some(name) = lib.name else { + continue; + }; if !relevant_lib(sess, lib) { - // Skip libraries if they are disabled by `#[link(cfg=...)]` continue; } // Skip if this library is the same as the last. - if last == lib.name { + last = if (lib.name, lib.kind, lib.verbatim) == last { continue; - } - - if let Some(static_lib_name) = lib.name { - if let NativeLibKind::Static { bundle: Some(false), whole_archive } = - lib.kind + } else { + (lib.name, lib.kind, lib.verbatim) + }; + + if let NativeLibKind::Static { bundle: Some(false), whole_archive } = + 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); - if whole_archive == Some(true) { - cmd.link_whole_staticlib( - static_lib_name, - verbatim, - search_path.get_or_init(|| archive_search_paths(sess)), - ); - } else { - cmd.link_staticlib(static_lib_name, verbatim); - } - - last = lib.name; + cmd.link_whole_staticlib( + name, + verbatim, + search_path.get_or_init(|| archive_search_paths(sess)), + ); + } else { + cmd.link_staticlib(name, verbatim); } } } @@ -2282,15 +2304,10 @@ fn add_upstream_rust_crates<'a, B: ArchiveBuilder<'a>>( let cratepath = &src.rlib.as_ref().unwrap().0; let mut link_upstream = |path: &Path| { - // If we're creating a dylib, then we need to include the - // whole of each object in our archive into that artifact. This is - // 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. + // We don't want to include the whole compiler-builtins crate (e.g., compiler-rt) + // regardless of the default because it'll get repeatedly linked anyway. 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) { cmd.link_whole_rlib(&path); @@ -2401,7 +2418,7 @@ fn add_upstream_native_libraries( sess: &Session, 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 lib in codegen_results.crate_info.native_libraries[&cnum].iter() { 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. - 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); match lib.kind { diff --git a/compiler/rustc_codegen_ssa/src/back/linker.rs b/compiler/rustc_codegen_ssa/src/back/linker.rs index a838787381d3f..3a66bfafaf3f4 100644 --- a/compiler/rustc_codegen_ssa/src/back/linker.rs +++ b/compiler/rustc_codegen_ssa/src/back/linker.rs @@ -186,6 +186,9 @@ pub trait Linker { fn no_crt_objects(&mut self); fn no_default_libraries(&mut self); 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 group_start(&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) { self.linker_arg("--subsystem"); self.linker_arg(&subsystem); @@ -1471,6 +1478,10 @@ impl<'a> Linker for L4Bender<'a> { return; } + fn exported_symbol_means_used_symbol(&self) -> bool { + false + } + fn subsystem(&mut self, subsystem: &str) { self.cmd.arg(&format!("--subsystem {}", subsystem)); } diff --git a/compiler/rustc_feature/src/accepted.rs b/compiler/rustc_feature/src/accepted.rs index ace0c9df58d50..e37251c9c2439 100644 --- a/compiler/rustc_feature/src/accepted.rs +++ b/compiler/rustc_feature/src/accepted.rs @@ -215,6 +215,10 @@ declare_features! ( /// 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. (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]`. (accepted, no_std, "1.6.0", None, None), /// Allows defining identifiers beyond ASCII. diff --git a/compiler/rustc_feature/src/active.rs b/compiler/rustc_feature/src/active.rs index feef7295254a9..28466315c8687 100644 --- a/compiler/rustc_feature/src/active.rs +++ b/compiler/rustc_feature/src/active.rs @@ -400,6 +400,8 @@ declare_features! ( (active, generic_arg_infer, "1.55.0", Some(85077), None), /// Allows associated types to be generic, e.g., `type Foo;` (RFC 1598). (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 (incomplete, generic_const_exprs, "1.56.0", Some(76560), None), /// 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), /// Allows using `#[naked]` on functions. (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 (active, native_link_modifiers_as_needed, "1.53.0", Some(81490), None), /// Allows specifying the bundle link modifier (active, native_link_modifiers_bundle, "1.53.0", Some(81490), None), /// Allows specifying the verbatim link modifier (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. (active, negative_impls, "1.44.0", Some(68318), None), /// Allows the `!` type. Does not imply 'exhaustive_patterns' (below) any more. diff --git a/compiler/rustc_lexer/src/lib.rs b/compiler/rustc_lexer/src/lib.rs index 5b8300ab530f9..a41e0374f410a 100644 --- a/compiler/rustc_lexer/src/lib.rs +++ b/compiler/rustc_lexer/src/lib.rs @@ -161,15 +161,15 @@ pub enum LiteralKind { /// "b"abc"", "b"abc" ByteStr { terminated: bool }, /// "r"abc"", "r#"abc"#", "r####"ab"###"c"####", "r#"a" - RawStr { n_hashes: u16, err: Option }, + RawStr { n_hashes: u8, err: Option }, /// "br"abc"", "br#"abc"#", "br####"ab"###"c"####", "br#"a" - RawByteStr { n_hashes: u16, err: Option }, + RawByteStr { n_hashes: u8, err: Option }, } /// Error produced validating a raw string. Represents cases like: /// - `r##~"abcde"##`: `InvalidStarter` /// - `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 #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)] 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 /// may have intended to terminate it. NoTerminator { expected: usize, found: usize, possible_terminator_offset: Option }, - /// More than 65535 `#`s exist. + /// More than 255 `#`s exist. TooManyDelimiters { found: usize }, } @@ -698,12 +698,12 @@ impl Cursor<'_> { } /// 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) { + fn raw_double_quoted_string(&mut self, prefix_len: usize) -> (u8, Option) { // Wrap the actual function to handle the error with too many hashes. // This way, it eats the whole raw string. let (n_hashes, err) = self.raw_string_unvalidated(prefix_len); - // Only up to 65535 `#`s are allowed in raw strings - match u16::try_from(n_hashes) { + // Only up to 255 `#`s are allowed in raw strings + match u8::try_from(n_hashes) { Ok(num) => (num, err), // We lie about the number of hashes here :P Err(_) => (0, Some(RawStrError::TooManyDelimiters { found: n_hashes })), diff --git a/compiler/rustc_lexer/src/tests.rs b/compiler/rustc_lexer/src/tests.rs index 548de67449abf..07daee06f0f86 100644 --- a/compiler/rustc_lexer/src/tests.rs +++ b/compiler/rustc_lexer/src/tests.rs @@ -2,7 +2,7 @@ use super::*; use expect_test::{expect, Expect}; -fn check_raw_str(s: &str, expected_hashes: u16, expected_err: Option) { +fn check_raw_str(s: &str, expected_hashes: u8, expected_err: Option) { let s = &format!("r{}", s); let mut cursor = Cursor::new(s); cursor.bump(); @@ -68,13 +68,13 @@ fn test_unterminated_no_pound() { #[test] fn test_too_many_hashes() { - let max_count = u16::MAX; + let max_count = u8::MAX; 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}' })); - // One more hash sign (65536 = 2^16) becomes too many. + // One more hash sign (256 = 2^8) becomes too many. hashes.push('#'); check_raw_str( &hashes, diff --git a/compiler/rustc_llvm/src/lib.rs b/compiler/rustc_llvm/src/lib.rs index 8476c2bfcc431..0324ac3641e11 100644 --- a/compiler/rustc_llvm/src/lib.rs +++ b/compiler/rustc_llvm/src/lib.rs @@ -1,5 +1,5 @@ #![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/")] // NOTE: This crate only exists to allow linking on mingw targets. diff --git a/compiler/rustc_metadata/src/native_libs.rs b/compiler/rustc_metadata/src/native_libs.rs index c3a7611239139..1cbfb0bd5546b 100644 --- a/compiler/rustc_metadata/src/native_libs.rs +++ b/compiler/rustc_metadata/src/native_libs.rs @@ -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 // 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() { + modifiers_count += 1; let span = item.name_value_literal_span().unwrap(); + let mut has_duplicate_modifiers = false; for modifier in modifiers.as_str().split(',') { let (modifier, value) = match modifier.strip_prefix(&['+', '-']) { Some(m) => (m, modifier.starts_with('+')), None => { + // Note: this error also excludes the case with empty modifier + // string, like `modifiers = ""`. sess.span_err( span, "invalid linking modifier syntax, expected '+' or '-' prefix \ @@ -143,6 +148,9 @@ impl<'tcx> ItemLikeVisitor<'tcx> for Collector<'tcx> { match (modifier, &mut lib.kind) { ("bundle", NativeLibKind::Static { bundle, .. }) => { + if bundle.is_some() { + has_duplicate_modifiers = true; + } *bundle = Some(value); } ("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, .. }) => { + if whole_archive.is_some() { + has_duplicate_modifiers = true; + } *whole_archive = Some(value); } ("whole-archive", _) => { @@ -168,6 +184,9 @@ impl<'tcx> ItemLikeVisitor<'tcx> for Collector<'tcx> { ("as-needed", NativeLibKind::Dylib { as_needed }) | ("as-needed", NativeLibKind::Framework { as_needed }) => { + if as_needed.is_some() { + has_duplicate_modifiers = true; + } *as_needed = Some(value); } ("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 { let msg = "must be of the form `#[link(modifiers = \"...\")]`"; 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 // #[link(wasm_import_module = "...")] without the `name`. let requires_name = kind_specified || lib.wasm_import_module.is_none(); @@ -349,6 +378,15 @@ impl Collector<'_> { .drain_filter(|lib| { if let Some(lib_name) = 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 { lib.kind = passed_lib.kind; } diff --git a/compiler/rustc_middle/src/ty/fold.rs b/compiler/rustc_middle/src/ty/fold.rs index 388109e6512dd..075928c889d83 100644 --- a/compiler/rustc_middle/src/ty/fold.rs +++ b/compiler/rustc_middle/src/ty/fold.rs @@ -1379,3 +1379,50 @@ impl<'tcx> TypeVisitor<'tcx> for LateBoundRegionsCollector { 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 { + 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 { + 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 { + 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 + } +} diff --git a/compiler/rustc_parse/src/lexer/mod.rs b/compiler/rustc_parse/src/lexer/mod.rs index 92c5d329f6e86..5ab412dc777de 100644 --- a/compiler/rustc_parse/src/lexer/mod.rs +++ b/compiler/rustc_parse/src/lexer/mod.rs @@ -597,15 +597,13 @@ impl<'a> StringReader<'a> { } } - /// Note: It was decided to not add a test case, because it would be too big. - /// fn report_too_many_hashes(&self, start: BytePos, found: usize) -> ! { self.fatal_span_( start, self.pos, &format!( "too many `#` symbols: raw strings may be delimited \ - by up to 65535 `#` symbols, but found {}", + by up to 255 `#` symbols, but found {}", found ), ) diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs index 44a2e2bdc85d3..856436e44dbc8 100644 --- a/compiler/rustc_session/src/config.rs +++ b/compiler/rustc_session/src/config.rs @@ -1948,9 +1948,6 @@ fn parse_native_lib_kind( kind: &str, error_format: ErrorOutputType, ) -> (NativeLibKind, Option) { - 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(':') { None => (kind, None), 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`", ) } - if !is_nightly { + if !nightly_options::match_is_nightly_build(matches) { early_error( error_format, "library kind `static-nobundle` are currently unstable and only accepted on \ @@ -1988,23 +1985,7 @@ fn parse_native_lib_kind( }; match modifiers { None => (kind, None), - Some(modifiers) => { - 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) - } + Some(modifiers) => parse_native_lib_modifiers(kind, modifiers, error_format, matches), } } @@ -2012,7 +1993,23 @@ fn parse_native_lib_modifiers( mut kind: NativeLibKind, modifiers: &str, error_format: ErrorOutputType, + matches: &getopts::Matches, ) -> (NativeLibKind, Option) { + 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; for modifier in modifiers.split(',') { let (modifier, value) = match modifier.strip_prefix(&['+', '-']) { @@ -2026,6 +2023,10 @@ fn parse_native_lib_modifiers( match (modifier, &mut kind) { ("bundle", NativeLibKind::Static { bundle, .. }) => { + report_unstable_modifier(modifier); + if bundle.is_some() { + has_duplicate_modifiers = true; + } *bundle = Some(value); } ("bundle", _) => early_error( @@ -2034,9 +2035,18 @@ fn parse_native_lib_modifiers( `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, .. }) => { + if whole_archive.is_some() { + has_duplicate_modifiers = true; + } *whole_archive = Some(value); } ("whole-archive", _) => early_error( @@ -2047,6 +2057,10 @@ fn parse_native_lib_modifiers( ("as-needed", NativeLibKind::Dylib { 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", _) => early_error( @@ -2055,6 +2069,8 @@ fn parse_native_lib_modifiers( `dylib` and `framework` linking kinds", ), + // Note: this error also excludes the case with empty modifier + // string, like `modifiers = ""`. _ => early_error( error_format, &format!( @@ -2064,6 +2080,9 @@ fn parse_native_lib_modifiers( ), } } + if has_duplicate_modifiers { + report_unstable_modifier("duplicating") + } (kind, verbatim) } diff --git a/compiler/rustc_session/src/cstore.rs b/compiler/rustc_session/src/cstore.rs index 281fc887633d9..c1fd3c7c61b9e 100644 --- a/compiler/rustc_session/src/cstore.rs +++ b/compiler/rustc_session/src/cstore.rs @@ -75,6 +75,12 @@ pub struct NativeLib { pub dll_imports: Vec, } +impl NativeLib { + pub fn has_modifiers(&self) -> bool { + self.verbatim.is_some() || self.kind.has_modifiers() + } +} + #[derive(Clone, Debug, Encodable, Decodable, HashStable_Generic)] pub struct DllImport { pub name: Symbol, diff --git a/compiler/rustc_session/src/utils.rs b/compiler/rustc_session/src/utils.rs index a33f94013d24c..6a8775bd10b7e 100644 --- a/compiler/rustc_session/src/utils.rs +++ b/compiler/rustc_session/src/utils.rs @@ -43,6 +43,20 @@ pub enum NativeLibKind { 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); #[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Encodable, Decodable)] @@ -53,6 +67,12 @@ pub struct NativeLib { pub verbatim: Option, } +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); /// A path that has been canonicalized along with its original, non-canonicalized form diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 84dbad846dd29..0bca0a99e157f 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -272,6 +272,7 @@ symbols! { __D, __H, __S, + __awaitee, __try_var, _d, _e, @@ -722,6 +723,7 @@ symbols! { generators, generic_arg_infer, generic_associated_types, + generic_associated_types_extended, generic_const_exprs, generic_param_attrs, get_context, @@ -1018,7 +1020,6 @@ symbols! { pattern_parentheses, phantom_data, pin, - pinned, platform_intrinsics, plugin, plugin_registrar, diff --git a/compiler/rustc_trait_selection/src/traits/auto_trait.rs b/compiler/rustc_trait_selection/src/traits/auto_trait.rs index 36eddf7784b32..d95512bb88f36 100644 --- a/compiler/rustc_trait_selection/src/traits/auto_trait.rs +++ b/compiler/rustc_trait_selection/src/traits/auto_trait.rs @@ -5,6 +5,7 @@ use super::*; use crate::infer::region_constraints::{Constraint, RegionConstraintData}; use crate::infer::InferCtxt; +use crate::traits::project::ProjectAndUnifyResult; use rustc_middle::ty::fold::TypeFolder; use rustc_middle::ty::{Region, RegionVid, Term}; @@ -751,7 +752,7 @@ impl<'tcx> AutoTraitFinder<'tcx> { debug!("Projecting and unifying projection predicate {:?}", predicate); match project::poly_project_and_unify_type(select, &obligation.with(p)) { - Err(e) => { + ProjectAndUnifyResult::MismatchedProjectionTypes(e) => { debug!( "evaluate_nested_obligations: Unable to unify predicate \ '{:?}' '{:?}', bailing out", @@ -759,11 +760,11 @@ impl<'tcx> AutoTraitFinder<'tcx> { ); return false; } - Ok(Err(project::InProgress)) => { + ProjectAndUnifyResult::Recursive => { debug!("evaluate_nested_obligations: recursive projection predicate"); return false; } - Ok(Ok(Some(v))) => { + ProjectAndUnifyResult::Holds(v) => { // We only care about sub-obligations // when we started out trying to unify // 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 - // in that case, we were only performing unification to check if an // error occurred (which would indicate that it's impossible for our diff --git a/compiler/rustc_trait_selection/src/traits/fulfill.rs b/compiler/rustc_trait_selection/src/traits/fulfill.rs index 1b8628344671d..d0b8b0281c5bf 100644 --- a/compiler/rustc_trait_selection/src/traits/fulfill.rs +++ b/compiler/rustc_trait_selection/src/traits/fulfill.rs @@ -14,7 +14,7 @@ use rustc_middle::ty::{self, Binder, Const, Ty, TypeFoldable}; use std::marker::PhantomData; use super::const_evaluatable; -use super::project; +use super::project::{self, ProjectAndUnifyResult}; use super::select::SelectionContext; use super::wf; 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) { - Ok(Ok(Some(os))) => ProcessResult::Changed(mk_pending(os)), - Ok(Ok(None)) => { + ProjectAndUnifyResult::Holds(os) => ProcessResult::Changed(mk_pending(os)), + ProjectAndUnifyResult::FailedNormalization => { stalled_on.clear(); stalled_on.extend(substs_infer_vars( self.selcx, @@ -763,10 +763,12 @@ impl<'a, 'b, 'tcx> FulfillProcessor<'a, 'b, 'tcx> { ProcessResult::Unchanged } // 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)), ])), - Err(e) => ProcessResult::Error(CodeProjectionError(e)), + ProjectAndUnifyResult::MismatchedProjectionTypes(e) => { + ProcessResult::Error(CodeProjectionError(e)) + } } } } diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs index d4ec677a0b1c5..2251f992e4dc6 100644 --- a/compiler/rustc_trait_selection/src/traits/project.rs +++ b/compiler/rustc_trait_selection/src/traits/project.rs @@ -28,7 +28,7 @@ use rustc_hir::def_id::DefId; use rustc_hir::lang_items::LangItem; use rustc_infer::infer::resolve::OpportunisticRegionResolver; 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::{self, Term, ToPredicate, Ty, TyCtxt}; use rustc_span::symbol::sym; @@ -144,6 +144,18 @@ impl<'tcx> ProjectionCandidateSet<'tcx> { } } +/// Takes the place of a +/// Result< +/// Result>>, InProgress>, +/// MismatchedProjectionTypes<'tcx>, +/// > +pub(super) enum ProjectAndUnifyResult<'tcx> { + Holds(Vec>), + FailedNormalization, + Recursive, + MismatchedProjectionTypes(MismatchedProjectionTypes<'tcx>), +} + /// Evaluates constraints of the form: /// /// for<...> ::U == V @@ -167,19 +179,47 @@ impl<'tcx> ProjectionCandidateSet<'tcx> { pub(super) fn poly_project_and_unify_type<'cx, 'tcx>( selcx: &mut SelectionContext<'cx, 'tcx>, obligation: &PolyProjectionObligation<'tcx>, -) -> Result< - Result>>, InProgress>, - MismatchedProjectionTypes<'tcx>, -> { +) -> ProjectAndUnifyResult<'tcx> { let infcx = selcx.infcx(); - infcx.commit_if_ok(|_snapshot| { + let r = infcx.commit_if_ok(|_snapshot| { + let old_universe = infcx.universe(); let placeholder_predicate = infcx.replace_bound_vars_with_placeholders(obligation.predicate); + let new_universe = infcx.universe(); let placeholder_obligation = obligation.with(placeholder_predicate); - let result = project_and_unify_type(selcx, &placeholder_obligation)?; - Ok(result) - }) + match project_and_unify_type(selcx, &placeholder_obligation) { + 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: @@ -189,15 +229,11 @@ pub(super) fn poly_project_and_unify_type<'cx, 'tcx>( /// If successful, this may result in additional obligations. /// /// 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>( selcx: &mut SelectionContext<'cx, 'tcx>, obligation: &ProjectionObligation<'tcx>, -) -> Result< - Result>>, InProgress>, - MismatchedProjectionTypes<'tcx>, -> { - debug!(?obligation, "project_and_unify_type"); - +) -> ProjectAndUnifyResult<'tcx> { let mut obligations = vec![]; let infcx = selcx.infcx(); @@ -210,8 +246,8 @@ fn project_and_unify_type<'cx, 'tcx>( &mut obligations, ) { Ok(Some(n)) => n, - Ok(None) => return Ok(Ok(None)), - Err(InProgress) => return Ok(Err(InProgress)), + Ok(None) => return ProjectAndUnifyResult::FailedNormalization, + Err(InProgress) => return ProjectAndUnifyResult::Recursive, }; debug!(?normalized, ?obligations, "project_and_unify_type result"); 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) { Ok(InferOk { obligations: inferred_obligations, value: () }) => { obligations.extend(inferred_obligations); - Ok(Ok(Some(obligations))) + ProjectAndUnifyResult::Holds(obligations) } Err(err) => { - debug!("project_and_unify_type: equating types encountered error {:?}", err); - Err(MismatchedProjectionTypes { err }) + debug!("equating types encountered error {:?}", err); + ProjectAndUnifyResult::MismatchedProjectionTypes(MismatchedProjectionTypes { err }) } } } diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index 42f17721f9b54..4f033d45c1f32 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -21,6 +21,7 @@ use super::{ use crate::infer::{InferCtxt, InferOk, TypeFreshener}; use crate::traits::error_reporting::InferCtxtExt; +use crate::traits::project::ProjectAndUnifyResult; use crate::traits::project::ProjectionCacheKeyExt; use crate::traits::ProjectionCacheKey; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; @@ -525,7 +526,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { let data = bound_predicate.rebind(data); let project_obligation = obligation.with(data); match project::poly_project_and_unify_type(self, &project_obligation) { - Ok(Ok(Some(mut subobligations))) => { + ProjectAndUnifyResult::Holds(mut subobligations) => { 'compute_res: { // If we've previously marked this projection as 'complete', then // use the final cached result (either `EvaluatedToOk` or @@ -573,9 +574,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { res } } - Ok(Ok(None)) => Ok(EvaluatedToAmbig), - Ok(Err(project::InProgress)) => Ok(EvaluatedToRecur), - Err(_) => Ok(EvaluatedToErr), + ProjectAndUnifyResult::FailedNormalization => Ok(EvaluatedToAmbig), + ProjectAndUnifyResult::Recursive => Ok(EvaluatedToRecur), + ProjectAndUnifyResult::MismatchedProjectionTypes(_) => Ok(EvaluatedToErr), } } diff --git a/library/alloc/src/vec/into_iter.rs b/library/alloc/src/vec/into_iter.rs index cc6dfb0e33017..03c532bb69769 100644 --- a/library/alloc/src/vec/into_iter.rs +++ b/library/alloc/src/vec/into_iter.rs @@ -8,7 +8,8 @@ use core::iter::{ FusedIterator, InPlaceIterable, SourceIter, TrustedLen, TrustedRandomAccessNoCoerce, }; use core::marker::PhantomData; -use core::mem::{self}; +use core::mem::{self, ManuallyDrop}; +use core::ops::Deref; use core::ptr::{self, NonNull}; use core::slice::{self}; @@ -32,7 +33,9 @@ pub struct IntoIter< pub(super) buf: NonNull, pub(super) phantom: PhantomData, 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, pub(super) ptr: *const T, pub(super) end: *const T, } @@ -295,11 +298,11 @@ where impl Clone for IntoIter { #[cfg(not(test))] 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)] 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 { impl Drop for DropGuard<'_, T, A> { fn drop(&mut self) { unsafe { - // `IntoIter::alloc` is not used anymore after this - let alloc = ptr::read(&self.0.alloc); + // `IntoIter::alloc` is not used anymore after this and will be dropped by RawVec + let alloc = ManuallyDrop::take(&mut self.0.alloc); // RawVec handles deallocation let _ = RawVec::from_raw_parts_in(self.0.buf.as_ptr(), self.0.cap, alloc); } diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs index 1ca5ee5537582..9773ec023377f 100644 --- a/library/alloc/src/vec/mod.rs +++ b/library/alloc/src/vec/mod.rs @@ -2579,7 +2579,7 @@ impl IntoIterator for Vec { fn into_iter(self) -> IntoIter { unsafe { 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 end = if mem::size_of::() == 0 { arith_offset(begin as *const i8, me.len() as isize) as *const T diff --git a/library/alloc/tests/vec.rs b/library/alloc/tests/vec.rs index ca0fcc855c7b8..19e39ebf910b5 100644 --- a/library/alloc/tests/vec.rs +++ b/library/alloc/tests/vec.rs @@ -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::borrow::Cow; use std::cell::Cell; @@ -991,6 +994,31 @@ fn test_into_iter_advance_by() { 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, core::alloc::AllocError> { + System.allocate(layout) + } + + unsafe fn deallocate(&self, ptr: NonNull, layout: Layout) { + System.deallocate(ptr, layout) + } + } + + let mut drop_count = 0; + + let allocator = ReferenceCountedAllocator(DropCounter { count: &mut drop_count }); + let _ = Vec::::new_in(allocator); + assert_eq!(drop_count, 1); + + let allocator = ReferenceCountedAllocator(DropCounter { count: &mut drop_count }); + let _ = Vec::::new_in(allocator).into_iter(); + assert_eq!(drop_count, 2); +} + #[test] fn test_from_iter_specialization() { let src: Vec = vec![0usize; 1]; diff --git a/library/unwind/src/lib.rs b/library/unwind/src/lib.rs index 079626f0fea54..82f1e63f4b54f 100644 --- a/library/unwind/src/lib.rs +++ b/library/unwind/src/lib.rs @@ -1,7 +1,7 @@ #![no_std] #![unstable(feature = "panic_unwind", issue = "32837")] #![feature(link_cfg)] -#![feature(native_link_modifiers)] +#![cfg_attr(bootstrap, feature(native_link_modifiers))] #![feature(native_link_modifiers_bundle)] #![feature(nll)] #![feature(staged_api)] diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs index 8f076ad914d9a..570a61742bcf3 100644 --- a/src/bootstrap/lib.rs +++ b/src/bootstrap/lib.rs @@ -117,6 +117,7 @@ use std::os::unix::fs::symlink as symlink_file; use std::os::windows::fs::symlink_file; use filetime::FileTime; +use once_cell::sync::OnceCell; use crate::builder::Kind; use crate::config::{LlvmLibunwind, TargetSelection}; @@ -904,7 +905,12 @@ impl Build { /// Returns the sysroot of the snapshot compiler. fn rustc_snapshot_sysroot(&self) -> &Path { - self.initial_rustc.parent().unwrap().parent().unwrap() + static SYSROOT_CACHE: OnceCell = 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. diff --git a/src/doc/rustc/src/command-line-arguments.md b/src/doc/rustc/src/command-line-arguments.md index 3759cb632bb3f..7838696cc128b 100644 --- a/src/doc/rustc/src/command-line-arguments.md +++ b/src/doc/rustc/src/command-line-arguments.md @@ -37,6 +37,8 @@ KIND=PATH` where `KIND` may be one of: ## `-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 a crate. @@ -47,7 +49,13 @@ where `KIND` may be one of: - `static` — A native static library (such as a `.a` archive). - `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 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 @@ -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 +### 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. + ## `--crate-type`: a list of types of crates for the compiler to emit diff --git a/src/doc/unstable-book/src/language-features/native-link-modifiers-whole-archive.md b/src/doc/unstable-book/src/language-features/native-link-modifiers-whole-archive.md deleted file mode 100644 index 4961e88cad1e0..0000000000000 --- a/src/doc/unstable-book/src/language-features/native-link-modifiers-whole-archive.md +++ /dev/null @@ -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`. diff --git a/src/doc/unstable-book/src/language-features/native-link-modifiers.md b/src/doc/unstable-book/src/language-features/native-link-modifiers.md deleted file mode 100644 index fc8b575462175..0000000000000 --- a/src/doc/unstable-book/src/language-features/native-link-modifiers.md +++ /dev/null @@ -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. diff --git a/src/test/codegen/async-fn-debug-awaitee-field.rs b/src/test/codegen/async-fn-debug-awaitee-field.rs new file mode 100644 index 0000000000000..efb345fa9f3e5 --- /dev/null +++ b/src/test/codegen/async-fn-debug-awaitee-field.rs @@ -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$", +// 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", +// MSVC: [[AWAITEE_TYPE]] = !DICompositeType(tag: DW_TAG_structure_type, name: "GenFuture >", + +fn main() { + let _fn = async_fn_test(); +} diff --git a/src/test/run-make/native-link-modifier-whole-archive/native_lib_in_src.rs b/src/test/run-make/native-link-modifier-whole-archive/native_lib_in_src.rs index 373d89b7936e5..2436c36e6ebfb 100644 --- a/src/test/run-make/native-link-modifier-whole-archive/native_lib_in_src.rs +++ b/src/test/run-make/native-link-modifier-whole-archive/native_lib_in_src.rs @@ -1,6 +1,4 @@ #![feature(native_link_modifiers_bundle)] -#![feature(native_link_modifiers_whole_archive)] -#![feature(native_link_modifiers)] use std::io::Write; diff --git a/src/test/run-make/raw-dylib-c/lib.rs b/src/test/run-make/raw-dylib-c/lib.rs index d8e6301f38eb8..e185c4aec12b0 100644 --- a/src/test/run-make/raw-dylib-c/lib.rs +++ b/src/test/run-make/raw-dylib-c/lib.rs @@ -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")] extern { diff --git a/src/test/ui/feature-gates/feature-gate-generic_associated_types_extended.rs b/src/test/ui/feature-gates/feature-gate-generic_associated_types_extended.rs new file mode 100644 index 0000000000000..258b8cd35c777 --- /dev/null +++ b/src/test/ui/feature-gates/feature-gate-generic_associated_types_extended.rs @@ -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() {} diff --git a/src/test/ui/feature-gates/feature-gate-generic_associated_types_extended.stderr b/src/test/ui/feature-gates/feature-gate-generic_associated_types_extended.stderr new file mode 100644 index 0000000000000..6a5eba38cacc6 --- /dev/null +++ b/src/test/ui/feature-gates/feature-gate-generic_associated_types_extended.stderr @@ -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`. diff --git a/src/test/ui/feature-gates/feature-gate-native_link_modifiers.rs b/src/test/ui/feature-gates/feature-gate-native_link_modifiers.rs deleted file mode 100644 index 2d00aa2a3cfcb..0000000000000 --- a/src/test/ui/feature-gates/feature-gate-native_link_modifiers.rs +++ /dev/null @@ -1,5 +0,0 @@ -#[link(name = "foo", modifiers = "")] -//~^ ERROR: native link modifiers are experimental -extern "C" {} - -fn main() {} diff --git a/src/test/ui/feature-gates/feature-gate-native_link_modifiers.stderr b/src/test/ui/feature-gates/feature-gate-native_link_modifiers.stderr deleted file mode 100644 index 20a2d6a26fa57..0000000000000 --- a/src/test/ui/feature-gates/feature-gate-native_link_modifiers.stderr +++ /dev/null @@ -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 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`. diff --git a/src/test/ui/feature-gates/feature-gate-native_link_modifiers_as_needed.rs b/src/test/ui/feature-gates/feature-gate-native_link_modifiers_as_needed.rs index 4cf8067592ec2..fedee8123980e 100644 --- a/src/test/ui/feature-gates/feature-gate-native_link_modifiers_as_needed.rs +++ b/src/test/ui/feature-gates/feature-gate-native_link_modifiers_as_needed.rs @@ -1,6 +1,3 @@ -#![allow(incomplete_features)] -#![feature(native_link_modifiers)] - #[link(name = "foo", modifiers = "+as-needed")] //~^ ERROR: `#[link(modifiers="as-needed")]` is unstable extern "C" {} diff --git a/src/test/ui/feature-gates/feature-gate-native_link_modifiers_as_needed.stderr b/src/test/ui/feature-gates/feature-gate-native_link_modifiers_as_needed.stderr index 08ce807851b38..96750aa6e808a 100644 --- a/src/test/ui/feature-gates/feature-gate-native_link_modifiers_as_needed.stderr +++ b/src/test/ui/feature-gates/feature-gate-native_link_modifiers_as_needed.stderr @@ -1,5 +1,5 @@ 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")] | ^^^^^^^^^^^^ diff --git a/src/test/ui/feature-gates/feature-gate-native_link_modifiers_bundle-2.rs b/src/test/ui/feature-gates/feature-gate-native_link_modifiers_bundle-2.rs index 1b5fa78ee5521..e229564950fcf 100644 --- a/src/test/ui/feature-gates/feature-gate-native_link_modifiers_bundle-2.rs +++ b/src/test/ui/feature-gates/feature-gate-native_link_modifiers_bundle-2.rs @@ -1,7 +1,6 @@ // Test native_link_modifiers_bundle don't need static-nobundle // check-pass -#![feature(native_link_modifiers)] #![feature(native_link_modifiers_bundle)] #[link(name = "foo", kind = "static", modifiers = "-bundle")] diff --git a/src/test/ui/feature-gates/feature-gate-native_link_modifiers_bundle-3.stderr b/src/test/ui/feature-gates/feature-gate-native_link_modifiers_bundle-3.stderr index 86ccb4e860b69..900605c3b375b 100644 --- a/src/test/ui/feature-gates/feature-gate-native_link_modifiers_bundle-3.stderr +++ b/src/test/ui/feature-gates/feature-gate-native_link_modifiers_bundle-3.stderr @@ -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 diff --git a/src/test/ui/feature-gates/feature-gate-native_link_modifiers_bundle.rs b/src/test/ui/feature-gates/feature-gate-native_link_modifiers_bundle.rs index b2b1dc28e47b9..c3c3cff17c403 100644 --- a/src/test/ui/feature-gates/feature-gate-native_link_modifiers_bundle.rs +++ b/src/test/ui/feature-gates/feature-gate-native_link_modifiers_bundle.rs @@ -1,6 +1,3 @@ -#![allow(incomplete_features)] -#![feature(native_link_modifiers)] - #[link(name = "foo", modifiers = "+bundle")] //~^ ERROR: `#[link(modifiers="bundle")]` is unstable extern "C" {} diff --git a/src/test/ui/feature-gates/feature-gate-native_link_modifiers_bundle.stderr b/src/test/ui/feature-gates/feature-gate-native_link_modifiers_bundle.stderr index b3e22b0644aa8..984b90d9b6c2e 100644 --- a/src/test/ui/feature-gates/feature-gate-native_link_modifiers_bundle.stderr +++ b/src/test/ui/feature-gates/feature-gate-native_link_modifiers_bundle.stderr @@ -1,5 +1,5 @@ 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")] | ^^^^^^^^^ diff --git a/src/test/ui/feature-gates/feature-gate-native_link_modifiers_verbatim.rs b/src/test/ui/feature-gates/feature-gate-native_link_modifiers_verbatim.rs index 042ce0b3f65b2..57527be1112cb 100644 --- a/src/test/ui/feature-gates/feature-gate-native_link_modifiers_verbatim.rs +++ b/src/test/ui/feature-gates/feature-gate-native_link_modifiers_verbatim.rs @@ -1,6 +1,3 @@ -#![allow(incomplete_features)] -#![feature(native_link_modifiers)] - #[link(name = "foo", modifiers = "+verbatim")] //~^ ERROR: `#[link(modifiers="verbatim")]` is unstable extern "C" {} diff --git a/src/test/ui/feature-gates/feature-gate-native_link_modifiers_verbatim.stderr b/src/test/ui/feature-gates/feature-gate-native_link_modifiers_verbatim.stderr index 8159416edfa3d..5c64c0d21bdb4 100644 --- a/src/test/ui/feature-gates/feature-gate-native_link_modifiers_verbatim.stderr +++ b/src/test/ui/feature-gates/feature-gate-native_link_modifiers_verbatim.stderr @@ -1,5 +1,5 @@ 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")] | ^^^^^^^^^^^ diff --git a/src/test/ui/feature-gates/feature-gate-native_link_modifiers_whole_archive.rs b/src/test/ui/feature-gates/feature-gate-native_link_modifiers_whole_archive.rs deleted file mode 100644 index ca801e5911432..0000000000000 --- a/src/test/ui/feature-gates/feature-gate-native_link_modifiers_whole_archive.rs +++ /dev/null @@ -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() {} diff --git a/src/test/ui/feature-gates/feature-gate-native_link_modifiers_whole_archive.stderr b/src/test/ui/feature-gates/feature-gate-native_link_modifiers_whole_archive.stderr deleted file mode 100644 index cacaa789ecb79..0000000000000 --- a/src/test/ui/feature-gates/feature-gate-native_link_modifiers_whole_archive.stderr +++ /dev/null @@ -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 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`. diff --git a/src/test/ui/generic-associated-types/extended/lending_iterator.base.nll.stderr b/src/test/ui/generic-associated-types/extended/lending_iterator.base.nll.stderr new file mode 100644 index 0000000000000..3da7794b3d2c0 --- /dev/null +++ b/src/test/ui/generic-associated-types/extended/lending_iterator.base.nll.stderr @@ -0,0 +1,12 @@ +error[E0276]: impl has stricter requirements than trait + --> $DIR/lending_iterator.rs:14:45 + | +LL | fn from_iter LendingIterator = A>>(iter: T) -> Self; + | ------------------------------------------------------------------------ definition of `from_iter` from trait +... +LL | fn from_iter LendingIterator = 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`. diff --git a/src/test/ui/generic-associated-types/extended/lending_iterator.base.stderr b/src/test/ui/generic-associated-types/extended/lending_iterator.base.stderr new file mode 100644 index 0000000000000..c5588b0912ba8 --- /dev/null +++ b/src/test/ui/generic-associated-types/extended/lending_iterator.base.stderr @@ -0,0 +1,26 @@ +error[E0276]: impl has stricter requirements than trait + --> $DIR/lending_iterator.rs:14:45 + | +LL | fn from_iter LendingIterator = A>>(iter: T) -> Self; + | ------------------------------------------------------------------------ definition of `from_iter` from trait +... +LL | fn from_iter LendingIterator = 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 | >::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 LendingIterator = A>>(iter: T) -> Self; + | ^^^^^^^^^^^^ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0276`. diff --git a/src/test/ui/generic-associated-types/extended/lending_iterator.rs b/src/test/ui/generic-associated-types/extended/lending_iterator.rs new file mode 100644 index 0000000000000..df11ab2124986 --- /dev/null +++ b/src/test/ui/generic-associated-types/extended/lending_iterator.rs @@ -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: Sized { + fn from_iter LendingIterator = A>>(iter: T) -> Self; +} + +impl FromLendingIterator for Vec { + fn from_iter LendingIterator = 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>; + + fn collect>(self) -> B + where + Self: Sized, + Self: for<'q> LendingIterator = A>, + { + >::from_iter(self) + //[base]~^ the parameter type + } +} + +fn main() {} diff --git a/src/test/ui/generic-associated-types/extended/lending_iterator_2.base.stderr b/src/test/ui/generic-associated-types/extended/lending_iterator_2.base.stderr new file mode 100644 index 0000000000000..6c2a624ca11d5 --- /dev/null +++ b/src/test/ui/generic-associated-types/extended/lending_iterator_2.base.stderr @@ -0,0 +1,12 @@ +error[E0276]: impl has stricter requirements than trait + --> $DIR/lending_iterator_2.rs:14:45 + | +LL | fn from_iter LendingIterator = A>>(iter: T) -> Self; + | ------------------------------------------------------------------------ definition of `from_iter` from trait +... +LL | fn from_iter LendingIterator = 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`. diff --git a/src/test/ui/generic-associated-types/extended/lending_iterator_2.rs b/src/test/ui/generic-associated-types/extended/lending_iterator_2.rs new file mode 100644 index 0000000000000..3c4a2184db90c --- /dev/null +++ b/src/test/ui/generic-associated-types/extended/lending_iterator_2.rs @@ -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: Sized { + fn from_iter LendingIterator = A>>(iter: T) -> Self; +} + +impl FromLendingIterator for Vec { + fn from_iter LendingIterator = 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>; +} + +fn main() {} diff --git a/src/test/ui/native-library-link-flags/mix-bundle-and-whole-archive-link-attr.rs b/src/test/ui/native-library-link-flags/mix-bundle-and-whole-archive-link-attr.rs index c3714a3845180..b153ef94626a3 100644 --- a/src/test/ui/native-library-link-flags/mix-bundle-and-whole-archive-link-attr.rs +++ b/src/test/ui/native-library-link-flags/mix-bundle-and-whole-archive-link-attr.rs @@ -2,9 +2,7 @@ // build-fail // 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_whole_archive)] #[link(name = "mylib", kind = "static", modifiers = "+bundle,+whole-archive")] extern "C" { } diff --git a/src/test/ui/native-library-link-flags/modifiers-override-2.rs b/src/test/ui/native-library-link-flags/modifiers-override-2.rs new file mode 100644 index 0000000000000..333f6786b0fba --- /dev/null +++ b/src/test/ui/native-library-link-flags/modifiers-override-2.rs @@ -0,0 +1,3 @@ +// compile-flags:-lstatic:+whole-archive,-whole-archive=foo + +fn main() {} diff --git a/src/test/ui/native-library-link-flags/modifiers-override-2.stderr b/src/test/ui/native-library-link-flags/modifiers-override-2.stderr new file mode 100644 index 0000000000000..9200d7bfb0ce3 --- /dev/null +++ b/src/test/ui/native-library-link-flags/modifiers-override-2.stderr @@ -0,0 +1,2 @@ +error: duplicating linking modifier is currently unstable and only accepted on the nightly compiler + diff --git a/src/test/ui/native-library-link-flags/modifiers-override.rs b/src/test/ui/native-library-link-flags/modifiers-override.rs new file mode 100644 index 0000000000000..f6d770559e6e0 --- /dev/null +++ b/src/test/ui/native-library-link-flags/modifiers-override.rs @@ -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() {} diff --git a/src/test/ui/native-library-link-flags/modifiers-override.stderr b/src/test/ui/native-library-link-flags/modifiers-override.stderr new file mode 100644 index 0000000000000..8644d2382d2ba --- /dev/null +++ b/src/test/ui/native-library-link-flags/modifiers-override.stderr @@ -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 + diff --git a/src/tools/clippy/clippy_lints/src/regex.rs b/src/tools/clippy/clippy_lints/src/regex.rs index b6d04334de9e5..a92097e1d24ca 100644 --- a/src/tools/clippy/clippy_lints/src/regex.rs +++ b/src/tools/clippy/clippy_lints/src/regex.rs @@ -81,7 +81,7 @@ impl<'tcx> LateLintPass<'tcx> for Regex { #[allow(clippy::cast_possible_truncation)] // truncation very unlikely here #[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 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);