From 6d455296fde6ff0d5154d39513259a60eb73f302 Mon Sep 17 00:00:00 2001 From: yukang Date: Tue, 25 Oct 2022 20:47:19 +0800 Subject: [PATCH 01/12] Fix #103451, find_width_of_character_at_span return width with 1 when reaching end --- compiler/rustc_span/src/source_map.rs | 8 ++---- compiler/rustc_span/src/source_map/tests.rs | 11 +++---- src/test/ui/parser/issue-103451.rs | 5 ++++ src/test/ui/parser/issue-103451.stderr | 32 +++++++++++++++++++++ 4 files changed, 46 insertions(+), 10 deletions(-) create mode 100644 src/test/ui/parser/issue-103451.rs create mode 100644 src/test/ui/parser/issue-103451.stderr diff --git a/compiler/rustc_span/src/source_map.rs b/compiler/rustc_span/src/source_map.rs index f9566eeee9465..3baa2e03cbad7 100644 --- a/compiler/rustc_span/src/source_map.rs +++ b/compiler/rustc_span/src/source_map.rs @@ -855,7 +855,8 @@ impl SourceMap { /// Returns a new span representing the next character after the end-point of this span. /// Special cases: /// - if span is a dummy one, returns the same span - /// - if next_point reached the end of source, return span with lo = hi + /// - if next_point reached the end of source, return a span exceeding the end of source, + /// which means sm.span_to_snippet(next_point) will get `Err` /// - respect multi-byte characters pub fn next_point(&self, sp: Span) -> Span { if sp.is_dummy() { @@ -864,9 +865,6 @@ impl SourceMap { let start_of_next_point = sp.hi().0; let width = self.find_width_of_character_at_span(sp, true); - if width == 0 { - return Span::new(sp.hi(), sp.hi(), sp.ctxt(), None); - } // If the width is 1, then the next span should only contain the next char besides current ending. // However, in the case of a multibyte character, where the width != 1, the next span should // span multiple bytes to include the whole character. @@ -938,7 +936,7 @@ impl SourceMap { // Ensure indexes are also not malformed. if start_index > end_index || end_index > source_len - 1 { debug!("find_width_of_character_at_span: source indexes are malformed"); - return 0; + return 1; } let src = local_begin.sf.external_src.borrow(); diff --git a/compiler/rustc_span/src/source_map/tests.rs b/compiler/rustc_span/src/source_map/tests.rs index 1fd81018fa05c..3cab59e8dbe6c 100644 --- a/compiler/rustc_span/src/source_map/tests.rs +++ b/compiler/rustc_span/src/source_map/tests.rs @@ -511,16 +511,17 @@ fn test_next_point() { assert_eq!(span.lo().0, 4); assert_eq!(span.hi().0, 5); - // A non-empty span at the last byte should advance to create an empty - // span pointing at the end of the file. + // Reaching to the end of file, return a span that will get error with `span_to_snippet` let span = Span::with_root_ctxt(BytePos(4), BytePos(5)); let span = sm.next_point(span); assert_eq!(span.lo().0, 5); - assert_eq!(span.hi().0, 5); + assert_eq!(span.hi().0, 6); + assert!(sm.span_to_snippet(span).is_err()); - // Empty span pointing just past the last byte. + // Reaching to the end of file, return a span that will get error with `span_to_snippet` let span = Span::with_root_ctxt(BytePos(5), BytePos(5)); let span = sm.next_point(span); assert_eq!(span.lo().0, 5); - assert_eq!(span.hi().0, 5); + assert_eq!(span.hi().0, 6); + assert!(sm.span_to_snippet(span).is_err()); } diff --git a/src/test/ui/parser/issue-103451.rs b/src/test/ui/parser/issue-103451.rs new file mode 100644 index 0000000000000..1fdb001488155 --- /dev/null +++ b/src/test/ui/parser/issue-103451.rs @@ -0,0 +1,5 @@ +// error-pattern: this file contains an unclosed delimiter +// error-pattern: expected value, found struct `R` +struct R { } +struct S { + x: [u8; R diff --git a/src/test/ui/parser/issue-103451.stderr b/src/test/ui/parser/issue-103451.stderr new file mode 100644 index 0000000000000..eb3c92fb43d9b --- /dev/null +++ b/src/test/ui/parser/issue-103451.stderr @@ -0,0 +1,32 @@ +error: this file contains an unclosed delimiter + --> $DIR/issue-103451.rs:5:15 + | +LL | struct S { + | - unclosed delimiter +LL | x: [u8; R + | - ^ + | | + | unclosed delimiter + +error: this file contains an unclosed delimiter + --> $DIR/issue-103451.rs:5:15 + | +LL | struct S { + | - unclosed delimiter +LL | x: [u8; R + | - ^ + | | + | unclosed delimiter + +error[E0423]: expected value, found struct `R` + --> $DIR/issue-103451.rs:5:13 + | +LL | struct R { } + | ------------ `R` defined here +LL | struct S { +LL | x: [u8; R + | ^ help: use struct literal syntax instead: `R {}` + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0423`. From a2037e3012ed6c59e91fadb693b35fd503cba117 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Tue, 1 Nov 2022 01:34:59 +0000 Subject: [PATCH 02/12] Check for substs compatibility for RPITITs --- .../src/traits/project.rs | 18 +++++++++++++++--- .../impl-trait/in-trait/generics-mismatch.rs | 17 +++++++++++++++++ .../in-trait/generics-mismatch.stderr | 12 ++++++++++++ 3 files changed, 44 insertions(+), 3 deletions(-) create mode 100644 src/test/ui/impl-trait/in-trait/generics-mismatch.rs create mode 100644 src/test/ui/impl-trait/in-trait/generics-mismatch.stderr diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs index c8276854016f0..ad216e5502d82 100644 --- a/compiler/rustc_trait_selection/src/traits/project.rs +++ b/compiler/rustc_trait_selection/src/traits/project.rs @@ -2192,7 +2192,7 @@ fn confirm_impl_candidate<'cx, 'tcx>( // Verify that the trait item and its implementation have compatible substs lists fn check_substs_compatible<'tcx>( tcx: TyCtxt<'tcx>, - assoc_ty: &ty::AssocItem, + assoc_item: &ty::AssocItem, substs: ty::SubstsRef<'tcx>, ) -> bool { fn check_substs_compatible_inner<'tcx>( @@ -2224,7 +2224,10 @@ fn check_substs_compatible<'tcx>( true } - check_substs_compatible_inner(tcx, tcx.generics_of(assoc_ty.def_id), substs.as_slice()) + let generics = tcx.generics_of(assoc_item.def_id); + // Chop off any additional substs (RPITIT) substs + let substs = &substs[0..generics.count().min(substs.len())]; + check_substs_compatible_inner(tcx, generics, substs) } fn confirm_impl_trait_in_trait_candidate<'tcx>( @@ -2253,12 +2256,21 @@ fn confirm_impl_trait_in_trait_candidate<'tcx>( }; } - let impl_fn_def_id = leaf_def.item.def_id; // Rebase from {trait}::{fn}::{opaque} to {impl}::{fn}::{opaque}, // since `data.substs` are the impl substs. let impl_fn_substs = obligation.predicate.substs.rebase_onto(tcx, tcx.parent(trait_fn_def_id), data.substs); + if !check_substs_compatible(tcx, &leaf_def.item, impl_fn_substs) { + let err = tcx.ty_error_with_message( + obligation.cause.span, + "impl method and trait method have different parameters", + ); + return Progress { term: err.into(), obligations }; + } + + let impl_fn_def_id = leaf_def.item.def_id; + let cause = ObligationCause::new( obligation.cause.span, obligation.cause.body_id, diff --git a/src/test/ui/impl-trait/in-trait/generics-mismatch.rs b/src/test/ui/impl-trait/in-trait/generics-mismatch.rs new file mode 100644 index 0000000000000..cc0fc720ebbfd --- /dev/null +++ b/src/test/ui/impl-trait/in-trait/generics-mismatch.rs @@ -0,0 +1,17 @@ +#![feature(return_position_impl_trait_in_trait)] +#![allow(incomplete_features)] + +struct U; + +trait Foo { + fn bar(&self) -> impl Sized; +} + +impl Foo for U { + fn bar(&self) {} + //~^ ERROR method `bar` has 1 type parameter but its trait declaration has 0 type parameters +} + +fn main() { + U.bar(); +} diff --git a/src/test/ui/impl-trait/in-trait/generics-mismatch.stderr b/src/test/ui/impl-trait/in-trait/generics-mismatch.stderr new file mode 100644 index 0000000000000..cd42683e0224d --- /dev/null +++ b/src/test/ui/impl-trait/in-trait/generics-mismatch.stderr @@ -0,0 +1,12 @@ +error[E0049]: method `bar` has 1 type parameter but its trait declaration has 0 type parameters + --> $DIR/generics-mismatch.rs:11:12 + | +LL | fn bar(&self) -> impl Sized; + | - expected 0 type parameters +... +LL | fn bar(&self) {} + | ^ found 1 type parameter + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0049`. From 32dae918a181e01b8ee01d256c1e54ddd6d0ea76 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Tue, 1 Nov 2022 01:36:50 +0000 Subject: [PATCH 03/12] Remap RPITIT substs properly --- .../src/traits/project.rs | 7 ++++++ .../in-trait/specialization-substs-remap.rs | 24 +++++++++++++++++++ 2 files changed, 31 insertions(+) create mode 100644 src/test/ui/impl-trait/in-trait/specialization-substs-remap.rs diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs index ad216e5502d82..474ae22e3d589 100644 --- a/compiler/rustc_trait_selection/src/traits/project.rs +++ b/compiler/rustc_trait_selection/src/traits/project.rs @@ -2260,6 +2260,13 @@ fn confirm_impl_trait_in_trait_candidate<'tcx>( // since `data.substs` are the impl substs. let impl_fn_substs = obligation.predicate.substs.rebase_onto(tcx, tcx.parent(trait_fn_def_id), data.substs); + let impl_fn_substs = translate_substs( + selcx.infcx(), + obligation.param_env, + data.impl_def_id, + impl_fn_substs, + leaf_def.defining_node, + ); if !check_substs_compatible(tcx, &leaf_def.item, impl_fn_substs) { let err = tcx.ty_error_with_message( diff --git a/src/test/ui/impl-trait/in-trait/specialization-substs-remap.rs b/src/test/ui/impl-trait/in-trait/specialization-substs-remap.rs new file mode 100644 index 0000000000000..c9ee877db8ec5 --- /dev/null +++ b/src/test/ui/impl-trait/in-trait/specialization-substs-remap.rs @@ -0,0 +1,24 @@ +// check-pass + +#![feature(specialization)] +#![feature(return_position_impl_trait_in_trait)] +#![allow(incomplete_features)] + +trait Foo { + fn bar(&self) -> impl Sized; +} + +impl Foo for U +where + U: Copy, +{ + fn bar(&self) -> U { + *self + } +} + +impl Foo for i32 {} + +fn main() { + let _: i32 = 1i32.bar(); +} From 0f632c8f7882a4470bf1c7b6a4d6b14379b8e163 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Tue, 1 Nov 2022 01:42:47 +0000 Subject: [PATCH 04/12] Fix ICE in default impl error reporting --- compiler/rustc_middle/src/ty/error.rs | 4 ++- .../in-trait/specialization-broken.rs | 26 +++++++++++++++++++ .../in-trait/specialization-broken.stderr | 23 ++++++++++++++++ 3 files changed, 52 insertions(+), 1 deletion(-) create mode 100644 src/test/ui/impl-trait/in-trait/specialization-broken.rs create mode 100644 src/test/ui/impl-trait/in-trait/specialization-broken.stderr diff --git a/compiler/rustc_middle/src/ty/error.rs b/compiler/rustc_middle/src/ty/error.rs index 4e6cdb786025e..dc13374f992eb 100644 --- a/compiler/rustc_middle/src/ty/error.rs +++ b/compiler/rustc_middle/src/ty/error.rs @@ -430,7 +430,9 @@ impl<'tcx> TyCtxt<'tcx> { (ty::Projection(_), ty::Projection(_)) => { diag.note("an associated type was expected, but a different one was found"); } - (ty::Param(p), ty::Projection(proj)) | (ty::Projection(proj), ty::Param(p)) => { + (ty::Param(p), ty::Projection(proj)) | (ty::Projection(proj), ty::Param(p)) + if self.def_kind(proj.item_def_id) != DefKind::ImplTraitPlaceholder => + { let generics = self.generics_of(body_owner_def_id); let p_span = self.def_span(generics.type_param(p, self).def_id); if !sp.contains(p_span) { diff --git a/src/test/ui/impl-trait/in-trait/specialization-broken.rs b/src/test/ui/impl-trait/in-trait/specialization-broken.rs new file mode 100644 index 0000000000000..9d27d3710a601 --- /dev/null +++ b/src/test/ui/impl-trait/in-trait/specialization-broken.rs @@ -0,0 +1,26 @@ +// FIXME(compiler-errors): I'm not exactly sure if this is expected to pass or not. +// But we fixed an ICE anyways. + +#![feature(specialization)] +#![feature(return_position_impl_trait_in_trait)] +#![allow(incomplete_features)] + +trait Foo { + fn bar(&self) -> impl Sized; +} + +default impl Foo for U +where + U: Copy, +{ + fn bar(&self) -> U { + //~^ ERROR method `bar` has an incompatible type for trait + *self + } +} + +impl Foo for i32 {} + +fn main() { + 1i32.bar(); +} diff --git a/src/test/ui/impl-trait/in-trait/specialization-broken.stderr b/src/test/ui/impl-trait/in-trait/specialization-broken.stderr new file mode 100644 index 0000000000000..a30e6346b2927 --- /dev/null +++ b/src/test/ui/impl-trait/in-trait/specialization-broken.stderr @@ -0,0 +1,23 @@ +error[E0053]: method `bar` has an incompatible type for trait + --> $DIR/specialization-broken.rs:16:22 + | +LL | default impl Foo for U + | - this type parameter +... +LL | fn bar(&self) -> U { + | ^ + | | + | expected associated type, found type parameter `U` + | help: change the output type to match the trait: `impl Sized` + | +note: type in trait + --> $DIR/specialization-broken.rs:9:22 + | +LL | fn bar(&self) -> impl Sized; + | ^^^^^^^^^^ + = note: expected fn pointer `fn(&U) -> impl Sized` + found fn pointer `fn(&U) -> U` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0053`. From 66847ff56b933609618b0899cb3bfdd74f9817d5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=AFc=20BRANSTETT?= Date: Mon, 21 Feb 2022 01:45:03 +0100 Subject: [PATCH 05/12] Test that target feature mix up with homogeneous floats is sound This is basically is ripoff of src/test/ui/simd/target-feature-mixup.rs but for floats and without #[repr(simd)] --- .../homogenous-floats-target-feature-mixup.rs | 192 ++++++++++++++++++ 1 file changed, 192 insertions(+) create mode 100644 src/test/ui/abi/homogenous-floats-target-feature-mixup.rs diff --git a/src/test/ui/abi/homogenous-floats-target-feature-mixup.rs b/src/test/ui/abi/homogenous-floats-target-feature-mixup.rs new file mode 100644 index 0000000000000..d7f5e19219ed6 --- /dev/null +++ b/src/test/ui/abi/homogenous-floats-target-feature-mixup.rs @@ -0,0 +1,192 @@ +// This test check that even if we mixup target feature of function with homogenous floats, +// the abi is sound and still produce the right answer. +// +// This is basically the same test as src/test/ui/simd/target-feature-mixup.rs but for floats and +// without #[repr(simd)] + +// run-pass +// ignore-emscripten +// ignore-sgx no processes + +#![feature(avx512_target_feature)] + +#![allow(overflowing_literals)] +#![allow(unused_variables)] + +use std::process::{Command, ExitStatus}; +use std::env; + +fn main() { + if let Some(level) = env::args().nth(1) { + return test::main(&level) + } + + match std::env::var("TARGET") { + Ok(s) => { + // Skip this tests on i586-unknown-linux-gnu where sse2 is disabled + if s.contains("i586") { + return + } + } + Err(_) => return, + } + + let me = env::current_exe().unwrap(); + for level in ["sse", "avx", "avx512"].iter() { + let status = Command::new(&me).arg(level).status().unwrap(); + if status.success() { + println!("success with {}", level); + continue + } + + // We don't actually know if our computer has the requisite target features + // for the test below. Testing for that will get added to libstd later so + // for now just assume sigill means this is a machine that can't run this test. + if is_sigill(status) { + println!("sigill with {}, assuming spurious", level); + continue + } + panic!("invalid status at {}: {}", level, status); + } +} + +#[cfg(unix)] +fn is_sigill(status: ExitStatus) -> bool { + use std::os::unix::prelude::*; + status.signal() == Some(4) +} + +#[cfg(windows)] +fn is_sigill(status: ExitStatus) -> bool { + status.code() == Some(0xc000001d) +} + +#[cfg(any(target_arch = "x86", target_arch = "x86_64"))] +#[allow(nonstandard_style)] +mod test { + #[derive(PartialEq, Debug, Clone, Copy)] + struct f32x2(f32, f32); + + #[derive(PartialEq, Debug, Clone, Copy)] + struct f32x4(f32, f32, f32, f32); + + #[derive(PartialEq, Debug, Clone, Copy)] + struct f32x8(f32, f32, f32, f32, f32, f32, f32, f32); + + pub fn main(level: &str) { + unsafe { + main_normal(level); + main_sse(level); + if level == "sse" { + return + } + main_avx(level); + if level == "avx" { + return + } + main_avx512(level); + } + } + + macro_rules! mains { + ($( + $(#[$attr:meta])* + unsafe fn $main:ident(level: &str) { + ... + } + )*) => ($( + $(#[$attr])* + unsafe fn $main(level: &str) { + let m128 = f32x2(1., 2.); + let m256 = f32x4(3., 4., 5., 6.); + let m512 = f32x8(7., 8., 9., 10., 11., 12., 13., 14.); + assert_eq!(id_sse_128(m128), m128); + assert_eq!(id_sse_256(m256), m256); + assert_eq!(id_sse_512(m512), m512); + + if level == "sse" { + return + } + assert_eq!(id_avx_128(m128), m128); + assert_eq!(id_avx_256(m256), m256); + assert_eq!(id_avx_512(m512), m512); + + if level == "avx" { + return + } + assert_eq!(id_avx512_128(m128), m128); + assert_eq!(id_avx512_256(m256), m256); + assert_eq!(id_avx512_512(m512), m512); + } + )*) + } + + mains! { + unsafe fn main_normal(level: &str) { ... } + #[target_feature(enable = "sse2")] + unsafe fn main_sse(level: &str) { ... } + #[target_feature(enable = "avx")] + unsafe fn main_avx(level: &str) { ... } + #[target_feature(enable = "avx512bw")] + unsafe fn main_avx512(level: &str) { ... } + } + + #[target_feature(enable = "sse2")] + unsafe fn id_sse_128(a: f32x2) -> f32x2 { + assert_eq!(a, f32x2(1., 2.)); + a.clone() + } + + #[target_feature(enable = "sse2")] + unsafe fn id_sse_256(a: f32x4) -> f32x4 { + assert_eq!(a, f32x4(3., 4., 5., 6.)); + a.clone() + } + + #[target_feature(enable = "sse2")] + unsafe fn id_sse_512(a: f32x8) -> f32x8 { + assert_eq!(a, f32x8(7., 8., 9., 10., 11., 12., 13., 14.)); + a.clone() + } + + #[target_feature(enable = "avx")] + unsafe fn id_avx_128(a: f32x2) -> f32x2 { + assert_eq!(a, f32x2(1., 2.)); + a.clone() + } + + #[target_feature(enable = "avx")] + unsafe fn id_avx_256(a: f32x4) -> f32x4 { + assert_eq!(a, f32x4(3., 4., 5., 6.)); + a.clone() + } + + #[target_feature(enable = "avx")] + unsafe fn id_avx_512(a: f32x8) -> f32x8 { + assert_eq!(a, f32x8(7., 8., 9., 10., 11., 12., 13., 14.)); + a.clone() + } + + #[target_feature(enable = "avx512bw")] + unsafe fn id_avx512_128(a: f32x2) -> f32x2 { + assert_eq!(a, f32x2(1., 2.)); + a.clone() + } + + #[target_feature(enable = "avx512bw")] + unsafe fn id_avx512_256(a: f32x4) -> f32x4 { + assert_eq!(a, f32x4(3., 4., 5., 6.)); + a.clone() + } + + #[target_feature(enable = "avx512bw")] + unsafe fn id_avx512_512(a: f32x8) -> f32x8 { + assert_eq!(a, f32x8(7., 8., 9., 10., 11., 12., 13., 14.)); + a.clone() + } +} + +#[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))] +mod test { + pub fn main(level: &str) {} +} From cf6efe8137d88237b7e280a22eaea2f2193da47d Mon Sep 17 00:00:00 2001 From: Wesley Wiser Date: Tue, 25 Oct 2022 16:57:21 -0400 Subject: [PATCH 06/12] Add test case --- .../codegen/auxiliary/static_dllimport_aux.rs | 13 +++++++++++++ .../issue-81408-dllimport-thinlto-windows.rs | 15 +++++++++++++++ 2 files changed, 28 insertions(+) create mode 100644 src/test/codegen/auxiliary/static_dllimport_aux.rs create mode 100644 src/test/codegen/issue-81408-dllimport-thinlto-windows.rs diff --git a/src/test/codegen/auxiliary/static_dllimport_aux.rs b/src/test/codegen/auxiliary/static_dllimport_aux.rs new file mode 100644 index 0000000000000..afb0dc42f443a --- /dev/null +++ b/src/test/codegen/auxiliary/static_dllimport_aux.rs @@ -0,0 +1,13 @@ +use std::sync::atomic::{AtomicPtr, Ordering}; + +#[inline(always)] +pub fn memrchr() { + fn detect() {} + + static CROSS_CRATE_STATIC_ITEM: AtomicPtr<()> = AtomicPtr::new(detect as *mut ()); + + unsafe { + let fun = CROSS_CRATE_STATIC_ITEM.load(Ordering::SeqCst); + std::mem::transmute::<*mut (), fn()>(fun)() + } +} diff --git a/src/test/codegen/issue-81408-dllimport-thinlto-windows.rs b/src/test/codegen/issue-81408-dllimport-thinlto-windows.rs new file mode 100644 index 0000000000000..e674c0561d3b8 --- /dev/null +++ b/src/test/codegen/issue-81408-dllimport-thinlto-windows.rs @@ -0,0 +1,15 @@ +// compile-flags: -O -C lto=thin -C prefer-dynamic=no +// only-windows +// aux-build:static_dllimport_aux.rs + +// Test that on Windows, when performing ThinLTO, we do not mark cross-crate static items with +// dllimport because lld does not fix the symbol names for us. + +extern crate static_dllimport_aux; + +// CHECK-LABEL: @{{.+}}CROSS_CRATE_STATIC_ITEM{{.+}} = +// CHECK-SAME: external dllimport local_unnamed_addr global %"{{.+}}::AtomicPtr + +pub fn main() { + static_dllimport_aux::memrchr(); +} From 296489c89268e56abb8f6050842d006b16ed4f09 Mon Sep 17 00:00:00 2001 From: Wesley Wiser Date: Thu, 20 Oct 2022 17:45:09 -0400 Subject: [PATCH 07/12] Fix Access Violation when using lld & ThinLTO on windows-msvc Users report an AV at runtime of the compiled binary when using lld and ThinLTO on windows-msvc. The AV occurs when accessing a static value which is defined in one crate but used in another. Based on the disassembly of the cross-crate use, it appears that the use is not correctly linked with the definition and is instead assigned a garbage pointer value. If we look at the symbol tables for each crates' obj file, we can see what is happening: *lib.obj*: ``` COFF SYMBOL TABLE ... 00E 00000000 SECT2 notype External | _ZN10reproducer7memrchr2FN17h612b61ca0e168901E ... ``` *bin.obj*: ``` COFF SYMBOL TABLE ... 010 00000000 UNDEF notype External | __imp__ZN10reproducer7memrchr2FN17h612b61ca0e168901E ... ``` The use of the symbol has the "import" style symbol name but the declaration doesn't generate any symbol with the same name. As a result, linking the files generates a warning from lld: > rust-lld: warning: bin.obj: locally defined symbol imported: reproducer::memrchr::FN::h612b61ca0e168901 (defined in lib.obj) [LNK4217] and the symbol reference remains undefined at runtime leading to the AV. To fix this, we just need to detect that we are performing ThinLTO (and thus, static linking) and omit the `dllimport` attribute on the extern item in LLVM IR. --- compiler/rustc_codegen_llvm/src/consts.rs | 4 +++- src/test/codegen/issue-81408-dllimport-thinlto-windows.rs | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/consts.rs b/compiler/rustc_codegen_llvm/src/consts.rs index dd3c43ba5ca7c..bf5ac4e503e3f 100644 --- a/compiler/rustc_codegen_llvm/src/consts.rs +++ b/compiler/rustc_codegen_llvm/src/consts.rs @@ -19,6 +19,7 @@ use rustc_middle::mir::mono::MonoItem; use rustc_middle::ty::layout::LayoutOf; use rustc_middle::ty::{self, Instance, Ty}; use rustc_middle::{bug, span_bug}; +use rustc_session::config::Lto; use rustc_target::abi::{ AddressSpace, Align, HasDataLayout, Primitive, Scalar, Size, WrappingRange, }; @@ -303,7 +304,8 @@ impl<'ll> CodegenCx<'ll, '_> { // ThinLTO can't handle this workaround in all cases, so we don't // emit the attrs. Instead we make them unnecessary by disallowing // dynamic linking when linker plugin based LTO is enabled. - !self.tcx.sess.opts.cg.linker_plugin_lto.enabled(); + !self.tcx.sess.opts.cg.linker_plugin_lto.enabled() && + self.tcx.sess.lto() != Lto::Thin; // If this assertion triggers, there's something wrong with commandline // argument validation. diff --git a/src/test/codegen/issue-81408-dllimport-thinlto-windows.rs b/src/test/codegen/issue-81408-dllimport-thinlto-windows.rs index e674c0561d3b8..0b6ab4f7ecb3b 100644 --- a/src/test/codegen/issue-81408-dllimport-thinlto-windows.rs +++ b/src/test/codegen/issue-81408-dllimport-thinlto-windows.rs @@ -8,7 +8,7 @@ extern crate static_dllimport_aux; // CHECK-LABEL: @{{.+}}CROSS_CRATE_STATIC_ITEM{{.+}} = -// CHECK-SAME: external dllimport local_unnamed_addr global %"{{.+}}::AtomicPtr +// CHECK-SAME: external local_unnamed_addr global %"{{.+}}AtomicPtr pub fn main() { static_dllimport_aux::memrchr(); From d5899efbdab28d6f5ecd95c68d03dfd1bdbfba1c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Miku=C5=82a?= Date: Sat, 5 Nov 2022 12:19:55 +0100 Subject: [PATCH 08/12] Update several crates for improved support of the new targets This helps with `*-windows-gnullvm` targets --- Cargo.lock | 64 +++++++++++-------- compiler/rustc_data_structures/Cargo.toml | 2 +- src/bootstrap/Cargo.lock | 75 ++++++++++++++++++++--- src/bootstrap/Cargo.toml | 2 +- 4 files changed, 107 insertions(+), 36 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index f230f50212a3b..9b452e051f99b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2522,7 +2522,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" dependencies = [ "lock_api", - "parking_lot_core 0.9.3", + "parking_lot_core 0.9.4", ] [[package]] @@ -2541,15 +2541,15 @@ dependencies = [ [[package]] name = "parking_lot_core" -version = "0.9.3" +version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09a279cbf25cb0757810394fbc1e359949b59e348145c643a939a525692e6929" +checksum = "4dc9e0dc2adc1c69d09143aff38d3d30c5c3f0df0dad82e6d25547af174ebec0" dependencies = [ "cfg-if 1.0.0", "libc", "redox_syscall", "smallvec", - "windows-sys 0.36.1", + "windows-sys 0.42.0", ] [[package]] @@ -2774,9 +2774,9 @@ dependencies = [ [[package]] name = "psm" -version = "0.1.16" +version = "0.1.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd136ff4382c4753fc061cb9e4712ab2af263376b95bbd5bd8cd50c020b78e69" +checksum = "5787f7cda34e3033a72192c018bc5883100330f362ef279a8cbccfce8bb4e874" dependencies = [ "cc", ] @@ -4677,9 +4677,9 @@ checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" [[package]] name = "stacker" -version = "0.1.14" +version = "0.1.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90939d5171a4420b3ff5fbc8954d641e7377335454c259dcb80786f3f21dc9b4" +checksum = "c886bd4480155fd3ef527d45e9ac8dd7118a898a46530b7b94c3e21866259fce" dependencies = [ "cc", "cfg-if 1.0.0", @@ -5499,17 +5499,25 @@ dependencies = [ [[package]] name = "windows-sys" -version = "0.36.1" +version = "0.42.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea04155a16a59f9eab786fe12a4a450e75cdb175f9e0d80da1e17db09f55b8d2" +checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7" dependencies = [ - "windows_aarch64_msvc 0.36.1", - "windows_i686_gnu 0.36.1", - "windows_i686_msvc 0.36.1", - "windows_x86_64_gnu 0.36.1", - "windows_x86_64_msvc 0.36.1", + "windows_aarch64_gnullvm", + "windows_aarch64_msvc 0.42.0", + "windows_i686_gnu 0.42.0", + "windows_i686_msvc 0.42.0", + "windows_x86_64_gnu 0.42.0", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc 0.42.0", ] +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41d2aa71f6f0cbe00ae5167d90ef3cfe66527d6f613ca78ac8024c3ccab9a19e" + [[package]] name = "windows_aarch64_msvc" version = "0.28.0" @@ -5518,9 +5526,9 @@ checksum = "52695a41e536859d5308cc613b4a022261a274390b25bd29dfff4bf08505f3c2" [[package]] name = "windows_aarch64_msvc" -version = "0.36.1" +version = "0.42.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9bb8c3fd39ade2d67e9874ac4f3db21f0d710bee00fe7cab16949ec184eeaa47" +checksum = "dd0f252f5a35cac83d6311b2e795981f5ee6e67eb1f9a7f64eb4500fbc4dcdb4" [[package]] name = "windows_i686_gnu" @@ -5530,9 +5538,9 @@ checksum = "f54725ac23affef038fecb177de6c9bf065787c2f432f79e3c373da92f3e1d8a" [[package]] name = "windows_i686_gnu" -version = "0.36.1" +version = "0.42.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "180e6ccf01daf4c426b846dfc66db1fc518f074baa793aa7d9b9aaeffad6a3b6" +checksum = "fbeae19f6716841636c28d695375df17562ca208b2b7d0dc47635a50ae6c5de7" [[package]] name = "windows_i686_msvc" @@ -5542,9 +5550,9 @@ checksum = "51d5158a43cc43623c0729d1ad6647e62fa384a3d135fd15108d37c683461f64" [[package]] name = "windows_i686_msvc" -version = "0.36.1" +version = "0.42.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2e7917148b2812d1eeafaeb22a97e4813dfa60a3f8f78ebe204bcc88f12f024" +checksum = "84c12f65daa39dd2babe6e442988fc329d6243fdce47d7d2d155b8d874862246" [[package]] name = "windows_x86_64_gnu" @@ -5554,9 +5562,15 @@ checksum = "bc31f409f565611535130cfe7ee8e6655d3fa99c1c61013981e491921b5ce954" [[package]] name = "windows_x86_64_gnu" -version = "0.36.1" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf7b1b21b5362cbc318f686150e5bcea75ecedc74dd157d874d754a2ca44b0ed" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.42.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4dcd171b8776c41b97521e5da127a2d86ad280114807d0b2ab1e462bc764d9e1" +checksum = "09d525d2ba30eeb3297665bd434a54297e4170c7f1a44cad4ef58095b4cd2028" [[package]] name = "windows_x86_64_msvc" @@ -5566,9 +5580,9 @@ checksum = "3f2b8c7cbd3bfdddd9ab98769f9746a7fad1bca236554cd032b78d768bc0e89f" [[package]] name = "windows_x86_64_msvc" -version = "0.36.1" +version = "0.42.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c811ca4a8c853ef420abd8592ba53ddbbac90410fab6903b3e79972a631f7680" +checksum = "f40009d85759725a34da6d89a94e63d7bdc50a862acf0dbc7c8e488f1edcb6f5" [[package]] name = "xattr" diff --git a/compiler/rustc_data_structures/Cargo.toml b/compiler/rustc_data_structures/Cargo.toml index 5152d5ab0465c..5afce15e26bfc 100644 --- a/compiler/rustc_data_structures/Cargo.toml +++ b/compiler/rustc_data_structures/Cargo.toml @@ -23,7 +23,7 @@ rustc_macros = { path = "../rustc_macros" } rustc_serialize = { path = "../rustc_serialize" } smallvec = { version = "1.8.1", features = ["const_generics", "union", "may_dangle"] } stable_deref_trait = "1.0.0" -stacker = "0.1.14" +stacker = "0.1.15" tempfile = "3.2" thin-vec = "0.2.9" tracing = "0.1" diff --git a/src/bootstrap/Cargo.lock b/src/bootstrap/Cargo.lock index baecca44cd987..e1a108cea9574 100644 --- a/src/bootstrap/Cargo.lock +++ b/src/bootstrap/Cargo.lock @@ -224,13 +224,13 @@ dependencies = [ [[package]] name = "fd-lock" -version = "3.0.6" +version = "3.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e11dcc7e4d79a8c89b9ab4c6f5c30b1fc4a83c420792da3542fd31179ed5f517" +checksum = "0c93a581058d957dc4176875aad04f82f81613e6611d64aa1a9c755bdfb16711" dependencies = [ "cfg-if", "rustix", - "windows-sys", + "windows-sys 0.42.0", ] [[package]] @@ -528,7 +528,7 @@ dependencies = [ "io-lifetimes", "libc", "linux-raw-sys", - "windows-sys", + "windows-sys 0.36.1", ] [[package]] @@ -721,43 +721,100 @@ version = "0.36.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ea04155a16a59f9eab786fe12a4a450e75cdb175f9e0d80da1e17db09f55b8d2" dependencies = [ - "windows_aarch64_msvc", - "windows_i686_gnu", - "windows_i686_msvc", - "windows_x86_64_gnu", - "windows_x86_64_msvc", + "windows_aarch64_msvc 0.36.1", + "windows_i686_gnu 0.36.1", + "windows_i686_msvc 0.36.1", + "windows_x86_64_gnu 0.36.1", + "windows_x86_64_msvc 0.36.1", ] +[[package]] +name = "windows-sys" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc 0.42.0", + "windows_i686_gnu 0.42.0", + "windows_i686_msvc 0.42.0", + "windows_x86_64_gnu 0.42.0", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc 0.42.0", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41d2aa71f6f0cbe00ae5167d90ef3cfe66527d6f613ca78ac8024c3ccab9a19e" + [[package]] name = "windows_aarch64_msvc" version = "0.36.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9bb8c3fd39ade2d67e9874ac4f3db21f0d710bee00fe7cab16949ec184eeaa47" +[[package]] +name = "windows_aarch64_msvc" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd0f252f5a35cac83d6311b2e795981f5ee6e67eb1f9a7f64eb4500fbc4dcdb4" + [[package]] name = "windows_i686_gnu" version = "0.36.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "180e6ccf01daf4c426b846dfc66db1fc518f074baa793aa7d9b9aaeffad6a3b6" +[[package]] +name = "windows_i686_gnu" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fbeae19f6716841636c28d695375df17562ca208b2b7d0dc47635a50ae6c5de7" + [[package]] name = "windows_i686_msvc" version = "0.36.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e2e7917148b2812d1eeafaeb22a97e4813dfa60a3f8f78ebe204bcc88f12f024" +[[package]] +name = "windows_i686_msvc" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "84c12f65daa39dd2babe6e442988fc329d6243fdce47d7d2d155b8d874862246" + [[package]] name = "windows_x86_64_gnu" version = "0.36.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4dcd171b8776c41b97521e5da127a2d86ad280114807d0b2ab1e462bc764d9e1" +[[package]] +name = "windows_x86_64_gnu" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf7b1b21b5362cbc318f686150e5bcea75ecedc74dd157d874d754a2ca44b0ed" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09d525d2ba30eeb3297665bd434a54297e4170c7f1a44cad4ef58095b4cd2028" + [[package]] name = "windows_x86_64_msvc" version = "0.36.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c811ca4a8c853ef420abd8592ba53ddbbac90410fab6903b3e79972a631f7680" +[[package]] +name = "windows_x86_64_msvc" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f40009d85759725a34da6d89a94e63d7bdc50a862acf0dbc7c8e488f1edcb6f5" + [[package]] name = "xattr" version = "0.2.3" diff --git a/src/bootstrap/Cargo.toml b/src/bootstrap/Cargo.toml index 95e711737738a..f74738437ea3a 100644 --- a/src/bootstrap/Cargo.toml +++ b/src/bootstrap/Cargo.toml @@ -36,7 +36,7 @@ test = false [dependencies] cmake = "0.1.38" -fd-lock = "3.0.6" +fd-lock = "3.0.7" filetime = "0.2" getopts = "0.2.19" cc = "1.0.69" From e49d10db14c618e2635d0e21b6e32cb2e1df78cf Mon Sep 17 00:00:00 2001 From: AndyJado <101876416+AndyJado@users.noreply.github.com> Date: Wed, 26 Oct 2022 10:42:05 +0800 Subject: [PATCH 09/12] first move on a nested span_label Apply suggestions from code review Co-authored-by: David Wood --- .../src/diagnostics/conflict_errors.rs | 14 ++++++--- .../rustc_borrowck/src/diagnostics/mod.rs | 20 +++++++++++++ .../rustc_borrowck/src/session_diagnostics.rs | 30 +++++++++++++++++++ .../locales/en-US/borrowck.ftl | 12 ++++++++ 4 files changed, 72 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs index 8987a51757cd5..7f26e970e3094 100644 --- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs @@ -724,13 +724,19 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { borrow_span, &self.describe_any_place(borrow.borrowed_place.as_ref()), ); - - borrow_spans.var_span_label( + borrow_spans.var_subdiag( &mut err, - { + |var_span| { + use crate::session_diagnostics::CaptureVarCause::*; let place = &borrow.borrowed_place; let desc_place = self.describe_any_place(place.as_ref()); - format!("borrow occurs due to use of {}{}", desc_place, borrow_spans.describe()) + match borrow_spans { + UseSpans::ClosureUse { generator_kind, .. } => match generator_kind { + Some(_) => BorrowUsePlaceGenerator { place: desc_place, var_span }, + None => BorrowUsePlaceClosure { place: desc_place, var_span }, + }, + _ => BorrowUsePlace { place: desc_place, var_span }, + } }, "mutable", ); diff --git a/compiler/rustc_borrowck/src/diagnostics/mod.rs b/compiler/rustc_borrowck/src/diagnostics/mod.rs index 534d9ecae6e6f..61518378e3d0c 100644 --- a/compiler/rustc_borrowck/src/diagnostics/mod.rs +++ b/compiler/rustc_borrowck/src/diagnostics/mod.rs @@ -623,6 +623,26 @@ impl UseSpans<'_> { } } + /// Add a subdiagnostic to the use of the captured variable, if it exists. + pub(super) fn var_subdiag( + self, + err: &mut Diagnostic, + f: impl Fn(Span) -> crate::session_diagnostics::CaptureVarCause, + kind_desc: impl Into, + ) { + if let UseSpans::ClosureUse { capture_kind_span, path_span, .. } = self { + if capture_kind_span == path_span { + err.subdiagnostic(f(capture_kind_span)); + } else { + err.subdiagnostic(crate::session_diagnostics::CaptureVarKind { + kind_desc: kind_desc.into(), + kind_span: capture_kind_span, + }); + err.subdiagnostic(f(path_span)); + } + } + } + /// Returns `false` if this place is not used in a closure. pub(super) fn for_closure(&self) -> bool { match *self { diff --git a/compiler/rustc_borrowck/src/session_diagnostics.rs b/compiler/rustc_borrowck/src/session_diagnostics.rs index fe24f85fae10a..824f20a31bb09 100644 --- a/compiler/rustc_borrowck/src/session_diagnostics.rs +++ b/compiler/rustc_borrowck/src/session_diagnostics.rs @@ -148,3 +148,33 @@ pub(crate) enum RequireStaticErr { multi_span: MultiSpan, }, } + +#[derive(Subdiagnostic)] +#[label(borrowck_capture_kind_label)] +pub(crate) struct CaptureVarKind { + pub kind_desc: String, + #[primary_span] + pub kind_span: Span, +} + +#[derive(Subdiagnostic)] +pub(crate) enum CaptureVarCause { + #[label(borrowck_var_borrow_by_use_place)] + BorrowUsePlace { + place: String, + #[primary_span] + var_span: Span, + }, + #[label(borrowck_var_borrow_by_use_place_in_generator)] + BorrowUsePlaceGenerator { + place: String, + #[primary_span] + var_span: Span, + }, + #[label(borrowck_var_borrow_by_use_place_in_closure)] + BorrowUsePlaceClosure { + place: String, + #[primary_span] + var_span: Span, + }, +} diff --git a/compiler/rustc_error_messages/locales/en-US/borrowck.ftl b/compiler/rustc_error_messages/locales/en-US/borrowck.ftl index 67f2156f32e50..80fc4c6e4f5d3 100644 --- a/compiler/rustc_error_messages/locales/en-US/borrowck.ftl +++ b/compiler/rustc_error_messages/locales/en-US/borrowck.ftl @@ -58,3 +58,15 @@ borrowck_returned_lifetime_short = borrowck_used_impl_require_static = the used `impl` has a `'static` requirement + +borrowck_capture_kind_label = + capture is {$kind_desc} because of use here + +borrowck_var_borrow_by_use_place_in_generator = + borrow occurs due to use of {$place} in closure in generator + +borrowck_var_borrow_by_use_place_in_closure = + borrow occurs due to use of {$place} in closure + +borrowck_var_borrow_by_use_place = + borrow occurs due to use of {$place} From c0889a6005ecac3d304009e734baa97b37b534d2 Mon Sep 17 00:00:00 2001 From: Boxy Date: Sun, 6 Nov 2022 13:39:13 +0000 Subject: [PATCH 10/12] fixyfixfix --- .../src/collect/lifetimes.rs | 92 ++++++++++++++++++- src/test/ui/issues/issue-47511.stderr | 18 ---- .../downgraded_to_early_through_alias.rs | 24 +++++ .../issue-47511.rs | 7 +- .../mismatched_arg_count.rs | 12 +++ .../mismatched_arg_count.stderr | 17 ++++ 6 files changed, 141 insertions(+), 29 deletions(-) delete mode 100644 src/test/ui/issues/issue-47511.stderr create mode 100644 src/test/ui/late-bound-lifetimes/downgraded_to_early_through_alias.rs rename src/test/ui/{issues => late-bound-lifetimes}/issue-47511.rs (52%) create mode 100644 src/test/ui/late-bound-lifetimes/mismatched_arg_count.rs create mode 100644 src/test/ui/late-bound-lifetimes/mismatched_arg_count.stderr diff --git a/compiler/rustc_hir_analysis/src/collect/lifetimes.rs b/compiler/rustc_hir_analysis/src/collect/lifetimes.rs index 3d07f3fbc674d..b9583bd2244b9 100644 --- a/compiler/rustc_hir_analysis/src/collect/lifetimes.rs +++ b/compiler/rustc_hir_analysis/src/collect/lifetimes.rs @@ -18,7 +18,7 @@ use rustc_middle::bug; use rustc_middle::hir::map::Map; use rustc_middle::hir::nested_filter; use rustc_middle::middle::resolve_lifetime::*; -use rustc_middle::ty::{self, DefIdTree, TyCtxt}; +use rustc_middle::ty::{self, DefIdTree, TyCtxt, TypeSuperVisitable, TypeVisitor}; use rustc_span::def_id::DefId; use rustc_span::symbol::{sym, Ident}; use rustc_span::Span; @@ -1781,7 +1781,7 @@ fn is_late_bound_map(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<&FxIndexSet< let mut late_bound = FxIndexSet::default(); - let mut constrained_by_input = ConstrainedCollector::default(); + let mut constrained_by_input = ConstrainedCollector { regions: Default::default(), tcx }; for arg_ty in decl.inputs { constrained_by_input.visit_ty(arg_ty); } @@ -1834,12 +1834,44 @@ fn is_late_bound_map(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<&FxIndexSet< debug!(?late_bound); return Some(tcx.arena.alloc(late_bound)); - #[derive(Default)] - struct ConstrainedCollector { + struct ConstrainedCollectorPostAstConv { + arg_is_constrained: Box<[bool]>, + } + + use std::ops::ControlFlow; + use ty::Ty; + impl<'tcx> TypeVisitor<'tcx> for ConstrainedCollectorPostAstConv { + fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow { + match t.kind() { + ty::Param(param_ty) => { + self.arg_is_constrained[param_ty.index as usize] = true; + } + ty::Projection(_) => return ControlFlow::Continue(()), + _ => (), + } + t.super_visit_with(self) + } + + fn visit_const(&mut self, _: ty::Const<'tcx>) -> ControlFlow { + ControlFlow::Continue(()) + } + + fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow { + debug!("r={:?}", r.kind()); + if let ty::RegionKind::ReEarlyBound(region) = r.kind() { + self.arg_is_constrained[region.index as usize] = true; + } + + ControlFlow::Continue(()) + } + } + + struct ConstrainedCollector<'tcx> { + tcx: TyCtxt<'tcx>, regions: FxHashSet, } - impl<'v> Visitor<'v> for ConstrainedCollector { + impl<'v> Visitor<'v> for ConstrainedCollector<'_> { fn visit_ty(&mut self, ty: &'v hir::Ty<'v>) { match ty.kind { hir::TyKind::Path( @@ -1850,6 +1882,56 @@ fn is_late_bound_map(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<&FxIndexSet< // (defined above) } + hir::TyKind::Path(hir::QPath::Resolved( + None, + hir::Path { res: Res::Def(DefKind::TyAlias, alias_def), segments, span }, + )) => { + // If this is a top level type alias attempt to "look through" it to see if the args + // are constrained, instead of assuming they are and inserting all the lifetimes. + // This is necessary for the following case: + // ``` + // type Alias<'a, T> = >::Assoc; + // fn foo<'a>(_: Alias<'a, ()>) -> Alias<'a, ()> { ... } + // ``` + // If we considered `'a` constrained then it would become late bound causing an error + // during astconv as the `'a` is not constrained by the input type `<() as Trait<'a>>::Assoc` + // but appears in the output type `<() as Trait<'a>>::Assoc`. + + let generics = self.tcx.generics_of(alias_def); + let mut walker = ConstrainedCollectorPostAstConv { + arg_is_constrained: vec![false; generics.params.len()].into_boxed_slice(), + }; + walker.visit_ty(self.tcx.type_of(alias_def)); + + match segments.last() { + Some(hir::PathSegment { args: Some(args), .. }) => { + let tcx = self.tcx; + for constrained_arg in + args.args.iter().enumerate().flat_map(|(n, arg)| { + match walker.arg_is_constrained.get(n) { + Some(true) => Some(arg), + Some(false) => None, + None => { + tcx.sess.delay_span_bug( + *span, + format!( + "Incorrect generic arg count for alias {:?}", + alias_def + ), + ); + None + } + } + }) + { + self.visit_generic_arg(constrained_arg); + } + } + Some(_) => (), + None => bug!("Path with no segments or self type"), + } + } + hir::TyKind::Path(hir::QPath::Resolved(None, ref path)) => { // consider only the lifetimes on the final // segment; I am not sure it's even currently diff --git a/src/test/ui/issues/issue-47511.stderr b/src/test/ui/issues/issue-47511.stderr deleted file mode 100644 index 9998ee0e8d0c6..0000000000000 --- a/src/test/ui/issues/issue-47511.stderr +++ /dev/null @@ -1,18 +0,0 @@ -error[E0581]: return type references an anonymous lifetime, which is not constrained by the fn input types - --> $DIR/issue-47511.rs:8:15 - | -LL | fn f(_: X) -> X { - | ^ - | - = note: lifetimes appearing in an associated or opaque type are not considered constrained - = note: consider introducing a named lifetime parameter - -error[E0581]: return type references lifetime `'a`, which is not constrained by the fn input types - --> $DIR/issue-47511.rs:12:23 - | -LL | fn g<'a>(_: X<'a>) -> X<'a> { - | ^^^^^ - -error: aborting due to 2 previous errors - -For more information about this error, try `rustc --explain E0581`. diff --git a/src/test/ui/late-bound-lifetimes/downgraded_to_early_through_alias.rs b/src/test/ui/late-bound-lifetimes/downgraded_to_early_through_alias.rs new file mode 100644 index 0000000000000..e56a34218e231 --- /dev/null +++ b/src/test/ui/late-bound-lifetimes/downgraded_to_early_through_alias.rs @@ -0,0 +1,24 @@ +// check-pass + +trait Gats<'a> { + type Assoc; + type Assoc2; +} + +trait Trait: for<'a> Gats<'a> { + fn foo<'a>(_: &mut >::Assoc) -> >::Assoc2; +} + +impl<'a> Gats<'a> for () { + type Assoc = &'a u32; + type Assoc2 = (); +} + +type GatsAssoc<'a, T> = >::Assoc; +type GatsAssoc2<'a, T> = >::Assoc2; + +impl Trait for () { + fn foo<'a>(_: &mut GatsAssoc<'a, Self>) -> GatsAssoc2<'a, Self> {} +} + +fn main() {} diff --git a/src/test/ui/issues/issue-47511.rs b/src/test/ui/late-bound-lifetimes/issue-47511.rs similarity index 52% rename from src/test/ui/issues/issue-47511.rs rename to src/test/ui/late-bound-lifetimes/issue-47511.rs index eb4860e75d758..7894435154082 100644 --- a/src/test/ui/issues/issue-47511.rs +++ b/src/test/ui/late-bound-lifetimes/issue-47511.rs @@ -1,9 +1,4 @@ -// check-fail -// known-bug: #47511 - -// Regression test for #47511: anonymous lifetimes can appear -// unconstrained in a return type, but only if they appear just once -// in the input, as the input to a projection. +// check-pass fn f(_: X) -> X { unimplemented!() diff --git a/src/test/ui/late-bound-lifetimes/mismatched_arg_count.rs b/src/test/ui/late-bound-lifetimes/mismatched_arg_count.rs new file mode 100644 index 0000000000000..0b331e2039f25 --- /dev/null +++ b/src/test/ui/late-bound-lifetimes/mismatched_arg_count.rs @@ -0,0 +1,12 @@ +// ensures that we don't ICE when there are too many args supplied to the alias. + +trait Trait<'a> { + type Assoc; +} + +type Alias<'a, T> = >::Assoc; + +fn bar<'a, T: Trait<'a>>(_: Alias<'a, 'a, T>) {} +//~^ error: this type alias takes 1 lifetime argument but 2 lifetime arguments were supplied + +fn main() {} diff --git a/src/test/ui/late-bound-lifetimes/mismatched_arg_count.stderr b/src/test/ui/late-bound-lifetimes/mismatched_arg_count.stderr new file mode 100644 index 0000000000000..3704d9bb957ed --- /dev/null +++ b/src/test/ui/late-bound-lifetimes/mismatched_arg_count.stderr @@ -0,0 +1,17 @@ +error[E0107]: this type alias takes 1 lifetime argument but 2 lifetime arguments were supplied + --> $DIR/mismatched_arg_count.rs:9:29 + | +LL | fn bar<'a, T: Trait<'a>>(_: Alias<'a, 'a, T>) {} + | ^^^^^ -- help: remove this lifetime argument + | | + | expected 1 lifetime argument + | +note: type alias defined here, with 1 lifetime parameter: `'a` + --> $DIR/mismatched_arg_count.rs:7:6 + | +LL | type Alias<'a, T> = >::Assoc; + | ^^^^^ -- + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0107`. From 49be827dcae4b226a2cb6f56e49083d49908fa6f Mon Sep 17 00:00:00 2001 From: Boxy Date: Tue, 8 Nov 2022 21:59:58 +0000 Subject: [PATCH 11/12] comment --- .../src/collect/lifetimes.rs | 34 +++++++++++++------ 1 file changed, 23 insertions(+), 11 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/collect/lifetimes.rs b/compiler/rustc_hir_analysis/src/collect/lifetimes.rs index b9583bd2244b9..c64177eea3f83 100644 --- a/compiler/rustc_hir_analysis/src/collect/lifetimes.rs +++ b/compiler/rustc_hir_analysis/src/collect/lifetimes.rs @@ -1834,6 +1834,27 @@ fn is_late_bound_map(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<&FxIndexSet< debug!(?late_bound); return Some(tcx.arena.alloc(late_bound)); + /// Visits a `ty::Ty` collecting information about what generic parameters are constrained. + /// + /// The visitor does not operate on `hir::Ty` so that it can be called on the rhs of a `type Alias<...> = ...;` + /// which may live in a separate crate so there would not be any hir available. Instead we use the `type_of` + /// query to obtain a `ty::Ty` which will be present even in cross crate scenarios. It also naturally + /// handles cycle detection as we go through the query system. + /// + /// This is necessary in the first place for the following case: + /// ``` + /// type Alias<'a, T> = >::Assoc; + /// fn foo<'a>(_: Alias<'a, ()>) -> Alias<'a, ()> { ... } + /// ``` + /// + /// If we conservatively considered `'a` unconstrained then we could break users who had written code before + /// we started correctly handling aliases. If we considered `'a` constrained then it would become late bound + /// causing an error during astconv as the `'a` is not constrained by the input type `<() as Trait<'a>>::Assoc` + /// but appears in the output type `<() as Trait<'a>>::Assoc`. + /// + /// We must therefore "look into" the `Alias` to see whether we should consider `'a` constrained or not. + /// + /// See #100508 #85533 #47511 for additional context struct ConstrainedCollectorPostAstConv { arg_is_constrained: Box<[bool]>, } @@ -1886,17 +1907,8 @@ fn is_late_bound_map(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<&FxIndexSet< None, hir::Path { res: Res::Def(DefKind::TyAlias, alias_def), segments, span }, )) => { - // If this is a top level type alias attempt to "look through" it to see if the args - // are constrained, instead of assuming they are and inserting all the lifetimes. - // This is necessary for the following case: - // ``` - // type Alias<'a, T> = >::Assoc; - // fn foo<'a>(_: Alias<'a, ()>) -> Alias<'a, ()> { ... } - // ``` - // If we considered `'a` constrained then it would become late bound causing an error - // during astconv as the `'a` is not constrained by the input type `<() as Trait<'a>>::Assoc` - // but appears in the output type `<() as Trait<'a>>::Assoc`. - + // See comments on `ConstrainedCollectorPostAstConv` for why this arm does not just consider + // substs to be unconstrained. let generics = self.tcx.generics_of(alias_def); let mut walker = ConstrainedCollectorPostAstConv { arg_is_constrained: vec![false; generics.params.len()].into_boxed_slice(), From 983a90d7160b5e6054827f42c0ecf9aa52cebcd4 Mon Sep 17 00:00:00 2001 From: Boxy Date: Tue, 8 Nov 2022 22:15:40 +0000 Subject: [PATCH 12/12] tests --- .../auxiliary/upstream_alias.rs | 5 +++++ .../ui/late-bound-lifetimes/cross_crate_alias.rs | 10 ++++++++++ .../late_bound_through_alias.rs | 16 ++++++++++++++++ 3 files changed, 31 insertions(+) create mode 100644 src/test/ui/late-bound-lifetimes/auxiliary/upstream_alias.rs create mode 100644 src/test/ui/late-bound-lifetimes/cross_crate_alias.rs create mode 100644 src/test/ui/late-bound-lifetimes/late_bound_through_alias.rs diff --git a/src/test/ui/late-bound-lifetimes/auxiliary/upstream_alias.rs b/src/test/ui/late-bound-lifetimes/auxiliary/upstream_alias.rs new file mode 100644 index 0000000000000..5b9dc0e43087c --- /dev/null +++ b/src/test/ui/late-bound-lifetimes/auxiliary/upstream_alias.rs @@ -0,0 +1,5 @@ +pub trait Trait<'a> { + type Assoc; +} + +pub type Alias<'a, T> = >::Assoc; diff --git a/src/test/ui/late-bound-lifetimes/cross_crate_alias.rs b/src/test/ui/late-bound-lifetimes/cross_crate_alias.rs new file mode 100644 index 0000000000000..4154c27924323 --- /dev/null +++ b/src/test/ui/late-bound-lifetimes/cross_crate_alias.rs @@ -0,0 +1,10 @@ +// aux-build:upstream_alias.rs +// check-pass + +extern crate upstream_alias; + +fn foo<'a, T: for<'b> upstream_alias::Trait<'b>>(_: upstream_alias::Alias<'a, T>) -> &'a () { + todo!() +} + +fn main() {} diff --git a/src/test/ui/late-bound-lifetimes/late_bound_through_alias.rs b/src/test/ui/late-bound-lifetimes/late_bound_through_alias.rs new file mode 100644 index 0000000000000..91839673c1f7a --- /dev/null +++ b/src/test/ui/late-bound-lifetimes/late_bound_through_alias.rs @@ -0,0 +1,16 @@ +// check-pass + +fn f(_: X) -> X { + unimplemented!() +} + +fn g<'a>(_: X<'a>) -> X<'a> { + unimplemented!() +} + +type X<'a> = &'a (); + +fn main() { + let _: for<'a> fn(X<'a>) -> X<'a> = g; + let _: for<'a> fn(X<'a>) -> X<'a> = f; +}