diff --git a/src/libcore/num/mod.rs b/src/libcore/num/mod.rs index 772502cc800e8..311447c844299 100644 --- a/src/libcore/num/mod.rs +++ b/src/libcore/num/mod.rs @@ -2152,6 +2152,7 @@ Basic usage: ", $Feature, "assert_eq!(", stringify!($SelfT), "::min_value(), 0);", $EndFeature, " ```"), #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_promotable] #[inline] pub const fn min_value() -> Self { 0 } } @@ -2168,6 +2169,7 @@ Basic usage: stringify!($MaxV), ");", $EndFeature, " ```"), #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_promotable] #[inline] pub const fn max_value() -> Self { !0 } } diff --git a/src/librustc_typeck/check/_match.rs b/src/librustc_typeck/check/_match.rs index 3204ef556f5dd..a1e51402830c9 100644 --- a/src/librustc_typeck/check/_match.rs +++ b/src/librustc_typeck/check/_match.rs @@ -626,9 +626,9 @@ https://doc.rust-lang.org/reference/types.html#trait-objects"); let discrim_diverges = self.diverges.get(); self.diverges.set(Diverges::Maybe); - // Typecheck the patterns first, so that we get types for all the - // bindings. - let all_arm_pats_diverge = arms.iter().map(|arm| { + // rust-lang/rust#55810: Typecheck patterns first (via eager + // collection into `Vec`), so we get types for all bindings. + let all_arm_pats_diverge: Vec<_> = arms.iter().map(|arm| { let mut all_pats_diverge = Diverges::WarnedAlways; for p in &arm.pats { self.diverges.set(Diverges::Maybe); @@ -644,7 +644,7 @@ https://doc.rust-lang.org/reference/types.html#trait-objects"); Diverges::Maybe => Diverges::Maybe, Diverges::Always | Diverges::WarnedAlways => Diverges::WarnedAlways, } - }); + }).collect(); // Now typecheck the blocks. // diff --git a/src/test/ui/consts/auxiliary/promotable_const_fn_lib.rs b/src/test/ui/consts/auxiliary/promotable_const_fn_lib.rs new file mode 100644 index 0000000000000..f6bbcc60e4e64 --- /dev/null +++ b/src/test/ui/consts/auxiliary/promotable_const_fn_lib.rs @@ -0,0 +1,31 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Crate that exports a const fn. Used for testing cross-crate. + +#![feature(staged_api, rustc_attrs)] +#![stable(since="1.0.0", feature = "mep")] + +#![crate_type="rlib"] + +#[rustc_promotable] +#[stable(since="1.0.0", feature = "mep")] +#[inline] +pub const fn foo() -> usize { 22 } + +#[stable(since="1.0.0", feature = "mep")] +pub struct Foo(usize); + +impl Foo { + #[stable(since="1.0.0", feature = "mep")] + #[inline] + #[rustc_promotable] + pub const fn foo() -> usize { 22 } +} diff --git a/src/test/ui/consts/promote_fn_calls.rs b/src/test/ui/consts/promote_fn_calls.rs new file mode 100644 index 0000000000000..045322de34708 --- /dev/null +++ b/src/test/ui/consts/promote_fn_calls.rs @@ -0,0 +1,13 @@ +// compile-pass +// aux-build:promotable_const_fn_lib.rs + +#![feature(nll)] + +extern crate promotable_const_fn_lib; + +use promotable_const_fn_lib::{foo, Foo}; + +fn main() { + let x: &'static usize = &foo(); + let x: &'static usize = &Foo::foo(); +} diff --git a/src/test/ui/consts/promote_fn_calls_std.rs b/src/test/ui/consts/promote_fn_calls_std.rs new file mode 100644 index 0000000000000..0350708d673d7 --- /dev/null +++ b/src/test/ui/consts/promote_fn_calls_std.rs @@ -0,0 +1,30 @@ +// compile-pass + +#![feature(nll)] + +fn main() { + let x: &'static u8 = &u8::max_value(); + let x: &'static u16 = &u16::max_value(); + let x: &'static u32 = &u32::max_value(); + let x: &'static u64 = &u64::max_value(); + let x: &'static u128 = &u128::max_value(); + let x: &'static usize = &usize::max_value(); + let x: &'static u8 = &u8::min_value(); + let x: &'static u16 = &u16::min_value(); + let x: &'static u32 = &u32::min_value(); + let x: &'static u64 = &u64::min_value(); + let x: &'static u128 = &u128::min_value(); + let x: &'static usize = &usize::min_value(); + let x: &'static i8 = &i8::max_value(); + let x: &'static i16 = &i16::max_value(); + let x: &'static i32 = &i32::max_value(); + let x: &'static i64 = &i64::max_value(); + let x: &'static i128 = &i128::max_value(); + let x: &'static isize = &isize::max_value(); + let x: &'static i8 = &i8::min_value(); + let x: &'static i16 = &i16::min_value(); + let x: &'static i32 = &i32::min_value(); + let x: &'static i64 = &i64::min_value(); + let x: &'static i128 = &i128::min_value(); + let x: &'static isize = &isize::min_value(); +} diff --git a/src/test/ui/typeck/issue-55810-must-typeck-match-pats-before-guards.rs b/src/test/ui/typeck/issue-55810-must-typeck-match-pats-before-guards.rs new file mode 100644 index 0000000000000..9eed80ad886e0 --- /dev/null +++ b/src/test/ui/typeck/issue-55810-must-typeck-match-pats-before-guards.rs @@ -0,0 +1,23 @@ +// compile-pass + +// rust-lang/rust#55810: types for a binding in a match arm can be +// inferred from arms that come later in the match. + +struct S; + +impl S { + fn method(&self) -> bool { + unimplemented!() + } +} + +fn get() -> T { + unimplemented!() +} + +fn main() { + match get() { + x if x.method() => {} + &S => {} + } +}