Auto merge of #91104 - matthiaskrgr:rollup-duk33o1, r=matthiaskrgr

Rollup of 4 pull requests

Successful merges:

 - #91008 (Adds IEEE 754-2019 minimun and maximum functions for f32/f64)
 - #91070 (Make `LLVMRustGetOrInsertGlobal` always return a `GlobalVariable`)
 - #91097 (Add spaces in opaque `impl Trait` with more than one trait)
 - #91098 (Don't suggest certain fixups (`.field`, `.await`, etc) when reporting errors while matching on arrays )

Failed merges:

r? `@ghost`
`@rustbot` modify labels: rollup
This commit is contained in:
bors 2021-11-21 10:19:33 +00:00
commit 3bfde2f1f4
17 changed files with 344 additions and 27 deletions

View File

@ -1695,11 +1695,23 @@ enum Mismatch<'a> {
}
_ => exp_found,
};
debug!("exp_found {:?} terr {:?}", exp_found, terr);
debug!("exp_found {:?} terr {:?} cause.code {:?}", exp_found, terr, cause.code);
if let Some(exp_found) = exp_found {
self.suggest_as_ref_where_appropriate(span, &exp_found, diag);
self.suggest_accessing_field_where_appropriate(cause, &exp_found, diag);
self.suggest_await_on_expect_found(cause, span, &exp_found, diag);
let should_suggest_fixes = if let ObligationCauseCode::Pattern { root_ty, .. } =
&cause.code
{
// Skip if the root_ty of the pattern is not the same as the expected_ty.
// If these types aren't equal then we've probably peeled off a layer of arrays.
same_type_modulo_infer(self.resolve_vars_if_possible(*root_ty), exp_found.expected)
} else {
true
};
if should_suggest_fixes {
self.suggest_as_ref_where_appropriate(span, &exp_found, diag);
self.suggest_accessing_field_where_appropriate(cause, &exp_found, diag);
self.suggest_await_on_expect_found(cause, span, &exp_found, diag);
}
}
// In some (most?) cases cause.body_id points to actual body, but in some cases
@ -1879,7 +1891,7 @@ fn suggest_accessing_field_where_appropriate(
.iter()
.filter(|field| field.vis.is_accessible_from(field.did, self.tcx))
.map(|field| (field.ident.name, field.ty(self.tcx, expected_substs)))
.find(|(_, ty)| ty::TyS::same_type(ty, exp_found.found))
.find(|(_, ty)| same_type_modulo_infer(ty, exp_found.found))
{
if let ObligationCauseCode::Pattern { span: Some(span), .. } = cause.code {
if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span) {
@ -1944,7 +1956,7 @@ fn suggest_as_ref_where_appropriate(
| (_, ty::Infer(_))
| (ty::Param(_), _)
| (ty::Infer(_), _) => {}
_ if ty::TyS::same_type(exp_ty, found_ty) => {}
_ if same_type_modulo_infer(exp_ty, found_ty) => {}
_ => show_suggestion = false,
};
}

View File

@ -124,8 +124,18 @@ extern "C" LLVMValueRef LLVMRustGetOrInsertFunction(LLVMModuleRef M,
extern "C" LLVMValueRef
LLVMRustGetOrInsertGlobal(LLVMModuleRef M, const char *Name, size_t NameLen, LLVMTypeRef Ty) {
Module *Mod = unwrap(M);
StringRef NameRef(Name, NameLen);
return wrap(unwrap(M)->getOrInsertGlobal(NameRef, unwrap(Ty)));
// We don't use Module::getOrInsertGlobal because that returns a Constant*,
// which may either be the real GlobalVariable*, or a constant bitcast of it
// if our type doesn't match the original declaration. We always want the
// GlobalVariable* so we can access linkage, visibility, etc.
GlobalVariable *GV = Mod->getGlobalVariable(NameRef, true);
if (!GV)
GV = new GlobalVariable(*Mod, unwrap(Ty), false,
GlobalValue::ExternalLinkage, nullptr, NameRef);
return wrap(GV);
}
extern "C" LLVMValueRef

View File

@ -688,7 +688,7 @@ fn pretty_print_type(mut self, ty: Ty<'tcx>) -> Result<Self::Type, Self::Error>
}
p!(
write("{}", if first { " " } else { "+" }),
write("{}", if first { " " } else { " + " }),
print(trait_ref.print_only_trait_path())
);
@ -699,7 +699,7 @@ fn pretty_print_type(mut self, ty: Ty<'tcx>) -> Result<Self::Type, Self::Error>
}
if is_future {
p!(write("{}Future", if first { " " } else { "+" }));
p!(write("{}Future", if first { " " } else { " + " }));
first = false;
if let Some(future_output_ty) = future_output_ty {
@ -712,7 +712,7 @@ fn pretty_print_type(mut self, ty: Ty<'tcx>) -> Result<Self::Type, Self::Error>
}
if !is_sized {
p!(write("{}?Sized", if first { " " } else { "+" }));
p!(write("{}?Sized", if first { " " } else { " + " }));
} else if first {
p!(" Sized");
}

View File

@ -673,6 +673,9 @@ pub fn to_radians(self) -> f32 {
/// Returns the maximum of the two numbers.
///
/// Follows the IEEE-754 2008 semantics for maxNum, except for handling of signaling NaNs.
/// This matches the behavior of libms fmin.
///
/// ```
/// let x = 1.0f32;
/// let y = 2.0f32;
@ -689,6 +692,9 @@ pub fn max(self, other: f32) -> f32 {
/// Returns the minimum of the two numbers.
///
/// Follows the IEEE-754 2008 semantics for minNum, except for handling of signaling NaNs.
/// This matches the behavior of libms fmin.
///
/// ```
/// let x = 1.0f32;
/// let y = 2.0f32;
@ -703,6 +709,68 @@ pub fn min(self, other: f32) -> f32 {
intrinsics::minnumf32(self, other)
}
/// Returns the maximum of the two numbers, propagating NaNs.
///
/// This returns NaN when *either* argument is NaN, as opposed to
/// [`f32::max`] which only returns NaN when *both* arguments are NaN.
///
/// ```
/// #![feature(float_minimum_maximum)]
/// let x = 1.0f32;
/// let y = 2.0f32;
///
/// assert_eq!(x.maximum(y), y);
/// assert!(x.maximum(f32::NAN).is_nan());
/// ```
///
/// If one of the arguments is NaN, then NaN is returned. Otherwise this returns the greater
/// of the two numbers. For this operation, -0.0 is considered to be less than +0.0.
/// Note that this follows the semantics specified in IEEE 754-2019.
#[unstable(feature = "float_minimum_maximum", issue = "91079")]
#[inline]
pub fn maximum(self, other: f32) -> f32 {
if self > other {
self
} else if other > self {
other
} else if self == other {
if self.is_sign_positive() && other.is_sign_negative() { self } else { other }
} else {
self + other
}
}
/// Returns the minimum of the two numbers, propagating NaNs.
///
/// This returns NaN when *either* argument is NaN, as opposed to
/// [`f32::min`] which only returns NaN when *both* arguments are NaN.
///
/// ```
/// #![feature(float_minimum_maximum)]
/// let x = 1.0f32;
/// let y = 2.0f32;
///
/// assert_eq!(x.minimum(y), x);
/// assert!(x.minimum(f32::NAN).is_nan());
/// ```
///
/// If one of the arguments is NaN, then NaN is returned. Otherwise this returns the lesser
/// of the two numbers. For this operation, -0.0 is considered to be less than +0.0.
/// Note that this follows the semantics specified in IEEE 754-2019.
#[unstable(feature = "float_minimum_maximum", issue = "91079")]
#[inline]
pub fn minimum(self, other: f32) -> f32 {
if self < other {
self
} else if other < self {
other
} else if self == other {
if self.is_sign_negative() && other.is_sign_positive() { self } else { other }
} else {
self + other
}
}
/// Rounds toward zero and converts to any primitive integer type,
/// assuming that the value is finite and fits in that type.
///

View File

@ -689,6 +689,9 @@ pub fn to_radians(self) -> f64 {
/// Returns the maximum of the two numbers.
///
/// Follows the IEEE-754 2008 semantics for maxNum, except for handling of signaling NaNs.
/// This matches the behavior of libms fmin.
///
/// ```
/// let x = 1.0_f64;
/// let y = 2.0_f64;
@ -705,6 +708,9 @@ pub fn max(self, other: f64) -> f64 {
/// Returns the minimum of the two numbers.
///
/// Follows the IEEE-754 2008 semantics for minNum, except for handling of signaling NaNs.
/// This matches the behavior of libms fmin.
///
/// ```
/// let x = 1.0_f64;
/// let y = 2.0_f64;
@ -719,6 +725,68 @@ pub fn min(self, other: f64) -> f64 {
intrinsics::minnumf64(self, other)
}
/// Returns the maximum of the two numbers, propagating NaNs.
///
/// This returns NaN when *either* argument is NaN, as opposed to
/// [`f64::max`] which only returns NaN when *both* arguments are NaN.
///
/// ```
/// #![feature(float_minimum_maximum)]
/// let x = 1.0_f64;
/// let y = 2.0_f64;
///
/// assert_eq!(x.maximum(y), y);
/// assert!(x.maximum(f64::NAN).is_nan());
/// ```
///
/// If one of the arguments is NaN, then NaN is returned. Otherwise this returns the greater
/// of the two numbers. For this operation, -0.0 is considered to be less than +0.0.
/// Note that this follows the semantics specified in IEEE 754-2019.
#[unstable(feature = "float_minimum_maximum", issue = "91079")]
#[inline]
pub fn maximum(self, other: f64) -> f64 {
if self > other {
self
} else if other > self {
other
} else if self == other {
if self.is_sign_positive() && other.is_sign_negative() { self } else { other }
} else {
self + other
}
}
/// Returns the minimum of the two numbers, propagating NaNs.
///
/// This returns NaN when *either* argument is NaN, as opposed to
/// [`f64::min`] which only returns NaN when *both* arguments are NaN.
///
/// ```
/// #![feature(float_minimum_maximum)]
/// let x = 1.0_f64;
/// let y = 2.0_f64;
///
/// assert_eq!(x.minimum(y), x);
/// assert!(x.minimum(f64::NAN).is_nan());
/// ```
///
/// If one of the arguments is NaN, then NaN is returned. Otherwise this returns the lesser
/// of the two numbers. For this operation, -0.0 is considered to be less than +0.0.
/// Note that this follows the semantics specified in IEEE 754-2019.
#[unstable(feature = "float_minimum_maximum", issue = "91079")]
#[inline]
pub fn minimum(self, other: f64) -> f64 {
if self < other {
self
} else if other < self {
other
} else if self == other {
if self.is_sign_negative() && other.is_sign_positive() { self } else { other }
} else {
self + other
}
}
/// Rounds toward zero and converts to any primitive integer type,
/// assuming that the value is finite and fits in that type.
///

View File

@ -27,6 +27,7 @@
#![feature(extern_types)]
#![feature(flt2dec)]
#![feature(fmt_internals)]
#![feature(float_minimum_maximum)]
#![feature(array_from_fn)]
#![feature(hashmap_internals)]
#![feature(try_find)]

View File

@ -715,6 +715,67 @@ fn max() {
assert!(($nan as $fty).max($nan).is_nan());
}
#[test]
fn minimum() {
assert_eq!((0.0 as $fty).minimum(0.0), 0.0);
assert!((0.0 as $fty).minimum(0.0).is_sign_positive());
assert_eq!((-0.0 as $fty).minimum(0.0), -0.0);
assert!((-0.0 as $fty).minimum(0.0).is_sign_negative());
assert_eq!((-0.0 as $fty).minimum(-0.0), -0.0);
assert!((-0.0 as $fty).minimum(-0.0).is_sign_negative());
assert_eq!((9.0 as $fty).minimum(9.0), 9.0);
assert_eq!((-9.0 as $fty).minimum(0.0), -9.0);
assert_eq!((0.0 as $fty).minimum(9.0), 0.0);
assert!((0.0 as $fty).minimum(9.0).is_sign_positive());
assert_eq!((-0.0 as $fty).minimum(9.0), -0.0);
assert!((-0.0 as $fty).minimum(9.0).is_sign_negative());
assert_eq!((-0.0 as $fty).minimum(-9.0), -9.0);
assert_eq!(($inf as $fty).minimum(9.0), 9.0);
assert_eq!((9.0 as $fty).minimum($inf), 9.0);
assert_eq!(($inf as $fty).minimum(-9.0), -9.0);
assert_eq!((-9.0 as $fty).minimum($inf), -9.0);
assert_eq!(($neginf as $fty).minimum(9.0), $neginf);
assert_eq!((9.0 as $fty).minimum($neginf), $neginf);
assert_eq!(($neginf as $fty).minimum(-9.0), $neginf);
assert_eq!((-9.0 as $fty).minimum($neginf), $neginf);
assert!(($nan as $fty).minimum(9.0).is_nan());
assert!(($nan as $fty).minimum(-9.0).is_nan());
assert!((9.0 as $fty).minimum($nan).is_nan());
assert!((-9.0 as $fty).minimum($nan).is_nan());
assert!(($nan as $fty).minimum($nan).is_nan());
}
#[test]
fn maximum() {
assert_eq!((0.0 as $fty).maximum(0.0), 0.0);
assert!((0.0 as $fty).maximum(0.0).is_sign_positive());
assert_eq!((-0.0 as $fty).maximum(0.0), 0.0);
assert!((-0.0 as $fty).maximum(0.0).is_sign_positive());
assert_eq!((-0.0 as $fty).maximum(-0.0), -0.0);
assert!((-0.0 as $fty).maximum(-0.0).is_sign_negative());
assert_eq!((9.0 as $fty).maximum(9.0), 9.0);
assert_eq!((-9.0 as $fty).maximum(0.0), 0.0);
assert!((-9.0 as $fty).maximum(0.0).is_sign_positive());
assert_eq!((-9.0 as $fty).maximum(-0.0), -0.0);
assert!((-9.0 as $fty).maximum(-0.0).is_sign_negative());
assert_eq!((0.0 as $fty).maximum(9.0), 9.0);
assert_eq!((0.0 as $fty).maximum(-9.0), 0.0);
assert!((0.0 as $fty).maximum(-9.0).is_sign_positive());
assert_eq!((-0.0 as $fty).maximum(-9.0), -0.0);
assert!((-0.0 as $fty).maximum(-9.0).is_sign_negative());
assert_eq!(($inf as $fty).maximum(9.0), $inf);
assert_eq!((9.0 as $fty).maximum($inf), $inf);
assert_eq!(($inf as $fty).maximum(-9.0), $inf);
assert_eq!((-9.0 as $fty).maximum($inf), $inf);
assert_eq!(($neginf as $fty).maximum(9.0), 9.0);
assert_eq!((9.0 as $fty).maximum($neginf), 9.0);
assert_eq!(($neginf as $fty).maximum(-9.0), -9.0);
assert_eq!((-9.0 as $fty).maximum($neginf), -9.0);
assert!(($nan as $fty).maximum(9.0).is_nan());
assert!(($nan as $fty).maximum(-9.0).is_nan());
assert!((9.0 as $fty).maximum($nan).is_nan());
assert!((-9.0 as $fty).maximum($nan).is_nan());
assert!(($nan as $fty).maximum($nan).is_nan());
}
#[test]
fn rem_euclid() {
let a: $fty = 42.0;
assert!($inf.rem_euclid(a).is_nan());

View File

@ -19,6 +19,18 @@ fn test_max_nan() {
assert_eq!(2.0f32.max(f32::NAN), 2.0);
}
#[test]
fn test_minimum() {
assert!(f32::NAN.minimum(2.0).is_nan());
assert!(2.0f32.minimum(f32::NAN).is_nan());
}
#[test]
fn test_maximum() {
assert!(f32::NAN.maximum(2.0).is_nan());
assert!(2.0f32.maximum(f32::NAN).is_nan());
}
#[test]
fn test_nan() {
let nan: f32 = f32::NAN;

View File

@ -287,6 +287,7 @@
#![feature(exhaustive_patterns)]
#![feature(extend_one)]
#![feature(fn_traits)]
#![feature(float_minimum_maximum)]
#![feature(format_args_nl)]
#![feature(gen_future)]
#![feature(generator_trait)]

View File

@ -83,17 +83,17 @@ fn main() {
//~^ ERROR type mismatch resolving `<impl DerivedTrait as Trait>::Associated == ()`
accepts_trait(returns_opaque_foo());
//~^ ERROR type mismatch resolving `<impl Trait+Foo as Trait>::Associated == ()`
//~^ ERROR type mismatch resolving `<impl Trait + Foo as Trait>::Associated == ()`
accepts_trait(returns_opaque_derived_foo());
//~^ ERROR type mismatch resolving `<impl DerivedTrait+Foo as Trait>::Associated == ()`
//~^ ERROR type mismatch resolving `<impl DerivedTrait + Foo as Trait>::Associated == ()`
accepts_generic_trait(returns_opaque_generic());
//~^ ERROR type mismatch resolving `<impl GenericTrait<()> as GenericTrait<()>>::Associated == ()`
accepts_generic_trait(returns_opaque_generic_foo());
//~^ ERROR type mismatch resolving `<impl GenericTrait<()>+Foo as GenericTrait<()>>::Associated == ()`
//~^ ERROR type mismatch resolving `<impl GenericTrait<()> + Foo as GenericTrait<()>>::Associated == ()`
accepts_generic_trait(returns_opaque_generic_duplicate());
//~^ ERROR type mismatch resolving `<impl GenericTrait<()>+GenericTrait<u8> as GenericTrait<()>>::Associated == ()`
//~^ ERROR type mismatch resolving `<impl GenericTrait<()> + GenericTrait<u8> as GenericTrait<()>>::Associated == ()`
}

View File

@ -160,7 +160,7 @@ help: consider constraining the associated type `<impl DerivedTrait as Trait>::A
LL | fn returns_opaque_derived() -> impl DerivedTrait<Associated = ()> + 'static {
| +++++++++++++++++
error[E0271]: type mismatch resolving `<impl Trait+Foo as Trait>::Associated == ()`
error[E0271]: type mismatch resolving `<impl Trait + Foo as Trait>::Associated == ()`
--> $DIR/issue-87261.rs:85:5
|
LL | fn returns_opaque_foo() -> impl Trait + Foo {
@ -170,18 +170,18 @@ LL | accepts_trait(returns_opaque_foo());
| ^^^^^^^^^^^^^ expected `()`, found associated type
|
= note: expected unit type `()`
found associated type `<impl Trait+Foo as Trait>::Associated`
found associated type `<impl Trait + Foo as Trait>::Associated`
note: required by a bound in `accepts_trait`
--> $DIR/issue-87261.rs:43:27
|
LL | fn accepts_trait<T: Trait<Associated = ()>>(_: T) {}
| ^^^^^^^^^^^^^^^ required by this bound in `accepts_trait`
help: consider constraining the associated type `<impl Trait+Foo as Trait>::Associated` to `()`
help: consider constraining the associated type `<impl Trait + Foo as Trait>::Associated` to `()`
|
LL | fn returns_opaque_foo() -> impl Trait<Associated = ()> + Foo {
| +++++++++++++++++
error[E0271]: type mismatch resolving `<impl DerivedTrait+Foo as Trait>::Associated == ()`
error[E0271]: type mismatch resolving `<impl DerivedTrait + Foo as Trait>::Associated == ()`
--> $DIR/issue-87261.rs:88:5
|
LL | fn returns_opaque_derived_foo() -> impl DerivedTrait + Foo {
@ -191,8 +191,8 @@ LL | accepts_trait(returns_opaque_derived_foo());
| ^^^^^^^^^^^^^ expected `()`, found associated type
|
= note: expected unit type `()`
found associated type `<impl DerivedTrait+Foo as Trait>::Associated`
= help: consider constraining the associated type `<impl DerivedTrait+Foo as Trait>::Associated` to `()`
found associated type `<impl DerivedTrait + Foo as Trait>::Associated`
= help: consider constraining the associated type `<impl DerivedTrait + Foo as Trait>::Associated` to `()`
= note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html
note: required by a bound in `accepts_trait`
--> $DIR/issue-87261.rs:43:27
@ -221,7 +221,7 @@ help: consider constraining the associated type `<impl GenericTrait<()> as Gener
LL | fn returns_opaque_generic() -> impl GenericTrait<(), Associated = ()> + 'static {
| +++++++++++++++++
error[E0271]: type mismatch resolving `<impl GenericTrait<()>+Foo as GenericTrait<()>>::Associated == ()`
error[E0271]: type mismatch resolving `<impl GenericTrait<()> + Foo as GenericTrait<()>>::Associated == ()`
--> $DIR/issue-87261.rs:94:5
|
LL | fn returns_opaque_generic_foo() -> impl GenericTrait<()> + Foo {
@ -231,18 +231,18 @@ LL | accepts_generic_trait(returns_opaque_generic_foo());
| ^^^^^^^^^^^^^^^^^^^^^ expected `()`, found associated type
|
= note: expected unit type `()`
found associated type `<impl GenericTrait<()>+Foo as GenericTrait<()>>::Associated`
found associated type `<impl GenericTrait<()> + Foo as GenericTrait<()>>::Associated`
note: required by a bound in `accepts_generic_trait`
--> $DIR/issue-87261.rs:44:46
|
LL | fn accepts_generic_trait<T: GenericTrait<(), Associated = ()>>(_: T) {}
| ^^^^^^^^^^^^^^^ required by this bound in `accepts_generic_trait`
help: consider constraining the associated type `<impl GenericTrait<()>+Foo as GenericTrait<()>>::Associated` to `()`
help: consider constraining the associated type `<impl GenericTrait<()> + Foo as GenericTrait<()>>::Associated` to `()`
|
LL | fn returns_opaque_generic_foo() -> impl GenericTrait<(), Associated = ()> + Foo {
| +++++++++++++++++
error[E0271]: type mismatch resolving `<impl GenericTrait<()>+GenericTrait<u8> as GenericTrait<()>>::Associated == ()`
error[E0271]: type mismatch resolving `<impl GenericTrait<()> + GenericTrait<u8> as GenericTrait<()>>::Associated == ()`
--> $DIR/issue-87261.rs:97:5
|
LL | fn returns_opaque_generic_duplicate() -> impl GenericTrait<()> + GenericTrait<u8> {
@ -252,8 +252,8 @@ LL | accepts_generic_trait(returns_opaque_generic_duplicate());
| ^^^^^^^^^^^^^^^^^^^^^ expected `()`, found associated type
|
= note: expected unit type `()`
found associated type `<impl GenericTrait<()>+GenericTrait<u8> as GenericTrait<()>>::Associated`
= help: consider constraining the associated type `<impl GenericTrait<()>+GenericTrait<u8> as GenericTrait<()>>::Associated` to `()`
found associated type `<impl GenericTrait<()> + GenericTrait<u8> as GenericTrait<()>>::Associated`
= help: consider constraining the associated type `<impl GenericTrait<()> + GenericTrait<u8> as GenericTrait<()>>::Associated` to `()`
= note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html
note: required by a bound in `accepts_generic_trait`
--> $DIR/issue-87261.rs:44:46

View File

@ -1,4 +1,4 @@
error[E0606]: casting `*mut impl Debug+?Sized` as `*mut impl Debug+?Sized` is invalid
error[E0606]: casting `*mut impl Debug + ?Sized` as `*mut impl Debug + ?Sized` is invalid
--> $DIR/casts-differing-anon.rs:21:13
|
LL | b_raw = f_raw as *mut _;

View File

@ -8,6 +8,10 @@ LL | Either::Right(_) => {}
|
= note: expected struct `S`
found enum `Either<_, _>`
help: you might have meant to use field `0` whose type is `Either<usize, usize>`
|
LL | match S(Either::Left(5)).0 {
| ~~~~~~~~~~~~~~~~~~~~
error: aborting due to previous error

View File

@ -0,0 +1,11 @@
struct S(());
fn main() {
let array = [S(())];
match array {
[()] => {}
//~^ ERROR mismatched types [E0308]
_ => {}
}
}

View File

@ -0,0 +1,11 @@
error[E0308]: mismatched types
--> $DIR/issue-91058.rs:7:10
|
LL | match array {
| ----- this expression has type `[S; 1]`
LL | [()] => {}
| ^^ expected struct `S`, found `()`
error: aborting due to previous error
For more information about this error, try `rustc --explain E0308`.

View File

@ -0,0 +1,34 @@
// build-pass
// compile-flags: --crate-type=rlib --emit=llvm-ir -Cno-prepopulate-passes
// This test declares globals by the same name with different types, which
// caused problems because Module::getOrInsertGlobal would return a Constant*
// bitcast instead of a GlobalVariable* that could access linkage/visibility.
// In alt builds with LLVM assertions this would fail:
//
// rustc: /checkout/src/llvm-project/llvm/include/llvm/Support/Casting.h:269:
// typename cast_retty<X, Y *>::ret_type llvm::cast(Y *) [X = llvm::GlobalValue, Y = llvm::Value]:
// Assertion `isa<X>(Val) && "cast<Ty>() argument of incompatible type!"' failed.
//
// In regular builds, the bad cast was UB, like "Invalid LLVMRustVisibility value!"
pub mod before {
#[no_mangle]
pub static GLOBAL1: [u8; 1] = [1];
}
pub mod inner {
extern "C" {
pub static GLOBAL1: u8;
pub static GLOBAL2: u8;
}
pub fn call() {
drop(unsafe { (GLOBAL1, GLOBAL2) });
}
}
pub mod after {
#[no_mangle]
pub static GLOBAL2: [u8; 1] = [2];
}

View File

@ -0,0 +1,24 @@
// build-pass
// compile-flags: --crate-type=rlib --emit=llvm-ir -Cno-prepopulate-passes
// This is a variant of issue-91050-1.rs -- see there for an explanation.
pub mod before {
extern "C" {
pub static GLOBAL1: [u8; 1];
}
pub unsafe fn do_something_with_array() -> u8 {
GLOBAL1[0]
}
}
pub mod inner {
extern "C" {
pub static GLOBAL1: u8;
}
pub unsafe fn call() -> u8 {
GLOBAL1 + 42
}
}