From b4337ab8c387658b7012fa242e429f46c5f31141 Mon Sep 17 00:00:00 2001 From: djugei Date: Wed, 27 May 2020 19:59:44 +0200 Subject: [PATCH 01/22] added .collect() into String from Box with fake feature/stability annotation --- src/liballoc/string.rs | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/liballoc/string.rs b/src/liballoc/string.rs index f3fe1adebb141..f205835845e40 100644 --- a/src/liballoc/string.rs +++ b/src/liballoc/string.rs @@ -1772,6 +1772,15 @@ impl FromIterator for String { } } +#[stable(feature = "box_str2", since = "1.45.0")] +impl FromIterator> for String { + fn from_iter>>(iter: I) -> String { + let mut buf = String::new(); + buf.extend(iter); + buf + } +} + #[stable(feature = "herd_cows", since = "1.19.0")] impl<'a> FromIterator> for String { fn from_iter>>(iter: I) -> String { @@ -1815,6 +1824,13 @@ impl<'a> Extend<&'a str> for String { } } +#[stable(feature = "box_str2", since = "1.45.0")] +impl Extend> for String { + fn extend>>(&mut self, iter: I) { + iter.into_iter().for_each(move |s| self.push_str(&s)); + } +} + #[stable(feature = "extend_string", since = "1.4.0")] impl Extend for String { fn extend>(&mut self, iter: I) { From f772587aba7b2be9a2fa708a26ba2605e32148ff Mon Sep 17 00:00:00 2001 From: Ivan Tham Date: Sat, 27 Jun 2020 13:09:06 +0800 Subject: [PATCH 02/22] Add unstable docs for rustc_attrs --- .../src/language-features/rustc-attrs.md | 50 +++++++++++++++++++ 1 file changed, 50 insertions(+) create mode 100644 src/doc/unstable-book/src/language-features/rustc-attrs.md diff --git a/src/doc/unstable-book/src/language-features/rustc-attrs.md b/src/doc/unstable-book/src/language-features/rustc-attrs.md new file mode 100644 index 0000000000000..500ae61b1dd08 --- /dev/null +++ b/src/doc/unstable-book/src/language-features/rustc-attrs.md @@ -0,0 +1,50 @@ +# `rustc_attrs` + +This feature has no tracking issue, and is therefore likely internal to +the compiler, not being intended for general use. + +------------------------ + +The `rustc_attrs` feature allows debugging rustc type layouts by using +`#[rustc_layout(...)]` to debug layout at compile time (it even works +with `cargo check`) as an alternative to `rustc -Z print-type-sizes` +that is way more verbose. + +Options provided by `#[rustc_layout(...)]` are `debug`, `size`, `abi`. +Note that it only work best with sized type without generics. + +## Examples + +```rust +#![feature(rustc_attrs)] + +#[rustc_layout(abi, size)] +pub enum X { + Y(u8, u8, u8), + Z(isize), +} +``` + +When that is compiled, the compiler will error with something like + +``` +error: abi: Aggregate { sized: true } + --> src/lib.rs:4:1 + | +4 | / pub enum T { +5 | | Y(u8, u8, u8), +6 | | Z(isize), +7 | | } + | |_^ + +error: size: Size { raw: 16 } + --> src/lib.rs:4:1 + | +4 | / pub enum T { +5 | | Y(u8, u8, u8), +6 | | Z(isize), +7 | | } + | |_^ + +error: aborting due to 2 previous errors +``` From 725918f17e9a2c1e8a0ffec658d1363681f768bd Mon Sep 17 00:00:00 2001 From: Ivan Tham Date: Sun, 28 Jun 2020 00:23:37 +0800 Subject: [PATCH 03/22] Update src/doc/unstable-book/src/language-features/rustc-attrs.md Co-authored-by: Ralf Jung --- src/doc/unstable-book/src/language-features/rustc-attrs.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doc/unstable-book/src/language-features/rustc-attrs.md b/src/doc/unstable-book/src/language-features/rustc-attrs.md index 500ae61b1dd08..01450c8fb1f9b 100644 --- a/src/doc/unstable-book/src/language-features/rustc-attrs.md +++ b/src/doc/unstable-book/src/language-features/rustc-attrs.md @@ -1,6 +1,6 @@ # `rustc_attrs` -This feature has no tracking issue, and is therefore likely internal to +This feature has no tracking issue, and is therefore internal to the compiler, not being intended for general use. ------------------------ From 0e6f1093be08949b6ac4ba3d92ad4e97d0137dc5 Mon Sep 17 00:00:00 2001 From: Ivan Tham Date: Sun, 28 Jun 2020 21:47:58 +0800 Subject: [PATCH 04/22] Add preamable on rustc-attrs doc discussion --- src/doc/unstable-book/src/language-features/rustc-attrs.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/doc/unstable-book/src/language-features/rustc-attrs.md b/src/doc/unstable-book/src/language-features/rustc-attrs.md index 01450c8fb1f9b..ad96aaf8281d6 100644 --- a/src/doc/unstable-book/src/language-features/rustc-attrs.md +++ b/src/doc/unstable-book/src/language-features/rustc-attrs.md @@ -3,6 +3,9 @@ This feature has no tracking issue, and is therefore internal to the compiler, not being intended for general use. +Note: `rustc_attrs` enables many rustc-internal attributes and this page +only discuss a few of them. + ------------------------ The `rustc_attrs` feature allows debugging rustc type layouts by using From 49b4804d291bc8cc93e7b4b8c24f344aa3e3f484 Mon Sep 17 00:00:00 2001 From: Ivan Tham Date: Mon, 29 Jun 2020 10:56:10 +0800 Subject: [PATCH 05/22] Ignore example compile in rustc-attrs doc --- src/doc/unstable-book/src/language-features/rustc-attrs.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/doc/unstable-book/src/language-features/rustc-attrs.md b/src/doc/unstable-book/src/language-features/rustc-attrs.md index ad96aaf8281d6..2967200faf80d 100644 --- a/src/doc/unstable-book/src/language-features/rustc-attrs.md +++ b/src/doc/unstable-book/src/language-features/rustc-attrs.md @@ -18,7 +18,7 @@ Note that it only work best with sized type without generics. ## Examples -```rust +```rust,ignore #![feature(rustc_attrs)] #[rustc_layout(abi, size)] @@ -30,7 +30,7 @@ pub enum X { When that is compiled, the compiler will error with something like -``` +```text error: abi: Aggregate { sized: true } --> src/lib.rs:4:1 | From aab37fe52c0f142d116fee67d6eddedc7825dcc7 Mon Sep 17 00:00:00 2001 From: Dan Aloni Date: Sat, 27 Jun 2020 21:08:32 +0300 Subject: [PATCH 06/22] Add test for issue #56175 --- .../ui/issues/auxiliary/reexported-trait.rs | 17 ++++++++++++ src/test/ui/issues/issue-56175.rs | 9 +++++++ src/test/ui/issues/issue-56175.stderr | 27 +++++++++++++++++++ 3 files changed, 53 insertions(+) create mode 100644 src/test/ui/issues/auxiliary/reexported-trait.rs create mode 100644 src/test/ui/issues/issue-56175.rs create mode 100644 src/test/ui/issues/issue-56175.stderr diff --git a/src/test/ui/issues/auxiliary/reexported-trait.rs b/src/test/ui/issues/auxiliary/reexported-trait.rs new file mode 100644 index 0000000000000..51a991bef5959 --- /dev/null +++ b/src/test/ui/issues/auxiliary/reexported-trait.rs @@ -0,0 +1,17 @@ +mod private { + pub trait Trait { + fn trait_method(&self) { + } + } + pub trait TraitB { + fn trait_method_b(&self) { + } + } +} + +pub struct FooStruct; +pub use crate::private::Trait; +impl crate::private::Trait for FooStruct {} + +pub use crate::private::TraitB as TraitBRename; +impl crate::private::TraitB for FooStruct {} diff --git a/src/test/ui/issues/issue-56175.rs b/src/test/ui/issues/issue-56175.rs new file mode 100644 index 0000000000000..ca1d0d4310ae9 --- /dev/null +++ b/src/test/ui/issues/issue-56175.rs @@ -0,0 +1,9 @@ +// edition:2018 +// aux-crate:reexported_trait=reexported-trait.rs + +fn main() { + reexported_trait::FooStruct.trait_method(); + //~^ ERROR + reexported_trait::FooStruct.trait_method_b(); + //~^ ERROR +} diff --git a/src/test/ui/issues/issue-56175.stderr b/src/test/ui/issues/issue-56175.stderr new file mode 100644 index 0000000000000..dc5beb4271df7 --- /dev/null +++ b/src/test/ui/issues/issue-56175.stderr @@ -0,0 +1,27 @@ +error[E0599]: no method named `trait_method` found for struct `reexported_trait::FooStruct` in the current scope + --> $DIR/issue-56175.rs:5:33 + | +LL | reexported_trait::FooStruct.trait_method(); + | ^^^^^^^^^^^^ method not found in `reexported_trait::FooStruct` + | + = help: items from traits can only be used if the trait is in scope +help: the following trait is implemented but not in scope; perhaps add a `use` for it: + | +LL | use reexported_trait::private::Trait; + | + +error[E0599]: no method named `trait_method_b` found for struct `reexported_trait::FooStruct` in the current scope + --> $DIR/issue-56175.rs:7:33 + | +LL | reexported_trait::FooStruct.trait_method_b(); + | ^^^^^^^^^^^^^^ method not found in `reexported_trait::FooStruct` + | + = help: items from traits can only be used if the trait is in scope +help: the following trait is implemented but not in scope; perhaps add a `use` for it: + | +LL | use reexported_trait::private::TraitB; + | + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0599`. From 5427d3bf7c38df0c37597272bf34c6710cab3c52 Mon Sep 17 00:00:00 2001 From: Dan Aloni Date: Mon, 29 Jun 2020 21:51:32 +0300 Subject: [PATCH 07/22] Fix try_print_visible_def_path for Rust 2018 The recursive check of `try_print_visible_def_path` did not properly handle the Rust 2018 case of crate-paths without 'extern crate'. Instead, it returned a "not found" via (false, self). This fixes issue #56175. --- src/librustc_middle/ty/print/pretty.rs | 35 +++++++++++++------------- src/test/ui/issues/issue-56175.stderr | 4 +-- 2 files changed, 20 insertions(+), 19 deletions(-) diff --git a/src/librustc_middle/ty/print/pretty.rs b/src/librustc_middle/ty/print/pretty.rs index 061214249713d..bbf9f550c03f4 100644 --- a/src/librustc_middle/ty/print/pretty.rs +++ b/src/librustc_middle/ty/print/pretty.rs @@ -282,26 +282,27 @@ pub trait PrettyPrinter<'tcx>: // where there is no explicit `extern crate`, we just prepend // the crate name. match self.tcx().extern_crate(def_id) { - Some(&ExternCrate { - src: ExternCrateSource::Extern(def_id), - dependency_of: LOCAL_CRATE, - span, - .. - }) => { - debug!("try_print_visible_def_path: def_id={:?}", def_id); - return Ok(( - if !span.is_dummy() { - self.print_def_path(def_id, &[])? - } else { - self.path_crate(cnum)? - }, - true, - )); - } + Some(&ExternCrate { src, dependency_of, span, .. }) => match (src, dependency_of) { + (ExternCrateSource::Extern(def_id), LOCAL_CRATE) => { + debug!("try_print_visible_def_path: def_id={:?}", def_id); + return Ok(( + if !span.is_dummy() { + self.print_def_path(def_id, &[])? + } else { + self.path_crate(cnum)? + }, + true, + )); + } + (ExternCrateSource::Path, LOCAL_CRATE) if self.tcx().sess.rust_2018() => { + debug!("try_print_visible_def_path: def_id={:?}", def_id); + return Ok((self.path_crate(cnum)?, true)); + } + _ => {} + }, None => { return Ok((self.path_crate(cnum)?, true)); } - _ => {} } } diff --git a/src/test/ui/issues/issue-56175.stderr b/src/test/ui/issues/issue-56175.stderr index dc5beb4271df7..c0799db7c1286 100644 --- a/src/test/ui/issues/issue-56175.stderr +++ b/src/test/ui/issues/issue-56175.stderr @@ -7,7 +7,7 @@ LL | reexported_trait::FooStruct.trait_method(); = help: items from traits can only be used if the trait is in scope help: the following trait is implemented but not in scope; perhaps add a `use` for it: | -LL | use reexported_trait::private::Trait; +LL | use reexported_trait::Trait; | error[E0599]: no method named `trait_method_b` found for struct `reexported_trait::FooStruct` in the current scope @@ -19,7 +19,7 @@ LL | reexported_trait::FooStruct.trait_method_b(); = help: items from traits can only be used if the trait is in scope help: the following trait is implemented but not in scope; perhaps add a `use` for it: | -LL | use reexported_trait::private::TraitB; +LL | use reexported_trait::TraitBRename; | error: aborting due to 2 previous errors From f77b6fe5711e42321b3e2b8b438e00e682f5411b Mon Sep 17 00:00:00 2001 From: Dan Aloni Date: Wed, 1 Jul 2020 20:05:51 +0300 Subject: [PATCH 08/22] Review fix --- src/librustc_middle/ty/print/pretty.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustc_middle/ty/print/pretty.rs b/src/librustc_middle/ty/print/pretty.rs index bbf9f550c03f4..f94a51feca3b8 100644 --- a/src/librustc_middle/ty/print/pretty.rs +++ b/src/librustc_middle/ty/print/pretty.rs @@ -294,7 +294,7 @@ pub trait PrettyPrinter<'tcx>: true, )); } - (ExternCrateSource::Path, LOCAL_CRATE) if self.tcx().sess.rust_2018() => { + (ExternCrateSource::Path, LOCAL_CRATE) => { debug!("try_print_visible_def_path: def_id={:?}", def_id); return Ok((self.path_crate(cnum)?, true)); } From 4030b7394845602eebb42f40c0e847be803af58f Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Thu, 2 Jul 2020 21:03:59 +0100 Subject: [PATCH 09/22] Use `Span`s to identify unreachable subpatterns in or-patterns --- src/librustc_mir_build/hair/pattern/_match.rs | 14 +++++++------- src/librustc_mir_build/hair/pattern/check_match.rs | 4 ++-- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/librustc_mir_build/hair/pattern/_match.rs b/src/librustc_mir_build/hair/pattern/_match.rs index 18b92bf29bf1b..b5a655e4218f1 100644 --- a/src/librustc_mir_build/hair/pattern/_match.rs +++ b/src/librustc_mir_build/hair/pattern/_match.rs @@ -1246,15 +1246,15 @@ impl<'p, 'tcx> Fields<'p, 'tcx> { } #[derive(Clone, Debug)] -crate enum Usefulness<'tcx, 'p> { +crate enum Usefulness<'tcx> { /// Carries a list of unreachable subpatterns. Used only in the presence of or-patterns. - Useful(Vec<&'p Pat<'tcx>>), + Useful(Vec), /// Carries a list of witnesses of non-exhaustiveness. UsefulWithWitness(Vec>), NotUseful, } -impl<'tcx, 'p> Usefulness<'tcx, 'p> { +impl<'tcx> Usefulness<'tcx> { fn new_useful(preference: WitnessPreference) -> Self { match preference { ConstructWitness => UsefulWithWitness(vec![Witness(vec![])]), @@ -1269,7 +1269,7 @@ impl<'tcx, 'p> Usefulness<'tcx, 'p> { } } - fn apply_constructor( + fn apply_constructor<'p>( self, cx: &MatchCheckCtxt<'p, 'tcx>, ctor: &Constructor<'tcx>, @@ -1828,7 +1828,7 @@ crate fn is_useful<'p, 'tcx>( hir_id: HirId, is_under_guard: bool, is_top_level: bool, -) -> Usefulness<'tcx, 'p> { +) -> Usefulness<'tcx> { let &Matrix(ref rows) = matrix; debug!("is_useful({:#?}, {:#?})", matrix, v); @@ -1861,7 +1861,7 @@ crate fn is_useful<'p, 'tcx>( any_is_useful = true; unreachable_pats.extend(pats); } - NotUseful => unreachable_pats.push(v.head()), + NotUseful => unreachable_pats.push(v.head().span), UsefulWithWitness(_) => { bug!("Encountered or-pat in `v` during exhaustiveness checking") } @@ -2014,7 +2014,7 @@ fn is_useful_specialized<'p, 'tcx>( witness_preference: WitnessPreference, hir_id: HirId, is_under_guard: bool, -) -> Usefulness<'tcx, 'p> { +) -> Usefulness<'tcx> { debug!("is_useful_specialized({:#?}, {:#?}, {:?})", v, ctor, ty); // We cache the result of `Fields::wildcards` because it is used a lot. diff --git a/src/librustc_mir_build/hair/pattern/check_match.rs b/src/librustc_mir_build/hair/pattern/check_match.rs index 6fc447a87f57a..6b8110fde6914 100644 --- a/src/librustc_mir_build/hair/pattern/check_match.rs +++ b/src/librustc_mir_build/hair/pattern/check_match.rs @@ -392,8 +392,8 @@ fn check_arms<'p, 'tcx>( } } Useful(unreachable_subpatterns) => { - for pat in unreachable_subpatterns { - unreachable_pattern(cx.tcx, pat.span, id, None); + for span in unreachable_subpatterns { + unreachable_pattern(cx.tcx, span, id, None); } } UsefulWithWitness(_) => bug!(), From 7a3081baaf81c1d924f3143479ec0c4a8f1e62b7 Mon Sep 17 00:00:00 2001 From: Bastian Kauschke Date: Fri, 3 Jul 2020 18:11:21 +0200 Subject: [PATCH 10/22] add `lazy_normalization_consts` feature gate --- src/librustc_feature/active.rs | 4 ++++ src/librustc_middle/ty/context.rs | 2 +- src/librustc_span/symbol.rs | 1 + .../{lazy-normalization => }/issue-71986.rs | 0 .../feature-gate-lazy_normalization_consts.rs | 10 +++++++++ ...ture-gate-lazy_normalization_consts.stderr | 21 +++++++++++++++++++ .../lazy_normalization_consts/issue-47814.rs | 16 ++++++++++++++ .../lazy_normalization_consts/issue-57739.rs | 17 +++++++++++++++ .../issue-57739.stderr | 19 +++++++++++++++++ .../lazy_normalization_consts/issue-73980.rs | 14 +++++++++++++ 10 files changed, 103 insertions(+), 1 deletion(-) rename src/test/ui/const-generics/{lazy-normalization => }/issue-71986.rs (100%) create mode 100644 src/test/ui/lazy_normalization_consts/feature-gate-lazy_normalization_consts.rs create mode 100644 src/test/ui/lazy_normalization_consts/feature-gate-lazy_normalization_consts.stderr create mode 100644 src/test/ui/lazy_normalization_consts/issue-47814.rs create mode 100644 src/test/ui/lazy_normalization_consts/issue-57739.rs create mode 100644 src/test/ui/lazy_normalization_consts/issue-57739.stderr create mode 100644 src/test/ui/lazy_normalization_consts/issue-73980.rs diff --git a/src/librustc_feature/active.rs b/src/librustc_feature/active.rs index 313744efb3fce..32481bf2b9574 100644 --- a/src/librustc_feature/active.rs +++ b/src/librustc_feature/active.rs @@ -570,6 +570,9 @@ declare_features! ( /// Allows capturing variables in scope using format_args! (active, format_args_capture, "1.46.0", Some(67984), None), + /// Lazily evaluate constants. This allows constants to depend on type parameters. + (active, lazy_normalization_consts, "1.46.0", Some(72219), None), + // ------------------------------------------------------------------------- // feature-group-end: actual feature gates // ------------------------------------------------------------------------- @@ -586,5 +589,6 @@ pub const INCOMPLETE_FEATURES: &[Symbol] = &[ sym::raw_dylib, sym::const_trait_impl, sym::const_trait_bound_opt_out, + sym::lazy_normalization_consts, sym::specialization, ]; diff --git a/src/librustc_middle/ty/context.rs b/src/librustc_middle/ty/context.rs index d942c07965a49..698bef4374545 100644 --- a/src/librustc_middle/ty/context.rs +++ b/src/librustc_middle/ty/context.rs @@ -1370,7 +1370,7 @@ impl<'tcx> TyCtxt<'tcx> { /// we still evaluate them eagerly. #[inline] pub fn lazy_normalization(self) -> bool { - self.features().const_generics + self.features().const_generics || self.features().lazy_normalization_consts } #[inline] diff --git a/src/librustc_span/symbol.rs b/src/librustc_span/symbol.rs index acc2a50abe88e..e35e1dd34134b 100644 --- a/src/librustc_span/symbol.rs +++ b/src/librustc_span/symbol.rs @@ -427,6 +427,7 @@ symbols! { label_break_value, lang, lang_items, + lazy_normalization_consts, lateout, let_chains, lhs, diff --git a/src/test/ui/const-generics/lazy-normalization/issue-71986.rs b/src/test/ui/const-generics/issue-71986.rs similarity index 100% rename from src/test/ui/const-generics/lazy-normalization/issue-71986.rs rename to src/test/ui/const-generics/issue-71986.rs diff --git a/src/test/ui/lazy_normalization_consts/feature-gate-lazy_normalization_consts.rs b/src/test/ui/lazy_normalization_consts/feature-gate-lazy_normalization_consts.rs new file mode 100644 index 0000000000000..44cb74815c6a0 --- /dev/null +++ b/src/test/ui/lazy_normalization_consts/feature-gate-lazy_normalization_consts.rs @@ -0,0 +1,10 @@ +pub const fn sof() -> usize { + 10 +} + +fn test() { + let _: [u8; sof::()]; + //~^ ERROR the size for values of type `T` +} + +fn main() {} diff --git a/src/test/ui/lazy_normalization_consts/feature-gate-lazy_normalization_consts.stderr b/src/test/ui/lazy_normalization_consts/feature-gate-lazy_normalization_consts.stderr new file mode 100644 index 0000000000000..6e19251c72800 --- /dev/null +++ b/src/test/ui/lazy_normalization_consts/feature-gate-lazy_normalization_consts.stderr @@ -0,0 +1,21 @@ +error[E0277]: the size for values of type `T` cannot be known at compilation time + --> $DIR/feature-gate-lazy_normalization_consts.rs:6:23 + | +LL | pub const fn sof() -> usize { + | - required by this bound in `sof` +... +LL | fn test() { + | - this type parameter needs to be `std::marker::Sized` +LL | let _: [u8; sof::()]; + | ^ doesn't have a size known at compile-time + | + = help: the trait `std::marker::Sized` is not implemented for `T` + = note: to learn more, visit +help: consider relaxing the implicit `Sized` restriction + | +LL | pub const fn sof() -> usize { + | ^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/lazy_normalization_consts/issue-47814.rs b/src/test/ui/lazy_normalization_consts/issue-47814.rs new file mode 100644 index 0000000000000..1fd0c45841b0d --- /dev/null +++ b/src/test/ui/lazy_normalization_consts/issue-47814.rs @@ -0,0 +1,16 @@ +// check-pass +#![feature(lazy_normalization_consts)] +#![allow(incomplete_features)] +pub struct ArpIPv4<'a> { + _s: &'a u8 +} + +impl<'a> ArpIPv4<'a> { + const LENGTH: usize = 20; + + pub fn to_buffer() -> [u8; Self::LENGTH] { + unimplemented!() + } +} + +fn main() {} diff --git a/src/test/ui/lazy_normalization_consts/issue-57739.rs b/src/test/ui/lazy_normalization_consts/issue-57739.rs new file mode 100644 index 0000000000000..4607f3e99b51f --- /dev/null +++ b/src/test/ui/lazy_normalization_consts/issue-57739.rs @@ -0,0 +1,17 @@ +#![feature(lazy_normalization_consts)] +//~^ WARN the feature `lazy_normalization_consts` is incomplete +trait ArraySizeTrait { + const SIZE: usize = 0; +} + +impl ArraySizeTrait for T { + const SIZE: usize = 1; +} + +struct SomeArray { + array: [u8; T::SIZE], + //~^ ERROR constant expression depends on a generic parameter + phantom: std::marker::PhantomData, +} + +fn main() {} diff --git a/src/test/ui/lazy_normalization_consts/issue-57739.stderr b/src/test/ui/lazy_normalization_consts/issue-57739.stderr new file mode 100644 index 0000000000000..1987f5890c041 --- /dev/null +++ b/src/test/ui/lazy_normalization_consts/issue-57739.stderr @@ -0,0 +1,19 @@ +warning: the feature `lazy_normalization_consts` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/issue-57739.rs:1:12 + | +LL | #![feature(lazy_normalization_consts)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `#[warn(incomplete_features)]` on by default + = note: see issue #72219 for more information + +error: constant expression depends on a generic parameter + --> $DIR/issue-57739.rs:12:5 + | +LL | array: [u8; T::SIZE], + | ^^^^^^^^^^^^^^^^^^^^ + | + = note: this may fail depending on what value the parameter takes + +error: aborting due to previous error; 1 warning emitted + diff --git a/src/test/ui/lazy_normalization_consts/issue-73980.rs b/src/test/ui/lazy_normalization_consts/issue-73980.rs new file mode 100644 index 0000000000000..339b22c0b423d --- /dev/null +++ b/src/test/ui/lazy_normalization_consts/issue-73980.rs @@ -0,0 +1,14 @@ +// check-pass +#![feature(lazy_normalization_consts)] +#![allow(incomplete_features)] + +pub struct X(P, Q); +pub struct L(T); + +impl L { + const S: usize = 1; +} + +impl X::S]> {} + +fn main() {} From 8900502a887d98a8f5a6b8774f1c756e89d4c29f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Mi=C4=85sko?= Date: Sat, 4 Jul 2020 00:00:00 +0000 Subject: [PATCH 11/22] Remove unnecessary release from Arc::try_unwrap The thread that recovers the unique access to Arc inner value (e.g., drop when ref-count strong reaches zero, successful try_unwrap), ensures that other operations on Arc inner value happened before by synchronizing with release operations performed when decrementing the reference counter. When try_unwrap succeeds, the current thread recovers the unique access to Arc inner value, so release is unnecessary. --- src/liballoc/sync.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/liballoc/sync.rs b/src/liballoc/sync.rs index ac3ce2255c89b..2d6a3917c764e 100644 --- a/src/liballoc/sync.rs +++ b/src/liballoc/sync.rs @@ -419,8 +419,7 @@ impl Arc { #[inline] #[stable(feature = "arc_unique", since = "1.4.0")] pub fn try_unwrap(this: Self) -> Result { - // See `drop` for why all these atomics are like this - if this.inner().strong.compare_exchange(1, 0, Release, Relaxed).is_err() { + if this.inner().strong.compare_exchange(1, 0, Relaxed, Relaxed).is_err() { return Err(this); } From 20d6941be7039eb7fad9a4f893792a77d65bc792 Mon Sep 17 00:00:00 2001 From: Bastian Kauschke Date: Sat, 4 Jul 2020 14:02:41 +0200 Subject: [PATCH 12/22] ConstCx to LocalDefId --- src/librustc_mir/const_eval/eval_queries.rs | 8 ++++---- src/librustc_mir/transform/check_consts/mod.rs | 4 ++-- .../check_consts/post_drop_elaboration.rs | 8 +------- .../transform/check_consts/qualifs.rs | 2 +- .../transform/check_consts/validation.rs | 18 +++++++++--------- src/librustc_mir/transform/mod.rs | 5 +++-- src/librustc_mir/transform/promote_consts.rs | 9 +++++---- 7 files changed, 25 insertions(+), 29 deletions(-) diff --git a/src/librustc_mir/const_eval/eval_queries.rs b/src/librustc_mir/const_eval/eval_queries.rs index d62300b3f5541..75067ffa4b338 100644 --- a/src/librustc_mir/const_eval/eval_queries.rs +++ b/src/librustc_mir/const_eval/eval_queries.rs @@ -334,9 +334,9 @@ pub fn const_eval_raw_provider<'tcx>( } v - } else if def_id.is_local() { + } else if let Some(def_id) = def_id.as_local() { // constant defined in this crate, we can figure out a lint level! - match tcx.def_kind(def_id) { + match tcx.def_kind(def_id.to_def_id()) { // constants never produce a hard error at the definition site. Anything else is // a backwards compatibility hazard (and will break old versions of winapi for // sure) @@ -346,7 +346,7 @@ pub fn const_eval_raw_provider<'tcx>( // validation thus preventing such a hard error from being a backwards // compatibility hazard DefKind::Const | DefKind::AssocConst => { - let hir_id = tcx.hir().as_local_hir_id(def_id.expect_local()); + let hir_id = tcx.hir().as_local_hir_id(def_id); err.report_as_lint( tcx.at(tcx.def_span(def_id)), "any use of this value will cause an error", @@ -369,7 +369,7 @@ pub fn const_eval_raw_provider<'tcx>( err.report_as_lint( tcx.at(span), "reaching this expression at runtime will panic or abort", - tcx.hir().as_local_hir_id(def_id.expect_local()), + tcx.hir().as_local_hir_id(def_id), Some(err.span), ) } diff --git a/src/librustc_mir/transform/check_consts/mod.rs b/src/librustc_mir/transform/check_consts/mod.rs index e4aa88e3c20a7..81c1b0b5bd49f 100644 --- a/src/librustc_mir/transform/check_consts/mod.rs +++ b/src/librustc_mir/transform/check_consts/mod.rs @@ -22,7 +22,7 @@ pub mod validation; pub struct ConstCx<'mir, 'tcx> { pub body: &'mir mir::Body<'tcx>, pub tcx: TyCtxt<'tcx>, - pub def_id: DefId, + pub def_id: LocalDefId, pub param_env: ty::ParamEnv<'tcx>, pub const_kind: Option, } @@ -40,7 +40,7 @@ impl ConstCx<'mir, 'tcx> { param_env: ty::ParamEnv<'tcx>, ) -> Self { let const_kind = tcx.hir().body_const_context(def_id); - ConstCx { body, tcx, def_id: def_id.to_def_id(), param_env, const_kind } + ConstCx { body, tcx, def_id: def_id, param_env, const_kind } } /// Returns the kind of const context this `Item` represents (`const`, `static`, etc.). diff --git a/src/librustc_mir/transform/check_consts/post_drop_elaboration.rs b/src/librustc_mir/transform/check_consts/post_drop_elaboration.rs index 1fd907f89fe18..33fe2758c28fe 100644 --- a/src/librustc_mir/transform/check_consts/post_drop_elaboration.rs +++ b/src/librustc_mir/transform/check_consts/post_drop_elaboration.rs @@ -29,13 +29,7 @@ pub fn check_live_drops(tcx: TyCtxt<'tcx>, def_id: LocalDefId, body: &mir::Body< return; } - let ccx = ConstCx { - body, - tcx, - def_id: def_id.to_def_id(), - const_kind, - param_env: tcx.param_env(def_id), - }; + let ccx = ConstCx { body, tcx, def_id: def_id, const_kind, param_env: tcx.param_env(def_id) }; let mut visitor = CheckLiveDrops { ccx: &ccx, qualifs: Qualifs::default() }; diff --git a/src/librustc_mir/transform/check_consts/qualifs.rs b/src/librustc_mir/transform/check_consts/qualifs.rs index e2893e81a2ce6..3dddd9c1c1766 100644 --- a/src/librustc_mir/transform/check_consts/qualifs.rs +++ b/src/librustc_mir/transform/check_consts/qualifs.rs @@ -126,7 +126,7 @@ impl Qualif for CustomEq { // because that component may be part of an enum variant (e.g., // `Option::::Some`), in which case some values of this type may be // structural-match (`Option::None`). - let id = cx.tcx.hir().local_def_id_to_hir_id(cx.def_id.as_local().unwrap()); + let id = cx.tcx.hir().local_def_id_to_hir_id(cx.def_id); traits::search_for_structural_match_violation(id, cx.body.span, cx.tcx, ty).is_some() } diff --git a/src/librustc_mir/transform/check_consts/validation.rs b/src/librustc_mir/transform/check_consts/validation.rs index f00fc96e5915a..5cb161ebcfb5e 100644 --- a/src/librustc_mir/transform/check_consts/validation.rs +++ b/src/librustc_mir/transform/check_consts/validation.rs @@ -56,7 +56,7 @@ impl Qualifs<'mir, 'tcx> { // without breaking stable code? MaybeMutBorrowedLocals::mut_borrows_only(tcx, &body, param_env) .unsound_ignore_borrow_on_drop() - .into_engine(tcx, &body, def_id) + .into_engine(tcx, &body, def_id.to_def_id()) .iterate_to_fixpoint() .into_results_cursor(&body) }); @@ -83,7 +83,7 @@ impl Qualifs<'mir, 'tcx> { let ConstCx { tcx, body, def_id, .. } = *ccx; FlowSensitiveAnalysis::new(NeedsDrop, ccx) - .into_engine(tcx, &body, def_id) + .into_engine(tcx, &body, def_id.to_def_id()) .iterate_to_fixpoint() .into_results_cursor(&body) }); @@ -110,7 +110,7 @@ impl Qualifs<'mir, 'tcx> { let ConstCx { tcx, body, def_id, .. } = *ccx; FlowSensitiveAnalysis::new(HasMutInterior, ccx) - .into_engine(tcx, &body, def_id) + .into_engine(tcx, &body, def_id.to_def_id()) .iterate_to_fixpoint() .into_results_cursor(&body) }); @@ -153,7 +153,7 @@ impl Qualifs<'mir, 'tcx> { hir::ConstContext::Const | hir::ConstContext::Static(_) => { let mut cursor = FlowSensitiveAnalysis::new(CustomEq, ccx) - .into_engine(ccx.tcx, &ccx.body, ccx.def_id) + .into_engine(ccx.tcx, &ccx.body, ccx.def_id.to_def_id()) .iterate_to_fixpoint() .into_results_cursor(&ccx.body); @@ -195,13 +195,13 @@ impl Validator<'mir, 'tcx> { let ConstCx { tcx, body, def_id, const_kind, .. } = *self.ccx; let use_min_const_fn_checks = (const_kind == Some(hir::ConstContext::ConstFn) - && crate::const_eval::is_min_const_fn(tcx, def_id)) + && crate::const_eval::is_min_const_fn(tcx, def_id.to_def_id())) && !tcx.sess.opts.debugging_opts.unleash_the_miri_inside_of_you; if use_min_const_fn_checks { // Enforce `min_const_fn` for stable `const fn`s. use crate::transform::qualify_min_const_fn::is_min_const_fn; - if let Err((span, err)) = is_min_const_fn(tcx, def_id, &body) { + if let Err((span, err)) = is_min_const_fn(tcx, def_id.to_def_id(), &body) { error_min_const_fn_violation(tcx, span, err); return; } @@ -212,10 +212,10 @@ impl Validator<'mir, 'tcx> { // Ensure that the end result is `Sync` in a non-thread local `static`. let should_check_for_sync = const_kind == Some(hir::ConstContext::Static(hir::Mutability::Not)) - && !tcx.is_thread_local_static(def_id); + && !tcx.is_thread_local_static(def_id.to_def_id()); if should_check_for_sync { - let hir_id = tcx.hir().as_local_hir_id(def_id.expect_local()); + let hir_id = tcx.hir().as_local_hir_id(def_id); check_return_ty_is_sync(tcx, &body, hir_id); } } @@ -535,7 +535,7 @@ impl Visitor<'tcx> for Validator<'mir, 'tcx> { // `#[allow_internal_unstable]`. use crate::transform::qualify_min_const_fn::lib_feature_allowed; if !self.span.allows_unstable(feature) - && !lib_feature_allowed(self.tcx, self.def_id, feature) + && !lib_feature_allowed(self.tcx, self.def_id.to_def_id(), feature) { self.check_op(ops::FnCallUnstable(def_id, feature)); } diff --git a/src/librustc_mir/transform/mod.rs b/src/librustc_mir/transform/mod.rs index 8ca240d2c7da7..14c3093e1e9a1 100644 --- a/src/librustc_mir/transform/mod.rs +++ b/src/librustc_mir/transform/mod.rs @@ -203,7 +203,8 @@ pub fn run_passes( } fn mir_const_qualif(tcx: TyCtxt<'_>, def_id: DefId) -> ConstQualifs { - let const_kind = tcx.hir().body_const_context(def_id.expect_local()); + let def_id = def_id.expect_local(); + let const_kind = tcx.hir().body_const_context(def_id); // No need to const-check a non-const `fn`. if const_kind.is_none() { @@ -214,7 +215,7 @@ fn mir_const_qualif(tcx: TyCtxt<'_>, def_id: DefId) -> ConstQualifs { // cannot yet be stolen), because `mir_validated()`, which steals // from `mir_const(), forces this query to execute before // performing the steal. - let body = &tcx.mir_const(def_id).borrow(); + let body = &tcx.mir_const(def_id.to_def_id()).borrow(); if body.return_ty().references_error() { tcx.sess.delay_span_bug(body.span, "mir_const_qualif: MIR had errors"); diff --git a/src/librustc_mir/transform/promote_consts.rs b/src/librustc_mir/transform/promote_consts.rs index bd7ebaa01f81b..5aa67227994d9 100644 --- a/src/librustc_mir/transform/promote_consts.rs +++ b/src/librustc_mir/transform/promote_consts.rs @@ -60,15 +60,16 @@ impl<'tcx> MirPass<'tcx> for PromoteTemps<'tcx> { return; } - let def_id = src.def_id(); + let def_id = src.def_id().expect_local(); let mut rpo = traversal::reverse_postorder(body); - let ccx = ConstCx::new(tcx, def_id.expect_local(), body); + let ccx = ConstCx::new(tcx, def_id, body); let (temps, all_candidates) = collect_temps_and_candidates(&ccx, &mut rpo); let promotable_candidates = validate_candidates(&ccx, &temps, &all_candidates); - let promoted = promote_candidates(def_id, body, tcx, temps, promotable_candidates); + let promoted = + promote_candidates(def_id.to_def_id(), body, tcx, temps, promotable_candidates); self.promoted_fragments.set(promoted); } } @@ -724,7 +725,7 @@ impl<'tcx> Validator<'_, 'tcx> { ty::FnDef(def_id, _) => { is_const_fn(self.tcx, def_id) || is_unstable_const_fn(self.tcx, def_id).is_some() - || is_lang_panic_fn(self.tcx, self.def_id) + || is_lang_panic_fn(self.tcx, self.def_id.to_def_id()) } _ => false, }; From dbcabc248c0e035f916a5f4bb64b714640a5c338 Mon Sep 17 00:00:00 2001 From: Bastian Kauschke Date: Sat, 4 Jul 2020 14:14:41 +0200 Subject: [PATCH 13/22] instantiate_opaque_types LocalDefId --- .../borrow_check/type_check/input_output.rs | 4 ++-- src/librustc_mir/borrow_check/type_check/mod.rs | 8 ++++---- src/librustc_trait_selection/opaque_types.rs | 17 ++++++----------- src/librustc_typeck/check/mod.rs | 6 +++--- 4 files changed, 15 insertions(+), 20 deletions(-) diff --git a/src/librustc_mir/borrow_check/type_check/input_output.rs b/src/librustc_mir/borrow_check/type_check/input_output.rs index edd2dc3c2de55..8cebd3679345f 100644 --- a/src/librustc_mir/borrow_check/type_check/input_output.rs +++ b/src/librustc_mir/borrow_check/type_check/input_output.rs @@ -122,7 +122,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { if let Err(terr) = self.eq_opaque_type_and_type( mir_output_ty, normalized_output_ty, - self.mir_def_id.to_def_id(), + self.mir_def_id, Locations::All(output_span), ConstraintCategory::BoringNoLocation, ) { @@ -145,7 +145,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { if let Err(err) = self.eq_opaque_type_and_type( mir_output_ty, user_provided_output_ty, - self.mir_def_id.to_def_id(), + self.mir_def_id, Locations::All(output_span), ConstraintCategory::BoringNoLocation, ) { diff --git a/src/librustc_mir/borrow_check/type_check/mod.rs b/src/librustc_mir/borrow_check/type_check/mod.rs index 0e35cafb9f3e9..3532b6de003ba 100644 --- a/src/librustc_mir/borrow_check/type_check/mod.rs +++ b/src/librustc_mir/borrow_check/type_check/mod.rs @@ -1144,7 +1144,8 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { // When you have `let x: impl Foo = ...` in a closure, // the resulting inferend values are stored with the // def-id of the base function. - let parent_def_id = self.tcx().closure_base_def_id(self.mir_def_id.to_def_id()); + let parent_def_id = + self.tcx().closure_base_def_id(self.mir_def_id.to_def_id()).expect_local(); return self.eq_opaque_type_and_type(sub, sup, parent_def_id, locations, category); } else { return Err(terr); @@ -1208,7 +1209,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { &mut self, revealed_ty: Ty<'tcx>, anon_ty: Ty<'tcx>, - anon_owner_def_id: DefId, + anon_owner_def_id: LocalDefId, locations: Locations, category: ConstraintCategory, ) -> Fallible<()> { @@ -1238,8 +1239,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { let tcx = infcx.tcx; let param_env = self.param_env; let body = self.body; - let concrete_opaque_types = - &tcx.typeck_tables_of(anon_owner_def_id.expect_local()).concrete_opaque_types; + let concrete_opaque_types = &tcx.typeck_tables_of(anon_owner_def_id).concrete_opaque_types; let mut opaque_type_values = Vec::new(); debug!("eq_opaque_type_and_type: mir_def_id={:?}", self.mir_def_id); diff --git a/src/librustc_trait_selection/opaque_types.rs b/src/librustc_trait_selection/opaque_types.rs index ce478de7c755c..b60531833bd41 100644 --- a/src/librustc_trait_selection/opaque_types.rs +++ b/src/librustc_trait_selection/opaque_types.rs @@ -108,7 +108,7 @@ pub enum GenerateMemberConstraints { pub trait InferCtxtExt<'tcx> { fn instantiate_opaque_types>( &self, - parent_def_id: DefId, + parent_def_id: LocalDefId, body_id: hir::HirId, param_env: ty::ParamEnv<'tcx>, value: &T, @@ -184,7 +184,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { /// - `value_span` -- the span where the value came from, used in error reporting fn instantiate_opaque_types>( &self, - parent_def_id: DefId, + parent_def_id: LocalDefId, body_id: hir::HirId, param_env: ty::ParamEnv<'tcx>, value: &T, @@ -986,7 +986,7 @@ impl TypeFolder<'tcx> for ReverseMapper<'tcx> { struct Instantiator<'a, 'tcx> { infcx: &'a InferCtxt<'a, 'tcx>, - parent_def_id: DefId, + parent_def_id: LocalDefId, body_id: hir::HirId, param_env: ty::ParamEnv<'tcx>, value_span: Span, @@ -1043,8 +1043,7 @@ impl<'a, 'tcx> Instantiator<'a, 'tcx> { let parent_def_id = self.parent_def_id; let def_scope_default = || { let opaque_parent_hir_id = tcx.hir().get_parent_item(opaque_hir_id); - parent_def_id - == tcx.hir().local_def_id(opaque_parent_hir_id).to_def_id() + parent_def_id == tcx.hir().local_def_id(opaque_parent_hir_id) }; let (in_definition_scope, origin) = match tcx.hir().find(opaque_hir_id) { Some(Node::Item(item)) => match item.kind { @@ -1053,18 +1052,14 @@ impl<'a, 'tcx> Instantiator<'a, 'tcx> { impl_trait_fn: Some(parent), origin, .. - }) => (parent == self.parent_def_id, origin), + }) => (parent == self.parent_def_id.to_def_id(), origin), // Named `type Foo = impl Bar;` hir::ItemKind::OpaqueTy(hir::OpaqueTy { impl_trait_fn: None, origin, .. }) => ( - may_define_opaque_type( - tcx, - self.parent_def_id.expect_local(), - opaque_hir_id, - ), + may_define_opaque_type(tcx, self.parent_def_id, opaque_hir_id), origin, ), _ => (def_scope_default(), hir::OpaqueTyOrigin::Misc), diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 58fd0f989c678..e564b01b11721 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -1321,8 +1321,8 @@ fn check_fn<'a, 'tcx>( fcx.resume_yield_tys = Some((resume_ty, yield_ty)); } - let outer_def_id = tcx.closure_base_def_id(hir.local_def_id(fn_id).to_def_id()); - let outer_hir_id = hir.as_local_hir_id(outer_def_id.expect_local()); + let outer_def_id = tcx.closure_base_def_id(hir.local_def_id(fn_id).to_def_id()).expect_local(); + let outer_hir_id = hir.as_local_hir_id(outer_def_id); GatherLocalsVisitor { fcx: &fcx, parent_id: outer_hir_id }.visit_body(body); // C-variadic fns also have a `VaList` input that's not listed in `fn_sig` @@ -3427,7 +3427,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let (value, opaque_type_map) = self.register_infer_ok_obligations(self.instantiate_opaque_types( - parent_def_id.to_def_id(), + parent_def_id, self.body_id, self.param_env, value, From f5305c3d16fb8221463ef604a1ea5ac11506ba6d Mon Sep 17 00:00:00 2001 From: Bastian Kauschke Date: Sat, 4 Jul 2020 16:20:27 +0200 Subject: [PATCH 14/22] nit Co-authored-by: varkor --- .../transform/check_consts/post_drop_elaboration.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustc_mir/transform/check_consts/post_drop_elaboration.rs b/src/librustc_mir/transform/check_consts/post_drop_elaboration.rs index 33fe2758c28fe..55075b3ab5e99 100644 --- a/src/librustc_mir/transform/check_consts/post_drop_elaboration.rs +++ b/src/librustc_mir/transform/check_consts/post_drop_elaboration.rs @@ -29,7 +29,7 @@ pub fn check_live_drops(tcx: TyCtxt<'tcx>, def_id: LocalDefId, body: &mir::Body< return; } - let ccx = ConstCx { body, tcx, def_id: def_id, const_kind, param_env: tcx.param_env(def_id) }; + let ccx = ConstCx { body, tcx, def_id, const_kind, param_env: tcx.param_env(def_id) }; let mut visitor = CheckLiveDrops { ccx: &ccx, qualifs: Qualifs::default() }; From 66fb778acc512213b8883101f275a7fa44c9b75d Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Sat, 27 Jun 2020 11:47:18 +0200 Subject: [PATCH 15/22] Make `rustc_peek` a safe intrinsic --- src/librustc_typeck/check/intrinsic.rs | 2 +- src/test/ui/mir-dataflow/def-inits-1.rs | 18 +++++------ src/test/ui/mir-dataflow/def-inits-1.stderr | 24 +++++++-------- .../mir-dataflow/indirect-mutation-offset.rs | 2 +- .../indirect-mutation-offset.stderr | 6 ++-- src/test/ui/mir-dataflow/inits-1.rs | 18 +++++------ src/test/ui/mir-dataflow/inits-1.stderr | 18 +++++------ src/test/ui/mir-dataflow/liveness-ptr.rs | 6 ++-- src/test/ui/mir-dataflow/liveness-ptr.stderr | 6 ++-- src/test/ui/mir-dataflow/uninits-1.rs | 18 +++++------ src/test/ui/mir-dataflow/uninits-1.stderr | 30 +++++++++---------- src/test/ui/mir-dataflow/uninits-2.rs | 4 +-- src/test/ui/mir-dataflow/uninits-2.stderr | 6 ++-- 13 files changed, 79 insertions(+), 79 deletions(-) diff --git a/src/librustc_typeck/check/intrinsic.rs b/src/librustc_typeck/check/intrinsic.rs index 6205088adadb7..da5b9f18c0719 100644 --- a/src/librustc_typeck/check/intrinsic.rs +++ b/src/librustc_typeck/check/intrinsic.rs @@ -75,7 +75,7 @@ pub fn intrinsic_operation_unsafety(intrinsic: &str) -> hir::Unsafety { | "saturating_sub" | "rotate_left" | "rotate_right" | "ctpop" | "ctlz" | "cttz" | "bswap" | "bitreverse" | "discriminant_value" | "type_id" | "likely" | "unlikely" | "ptr_guaranteed_eq" | "ptr_guaranteed_ne" | "minnumf32" | "minnumf64" | "maxnumf32" - | "maxnumf64" | "type_name" | "variant_count" => hir::Unsafety::Normal, + | "rustc_peek" | "maxnumf64" | "type_name" | "variant_count" => hir::Unsafety::Normal, _ => hir::Unsafety::Unsafe, } } diff --git a/src/test/ui/mir-dataflow/def-inits-1.rs b/src/test/ui/mir-dataflow/def-inits-1.rs index 91d41e9b5794e..30460824a1678 100644 --- a/src/test/ui/mir-dataflow/def-inits-1.rs +++ b/src/test/ui/mir-dataflow/def-inits-1.rs @@ -11,13 +11,13 @@ struct S(i32); fn foo(test: bool, x: &mut S, y: S, mut z: S) -> S { let ret; // `ret` starts off uninitialized - unsafe { rustc_peek(&ret); } //~ ERROR rustc_peek: bit not set + rustc_peek(&ret); //~ ERROR rustc_peek: bit not set // All function formal parameters start off initialized. - unsafe { rustc_peek(&x) }; - unsafe { rustc_peek(&y) }; - unsafe { rustc_peek(&z) }; + rustc_peek(&x); + rustc_peek(&y); + rustc_peek(&z); ret = if test { ::std::mem::replace(x, y) @@ -27,21 +27,21 @@ fn foo(test: bool, x: &mut S, y: S, mut z: S) -> S { }; // `z` may be uninitialized here. - unsafe { rustc_peek(&z); } //~ ERROR rustc_peek: bit not set + rustc_peek(&z); //~ ERROR rustc_peek: bit not set // `y` is definitely uninitialized here. - unsafe { rustc_peek(&y); } //~ ERROR rustc_peek: bit not set + rustc_peek(&y); //~ ERROR rustc_peek: bit not set // `x` is still (definitely) initialized (replace above is a reborrow). - unsafe { rustc_peek(&x); } + rustc_peek(&x); ::std::mem::drop(x); // `x` is *definitely* uninitialized here - unsafe { rustc_peek(&x); } //~ ERROR rustc_peek: bit not set + rustc_peek(&x); //~ ERROR rustc_peek: bit not set // `ret` is now definitely initialized (via `if` above). - unsafe { rustc_peek(&ret); } + rustc_peek(&ret); ret } diff --git a/src/test/ui/mir-dataflow/def-inits-1.stderr b/src/test/ui/mir-dataflow/def-inits-1.stderr index 48d8450489488..e2bddb54d9ba8 100644 --- a/src/test/ui/mir-dataflow/def-inits-1.stderr +++ b/src/test/ui/mir-dataflow/def-inits-1.stderr @@ -1,26 +1,26 @@ error: rustc_peek: bit not set - --> $DIR/def-inits-1.rs:14:14 + --> $DIR/def-inits-1.rs:14:5 | -LL | unsafe { rustc_peek(&ret); } - | ^^^^^^^^^^^^^^^^ +LL | rustc_peek(&ret); + | ^^^^^^^^^^^^^^^^ error: rustc_peek: bit not set - --> $DIR/def-inits-1.rs:30:14 + --> $DIR/def-inits-1.rs:30:5 | -LL | unsafe { rustc_peek(&z); } - | ^^^^^^^^^^^^^^ +LL | rustc_peek(&z); + | ^^^^^^^^^^^^^^ error: rustc_peek: bit not set - --> $DIR/def-inits-1.rs:33:14 + --> $DIR/def-inits-1.rs:33:5 | -LL | unsafe { rustc_peek(&y); } - | ^^^^^^^^^^^^^^ +LL | rustc_peek(&y); + | ^^^^^^^^^^^^^^ error: rustc_peek: bit not set - --> $DIR/def-inits-1.rs:41:14 + --> $DIR/def-inits-1.rs:41:5 | -LL | unsafe { rustc_peek(&x); } - | ^^^^^^^^^^^^^^ +LL | rustc_peek(&x); + | ^^^^^^^^^^^^^^ error: stop_after_dataflow ended compilation diff --git a/src/test/ui/mir-dataflow/indirect-mutation-offset.rs b/src/test/ui/mir-dataflow/indirect-mutation-offset.rs index caa307e269fe7..374a9f75a134b 100644 --- a/src/test/ui/mir-dataflow/indirect-mutation-offset.rs +++ b/src/test/ui/mir-dataflow/indirect-mutation-offset.rs @@ -38,7 +38,7 @@ const BOO: i32 = { *rmut_cell = 42; // Mutates `x` indirectly even though `x` is not marked indirectly mutable!!! let val = *rmut_cell; - unsafe { rustc_peek(x) }; //~ ERROR rustc_peek: bit not set + rustc_peek(x); //~ ERROR rustc_peek: bit not set val }; diff --git a/src/test/ui/mir-dataflow/indirect-mutation-offset.stderr b/src/test/ui/mir-dataflow/indirect-mutation-offset.stderr index 8d3548ececdd9..1d5287c15ab79 100644 --- a/src/test/ui/mir-dataflow/indirect-mutation-offset.stderr +++ b/src/test/ui/mir-dataflow/indirect-mutation-offset.stderr @@ -1,8 +1,8 @@ error: rustc_peek: bit not set - --> $DIR/indirect-mutation-offset.rs:41:14 + --> $DIR/indirect-mutation-offset.rs:41:5 | -LL | unsafe { rustc_peek(x) }; - | ^^^^^^^^^^^^^ +LL | rustc_peek(x); + | ^^^^^^^^^^^^^ error: stop_after_dataflow ended compilation diff --git a/src/test/ui/mir-dataflow/inits-1.rs b/src/test/ui/mir-dataflow/inits-1.rs index 4a4786a2a7378..8fb1d4bc736d6 100644 --- a/src/test/ui/mir-dataflow/inits-1.rs +++ b/src/test/ui/mir-dataflow/inits-1.rs @@ -11,13 +11,13 @@ struct S(i32); fn foo(test: bool, x: &mut S, y: S, mut z: S) -> S { let ret; // `ret` starts off uninitialized, so we get an error report here. - unsafe { rustc_peek(&ret); } //~ ERROR rustc_peek: bit not set + rustc_peek(&ret); //~ ERROR rustc_peek: bit not set // All function formal parameters start off initialized. - unsafe { rustc_peek(&x) }; - unsafe { rustc_peek(&y) }; - unsafe { rustc_peek(&z) }; + rustc_peek(&x); + rustc_peek(&y); + rustc_peek(&z); ret = if test { ::std::mem::replace(x, y) @@ -28,21 +28,21 @@ fn foo(test: bool, x: &mut S, y: S, mut z: S) -> S { // `z` may be initialized here. - unsafe { rustc_peek(&z); } + rustc_peek(&z); // `y` is definitely uninitialized here. - unsafe { rustc_peek(&y); } //~ ERROR rustc_peek: bit not set + rustc_peek(&y); //~ ERROR rustc_peek: bit not set // `x` is still (definitely) initialized (replace above is a reborrow). - unsafe { rustc_peek(&x); } + rustc_peek(&x); ::std::mem::drop(x); // `x` is *definitely* uninitialized here - unsafe { rustc_peek(&x); } //~ ERROR rustc_peek: bit not set + rustc_peek(&x); //~ ERROR rustc_peek: bit not set // `ret` is now definitely initialized (via `if` above). - unsafe { rustc_peek(&ret); } + rustc_peek(&ret); ret } diff --git a/src/test/ui/mir-dataflow/inits-1.stderr b/src/test/ui/mir-dataflow/inits-1.stderr index 23d0679cb1ac1..7a00a70af6f84 100644 --- a/src/test/ui/mir-dataflow/inits-1.stderr +++ b/src/test/ui/mir-dataflow/inits-1.stderr @@ -1,20 +1,20 @@ error: rustc_peek: bit not set - --> $DIR/inits-1.rs:14:14 + --> $DIR/inits-1.rs:14:5 | -LL | unsafe { rustc_peek(&ret); } - | ^^^^^^^^^^^^^^^^ +LL | rustc_peek(&ret); + | ^^^^^^^^^^^^^^^^ error: rustc_peek: bit not set - --> $DIR/inits-1.rs:34:14 + --> $DIR/inits-1.rs:34:5 | -LL | unsafe { rustc_peek(&y); } - | ^^^^^^^^^^^^^^ +LL | rustc_peek(&y); + | ^^^^^^^^^^^^^^ error: rustc_peek: bit not set - --> $DIR/inits-1.rs:42:14 + --> $DIR/inits-1.rs:42:5 | -LL | unsafe { rustc_peek(&x); } - | ^^^^^^^^^^^^^^ +LL | rustc_peek(&x); + | ^^^^^^^^^^^^^^ error: stop_after_dataflow ended compilation diff --git a/src/test/ui/mir-dataflow/liveness-ptr.rs b/src/test/ui/mir-dataflow/liveness-ptr.rs index 34097d7526a6e..786da523a3391 100644 --- a/src/test/ui/mir-dataflow/liveness-ptr.rs +++ b/src/test/ui/mir-dataflow/liveness-ptr.rs @@ -10,17 +10,17 @@ fn foo() -> i32 { x = 0; // `x` is live here since it is used in the next statement... - unsafe { rustc_peek(x); } + rustc_peek(x); p = &x; // ... but not here, even while it can be accessed through `p`. - unsafe { rustc_peek(x); } //~ ERROR rustc_peek: bit not set + rustc_peek(x); //~ ERROR rustc_peek: bit not set let tmp = unsafe { *p }; x = tmp + 1; - unsafe { rustc_peek(x); } + rustc_peek(x); x } diff --git a/src/test/ui/mir-dataflow/liveness-ptr.stderr b/src/test/ui/mir-dataflow/liveness-ptr.stderr index 3397d0c5a121d..858cdbac3d312 100644 --- a/src/test/ui/mir-dataflow/liveness-ptr.stderr +++ b/src/test/ui/mir-dataflow/liveness-ptr.stderr @@ -1,8 +1,8 @@ error: rustc_peek: bit not set - --> $DIR/liveness-ptr.rs:18:14 + --> $DIR/liveness-ptr.rs:18:5 | -LL | unsafe { rustc_peek(x); } - | ^^^^^^^^^^^^^ +LL | rustc_peek(x); + | ^^^^^^^^^^^^^ error: stop_after_dataflow ended compilation diff --git a/src/test/ui/mir-dataflow/uninits-1.rs b/src/test/ui/mir-dataflow/uninits-1.rs index 66b3f458a5159..c2b4284a7b4f8 100644 --- a/src/test/ui/mir-dataflow/uninits-1.rs +++ b/src/test/ui/mir-dataflow/uninits-1.rs @@ -11,13 +11,13 @@ struct S(i32); fn foo(test: bool, x: &mut S, y: S, mut z: S) -> S { let ret; // `ret` starts off uninitialized - unsafe { rustc_peek(&ret); } + rustc_peek(&ret); // All function formal parameters start off initialized. - unsafe { rustc_peek(&x) }; //~ ERROR rustc_peek: bit not set - unsafe { rustc_peek(&y) }; //~ ERROR rustc_peek: bit not set - unsafe { rustc_peek(&z) }; //~ ERROR rustc_peek: bit not set + rustc_peek(&x); //~ ERROR rustc_peek: bit not set + rustc_peek(&y); //~ ERROR rustc_peek: bit not set + rustc_peek(&z); //~ ERROR rustc_peek: bit not set ret = if test { ::std::mem::replace(x, y) @@ -27,21 +27,21 @@ fn foo(test: bool, x: &mut S, y: S, mut z: S) -> S { }; // `z` may be uninitialized here. - unsafe { rustc_peek(&z); } + rustc_peek(&z); // `y` is definitely uninitialized here. - unsafe { rustc_peek(&y); } + rustc_peek(&y); // `x` is still (definitely) initialized (replace above is a reborrow). - unsafe { rustc_peek(&x); } //~ ERROR rustc_peek: bit not set + rustc_peek(&x); //~ ERROR rustc_peek: bit not set ::std::mem::drop(x); // `x` is *definitely* uninitialized here - unsafe { rustc_peek(&x); } + rustc_peek(&x); // `ret` is now definitely initialized (via `if` above). - unsafe { rustc_peek(&ret); } //~ ERROR rustc_peek: bit not set + rustc_peek(&ret); //~ ERROR rustc_peek: bit not set ret } diff --git a/src/test/ui/mir-dataflow/uninits-1.stderr b/src/test/ui/mir-dataflow/uninits-1.stderr index 5f6dbde212d0a..c52f5ac7bd9b6 100644 --- a/src/test/ui/mir-dataflow/uninits-1.stderr +++ b/src/test/ui/mir-dataflow/uninits-1.stderr @@ -1,32 +1,32 @@ error: rustc_peek: bit not set - --> $DIR/uninits-1.rs:18:14 + --> $DIR/uninits-1.rs:18:5 | -LL | unsafe { rustc_peek(&x) }; - | ^^^^^^^^^^^^^^ +LL | rustc_peek(&x); + | ^^^^^^^^^^^^^^ error: rustc_peek: bit not set - --> $DIR/uninits-1.rs:19:14 + --> $DIR/uninits-1.rs:19:5 | -LL | unsafe { rustc_peek(&y) }; - | ^^^^^^^^^^^^^^ +LL | rustc_peek(&y); + | ^^^^^^^^^^^^^^ error: rustc_peek: bit not set - --> $DIR/uninits-1.rs:20:14 + --> $DIR/uninits-1.rs:20:5 | -LL | unsafe { rustc_peek(&z) }; - | ^^^^^^^^^^^^^^ +LL | rustc_peek(&z); + | ^^^^^^^^^^^^^^ error: rustc_peek: bit not set - --> $DIR/uninits-1.rs:36:14 + --> $DIR/uninits-1.rs:36:5 | -LL | unsafe { rustc_peek(&x); } - | ^^^^^^^^^^^^^^ +LL | rustc_peek(&x); + | ^^^^^^^^^^^^^^ error: rustc_peek: bit not set - --> $DIR/uninits-1.rs:44:14 + --> $DIR/uninits-1.rs:44:5 | -LL | unsafe { rustc_peek(&ret); } - | ^^^^^^^^^^^^^^^^ +LL | rustc_peek(&ret); + | ^^^^^^^^^^^^^^^^ error: stop_after_dataflow ended compilation diff --git a/src/test/ui/mir-dataflow/uninits-2.rs b/src/test/ui/mir-dataflow/uninits-2.rs index 2ccf1c7f9d6c6..c584ee74afb48 100644 --- a/src/test/ui/mir-dataflow/uninits-2.rs +++ b/src/test/ui/mir-dataflow/uninits-2.rs @@ -11,12 +11,12 @@ struct S(i32); fn foo(x: &mut S) { // `x` is initialized here, so maybe-uninit bit is 0. - unsafe { rustc_peek(&x) }; //~ ERROR rustc_peek: bit not set + rustc_peek(&x); //~ ERROR rustc_peek: bit not set ::std::mem::drop(x); // `x` definitely uninitialized here, so maybe-uninit bit is 1. - unsafe { rustc_peek(&x) }; + rustc_peek(&x); } fn main() { foo(&mut S(13)); diff --git a/src/test/ui/mir-dataflow/uninits-2.stderr b/src/test/ui/mir-dataflow/uninits-2.stderr index dcb61371994db..0ef954e35a4d8 100644 --- a/src/test/ui/mir-dataflow/uninits-2.stderr +++ b/src/test/ui/mir-dataflow/uninits-2.stderr @@ -1,8 +1,8 @@ error: rustc_peek: bit not set - --> $DIR/uninits-2.rs:14:14 + --> $DIR/uninits-2.rs:14:5 | -LL | unsafe { rustc_peek(&x) }; - | ^^^^^^^^^^^^^^ +LL | rustc_peek(&x); + | ^^^^^^^^^^^^^^ error: stop_after_dataflow ended compilation From 394b8cdfb7734a6dcb10b392c5b83e1b3d9521d3 Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Sun, 28 Jun 2020 12:58:20 +0200 Subject: [PATCH 16/22] Match on `Symbol` instead of `&str` for type-checking intrinsics. --- src/librustc_span/symbol.rs | 79 ++++++++ src/librustc_typeck/check/intrinsic.rs | 263 ++++++++++++++----------- src/librustc_typeck/collect.rs | 2 +- 3 files changed, 229 insertions(+), 115 deletions(-) diff --git a/src/librustc_span/symbol.rs b/src/librustc_span/symbol.rs index acc2a50abe88e..c34da8b1cf326 100644 --- a/src/librustc_span/symbol.rs +++ b/src/librustc_span/symbol.rs @@ -152,10 +152,14 @@ symbols! { arm_target_feature, asm, assert, + assert_inhabited, + assert_uninit_valid, + assert_zero_valid, associated_consts, associated_type_bounds, associated_type_defaults, associated_types, + assume, assume_init, async_await, async_closure, @@ -181,11 +185,14 @@ symbols! { box_patterns, box_syntax, braced_empty_structs, + breakpoint, bswap, bitreverse, C, caller_location, cdylib, + ceilf32, + ceilf64, cfg, cfg_accessible, cfg_attr, @@ -239,8 +246,14 @@ symbols! { convert, Copy, copy_closures, + copy, + copy_nonoverlapping, + copysignf32, + copysignf64, core, core_intrinsics, + cosf32, + cosf64, count_code_region, coverage_counter_add, coverage_counter_subtract, @@ -299,6 +312,7 @@ symbols! { dropck_eyepatch, dropck_parametricity, drop_types_in_const, + drop_in_place, dylib, dyn_trait, eh_personality, @@ -311,11 +325,16 @@ symbols! { Eq, Equal, enclosing_scope, + exact_div, except, exclusive_range_pattern, exhaustive_integer_patterns, exhaustive_patterns, existential_type, + expf32, + expf64, + exp2f32, + exp2f64, expected, export_name, expr, @@ -329,6 +348,10 @@ symbols! { f16c_target_feature, f32, f64, + fadd_fast, + fabsf32, + fabsf64, + fdiv_fast, feature, ffi_const, ffi_pure, @@ -336,13 +359,21 @@ symbols! { field, field_init_shorthand, file, + float_to_int_unchecked, + floorf64, + floorf32, + fmaf32, + fmaf64, fmt, fmt_internals, + fmul_fast, fn_must_use, forbid, + forget, format_args, format_args_nl, format_args_capture, + frem_fast, from, From, from_desugaring, @@ -352,6 +383,7 @@ symbols! { from_ok, from_usize, from_trait, + fsub_fast, fundamental, future, Future, @@ -448,6 +480,12 @@ symbols! { llvm_asm, local_inner_macros, log_syntax, + logf32, + logf64, + log10f32, + log10f64, + log2f32, + log2f64, loop_break_value, macro_at_most_once_rep, macro_escape, @@ -475,10 +513,16 @@ symbols! { message, meta, min_align_of, + min_align_of_val, min_const_fn, min_const_unsafe_fn, min_specialization, + minnumf32, + minnumf64, + maxnumf32, + maxnumf64, mips_target_feature, + miri_start_panic, mmx_target_feature, module, module_path, @@ -491,6 +535,8 @@ symbols! { naked, naked_functions, name, + nearbyintf32, + nearbyintf64, needs_allocator, needs_drop, needs_panic_runtime, @@ -518,6 +564,7 @@ symbols! { None, non_exhaustive, non_modrs_mods, + nontemporal_store, nontrapping_fptoint: "nontrapping-fptoint", noreturn, no_niche, @@ -577,8 +624,16 @@ symbols! { poll, Poll, powerpc_target_feature, + powf32, + powf64, + powif32, + powif64, precise_pointer_size_matching, pref_align_of, + prefetch_read_data, + prefetch_read_instruction, + prefetch_write_data, + prefetch_write_instruction, prelude, prelude_import, preserves_flags, @@ -640,10 +695,14 @@ symbols! { Result, Return, rhs, + rintf32, + rintf64, riscv_target_feature, rlib, rotate_left, rotate_right, + roundf32, + roundf64, rt, rtm_target_feature, rust, @@ -726,14 +785,19 @@ symbols! { simd_ffi, simd_insert, since, + sinf32, + sinf64, size, size_of, + size_of_val, slice_patterns, slicing_syntax, soft, Some, specialization, speed, + sqrtf32, + sqrtf64, sse4a_target_feature, stable, staged_api, @@ -787,6 +851,8 @@ symbols! { transparent_enums, transparent_unions, trivial_bounds, + truncf32, + truncf64, Try, try_blocks, try_trait, @@ -809,6 +875,8 @@ symbols! { u32, u64, u8, + unaligned_volatile_load, + unaligned_volatile_store, unboxed_closures, unchecked_add, unchecked_div, @@ -824,6 +892,7 @@ symbols! { universal_impl_trait, unlikely, unmarked_api, + unreachable, unreachable_code, unrestricted_attribute_tokens, unsafe_block_in_unsafe_fn, @@ -843,12 +912,21 @@ symbols! { val, var, variant_count, + va_arg, + va_copy, + va_end, + va_start, vec, Vec, version, vis, visible_private_types, volatile, + volatile_copy_memory, + volatile_copy_nonoverlapping_memory, + volatile_load, + volatile_set_memory, + volatile_store, warn, wasm_import_module, wasm_target_feature, @@ -858,6 +936,7 @@ symbols! { wrapping_add, wrapping_sub, wrapping_mul, + write_bytes, Yield, } } diff --git a/src/librustc_typeck/check/intrinsic.rs b/src/librustc_typeck/check/intrinsic.rs index da5b9f18c0719..9b3b4a67650a2 100644 --- a/src/librustc_typeck/check/intrinsic.rs +++ b/src/librustc_typeck/check/intrinsic.rs @@ -5,10 +5,11 @@ use crate::require_same_types; use rustc_errors::struct_span_err; use rustc_hir as hir; +use rustc_hir::def_id::DefId; use rustc_middle::traits::{ObligationCause, ObligationCauseCode}; use rustc_middle::ty::subst::Subst; use rustc_middle::ty::{self, Ty, TyCtxt}; -use rustc_span::symbol::Symbol; +use rustc_span::symbol::{kw, sym, Symbol}; use rustc_target::spec::abi::Abi; use std::iter; @@ -16,14 +17,13 @@ use std::iter; fn equate_intrinsic_type<'tcx>( tcx: TyCtxt<'tcx>, it: &hir::ForeignItem<'_>, + def_id: DefId, n_tps: usize, abi: Abi, safety: hir::Unsafety, inputs: Vec>, output: Ty<'tcx>, ) { - let def_id = tcx.hir().local_def_id(it.hir_id); - match it.kind { hir::ForeignItemKind::Fn(..) => {} _ => { @@ -67,15 +67,43 @@ fn equate_intrinsic_type<'tcx>( } /// Returns `true` if the given intrinsic is unsafe to call or not. -pub fn intrinsic_operation_unsafety(intrinsic: &str) -> hir::Unsafety { +pub fn intrinsic_operation_unsafety(intrinsic: Symbol) -> hir::Unsafety { match intrinsic { - "abort" | "size_of" | "min_align_of" | "needs_drop" | "caller_location" | "size_of_val" - | "min_align_of_val" | "add_with_overflow" | "sub_with_overflow" | "mul_with_overflow" - | "wrapping_add" | "wrapping_sub" | "wrapping_mul" | "saturating_add" - | "saturating_sub" | "rotate_left" | "rotate_right" | "ctpop" | "ctlz" | "cttz" - | "bswap" | "bitreverse" | "discriminant_value" | "type_id" | "likely" | "unlikely" - | "ptr_guaranteed_eq" | "ptr_guaranteed_ne" | "minnumf32" | "minnumf64" | "maxnumf32" - | "rustc_peek" | "maxnumf64" | "type_name" | "variant_count" => hir::Unsafety::Normal, + sym::abort + | sym::size_of + | sym::min_align_of + | sym::needs_drop + | sym::caller_location + | sym::size_of_val + | sym::min_align_of_val + | sym::add_with_overflow + | sym::sub_with_overflow + | sym::mul_with_overflow + | sym::wrapping_add + | sym::wrapping_sub + | sym::wrapping_mul + | sym::saturating_add + | sym::saturating_sub + | sym::rotate_left + | sym::rotate_right + | sym::ctpop + | sym::ctlz + | sym::cttz + | sym::bswap + | sym::bitreverse + | sym::discriminant_value + | sym::type_id + | sym::likely + | sym::unlikely + | sym::ptr_guaranteed_eq + | sym::ptr_guaranteed_ne + | sym::minnumf32 + | sym::minnumf64 + | sym::maxnumf32 + | sym::rustc_peek + | sym::maxnumf64 + | sym::type_name + | sym::variant_count => hir::Unsafety::Normal, _ => hir::Unsafety::Unsafe, } } @@ -84,7 +112,9 @@ pub fn intrinsic_operation_unsafety(intrinsic: &str) -> hir::Unsafety { /// and in libcore/intrinsics.rs pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) { let param = |n| tcx.mk_ty_param(n, Symbol::intern(&format!("P{}", n))); - let name = it.ident.as_str(); + let def_id = tcx.hir().local_def_id(it.hir_id).to_def_id(); + let intrinsic_name = tcx.item_name(def_id); + let name_str = intrinsic_name.as_str(); let mk_va_list_ty = |mutbl| { tcx.lang_items().va_list().map(|did| { @@ -98,8 +128,8 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) { }) }; - let (n_tps, inputs, output, unsafety) = if name.starts_with("atomic_") { - let split: Vec<&str> = name.split('_').collect(); + let (n_tps, inputs, output, unsafety) = if name_str.starts_with("atomic_") { + let split: Vec<&str> = name_str.split('_').collect(); assert!(split.len() >= 2, "Atomic intrinsic in an incorrect format"); //We only care about the operation here @@ -129,32 +159,30 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) { } }; (n_tps, inputs, output, hir::Unsafety::Unsafe) - } else if &name[..] == "abort" { - (0, Vec::new(), tcx.types.never, hir::Unsafety::Normal) - } else if &name[..] == "unreachable" { - (0, Vec::new(), tcx.types.never, hir::Unsafety::Unsafe) } else { - let unsafety = intrinsic_operation_unsafety(&name[..]); - let (n_tps, inputs, output) = match &name[..] { - "breakpoint" => (0, Vec::new(), tcx.mk_unit()), - "size_of" | "pref_align_of" | "min_align_of" | "variant_count" => { + let unsafety = intrinsic_operation_unsafety(intrinsic_name); + let (n_tps, inputs, output) = match intrinsic_name { + sym::abort => (0, Vec::new(), tcx.types.never), + sym::unreachable => (0, Vec::new(), tcx.types.never), + sym::breakpoint => (0, Vec::new(), tcx.mk_unit()), + sym::size_of | sym::pref_align_of | sym::min_align_of | sym::variant_count => { (1, Vec::new(), tcx.types.usize) } - "size_of_val" | "min_align_of_val" => { + sym::size_of_val | sym::min_align_of_val => { (1, vec![tcx.mk_imm_ptr(param(0))], tcx.types.usize) } - "rustc_peek" => (1, vec![param(0)], param(0)), - "caller_location" => (0, vec![], tcx.caller_location_ty()), - "assert_inhabited" | "assert_zero_valid" | "assert_uninit_valid" => { + sym::rustc_peek => (1, vec![param(0)], param(0)), + sym::caller_location => (0, vec![], tcx.caller_location_ty()), + sym::assert_inhabited | sym::assert_zero_valid | sym::assert_uninit_valid => { (1, Vec::new(), tcx.mk_unit()) } - "forget" => (1, vec![param(0)], tcx.mk_unit()), - "transmute" => (2, vec![param(0)], param(1)), - "move_val_init" => (1, vec![tcx.mk_mut_ptr(param(0)), param(0)], tcx.mk_unit()), - "prefetch_read_data" - | "prefetch_write_data" - | "prefetch_read_instruction" - | "prefetch_write_instruction" => ( + sym::forget => (1, vec![param(0)], tcx.mk_unit()), + sym::transmute => (2, vec![param(0)], param(1)), + sym::move_val_init => (1, vec![tcx.mk_mut_ptr(param(0)), param(0)], tcx.mk_unit()), + sym::prefetch_read_data + | sym::prefetch_write_data + | sym::prefetch_read_instruction + | sym::prefetch_write_instruction => ( 1, vec![ tcx.mk_ptr(ty::TypeAndMut { ty: param(0), mutbl: hir::Mutability::Not }), @@ -162,12 +190,12 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) { ], tcx.mk_unit(), ), - "drop_in_place" => (1, vec![tcx.mk_mut_ptr(param(0))], tcx.mk_unit()), - "needs_drop" => (1, Vec::new(), tcx.types.bool), + sym::drop_in_place => (1, vec![tcx.mk_mut_ptr(param(0))], tcx.mk_unit()), + sym::needs_drop => (1, Vec::new(), tcx.types.bool), - "type_name" => (1, Vec::new(), tcx.mk_static_str()), - "type_id" => (1, Vec::new(), tcx.types.u64), - "offset" | "arith_offset" => ( + sym::type_name => (1, Vec::new(), tcx.mk_static_str()), + sym::type_id => (1, Vec::new(), tcx.types.u64), + sym::offset | sym::arith_offset => ( 1, vec![ tcx.mk_ptr(ty::TypeAndMut { ty: param(0), mutbl: hir::Mutability::Not }), @@ -175,7 +203,7 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) { ], tcx.mk_ptr(ty::TypeAndMut { ty: param(0), mutbl: hir::Mutability::Not }), ), - "copy" | "copy_nonoverlapping" => ( + sym::copy | sym::copy_nonoverlapping => ( 1, vec![ tcx.mk_ptr(ty::TypeAndMut { ty: param(0), mutbl: hir::Mutability::Not }), @@ -184,7 +212,7 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) { ], tcx.mk_unit(), ), - "volatile_copy_memory" | "volatile_copy_nonoverlapping_memory" => ( + sym::volatile_copy_memory | sym::volatile_copy_nonoverlapping_memory => ( 1, vec![ tcx.mk_ptr(ty::TypeAndMut { ty: param(0), mutbl: hir::Mutability::Mut }), @@ -193,7 +221,7 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) { ], tcx.mk_unit(), ), - "write_bytes" | "volatile_set_memory" => ( + sym::write_bytes | sym::volatile_set_memory => ( 1, vec![ tcx.mk_ptr(ty::TypeAndMut { ty: param(0), mutbl: hir::Mutability::Mut }), @@ -202,93 +230,98 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) { ], tcx.mk_unit(), ), - "sqrtf32" => (0, vec![tcx.types.f32], tcx.types.f32), - "sqrtf64" => (0, vec![tcx.types.f64], tcx.types.f64), - "powif32" => (0, vec![tcx.types.f32, tcx.types.i32], tcx.types.f32), - "powif64" => (0, vec![tcx.types.f64, tcx.types.i32], tcx.types.f64), - "sinf32" => (0, vec![tcx.types.f32], tcx.types.f32), - "sinf64" => (0, vec![tcx.types.f64], tcx.types.f64), - "cosf32" => (0, vec![tcx.types.f32], tcx.types.f32), - "cosf64" => (0, vec![tcx.types.f64], tcx.types.f64), - "powf32" => (0, vec![tcx.types.f32, tcx.types.f32], tcx.types.f32), - "powf64" => (0, vec![tcx.types.f64, tcx.types.f64], tcx.types.f64), - "expf32" => (0, vec![tcx.types.f32], tcx.types.f32), - "expf64" => (0, vec![tcx.types.f64], tcx.types.f64), - "exp2f32" => (0, vec![tcx.types.f32], tcx.types.f32), - "exp2f64" => (0, vec![tcx.types.f64], tcx.types.f64), - "logf32" => (0, vec![tcx.types.f32], tcx.types.f32), - "logf64" => (0, vec![tcx.types.f64], tcx.types.f64), - "log10f32" => (0, vec![tcx.types.f32], tcx.types.f32), - "log10f64" => (0, vec![tcx.types.f64], tcx.types.f64), - "log2f32" => (0, vec![tcx.types.f32], tcx.types.f32), - "log2f64" => (0, vec![tcx.types.f64], tcx.types.f64), - "fmaf32" => (0, vec![tcx.types.f32, tcx.types.f32, tcx.types.f32], tcx.types.f32), - "fmaf64" => (0, vec![tcx.types.f64, tcx.types.f64, tcx.types.f64], tcx.types.f64), - "fabsf32" => (0, vec![tcx.types.f32], tcx.types.f32), - "fabsf64" => (0, vec![tcx.types.f64], tcx.types.f64), - "minnumf32" => (0, vec![tcx.types.f32, tcx.types.f32], tcx.types.f32), - "minnumf64" => (0, vec![tcx.types.f64, tcx.types.f64], tcx.types.f64), - "maxnumf32" => (0, vec![tcx.types.f32, tcx.types.f32], tcx.types.f32), - "maxnumf64" => (0, vec![tcx.types.f64, tcx.types.f64], tcx.types.f64), - "copysignf32" => (0, vec![tcx.types.f32, tcx.types.f32], tcx.types.f32), - "copysignf64" => (0, vec![tcx.types.f64, tcx.types.f64], tcx.types.f64), - "floorf32" => (0, vec![tcx.types.f32], tcx.types.f32), - "floorf64" => (0, vec![tcx.types.f64], tcx.types.f64), - "ceilf32" => (0, vec![tcx.types.f32], tcx.types.f32), - "ceilf64" => (0, vec![tcx.types.f64], tcx.types.f64), - "truncf32" => (0, vec![tcx.types.f32], tcx.types.f32), - "truncf64" => (0, vec![tcx.types.f64], tcx.types.f64), - "rintf32" => (0, vec![tcx.types.f32], tcx.types.f32), - "rintf64" => (0, vec![tcx.types.f64], tcx.types.f64), - "nearbyintf32" => (0, vec![tcx.types.f32], tcx.types.f32), - "nearbyintf64" => (0, vec![tcx.types.f64], tcx.types.f64), - "roundf32" => (0, vec![tcx.types.f32], tcx.types.f32), - "roundf64" => (0, vec![tcx.types.f64], tcx.types.f64), - - "volatile_load" | "unaligned_volatile_load" => { + sym::sqrtf32 => (0, vec![tcx.types.f32], tcx.types.f32), + sym::sqrtf64 => (0, vec![tcx.types.f64], tcx.types.f64), + sym::powif32 => (0, vec![tcx.types.f32, tcx.types.i32], tcx.types.f32), + sym::powif64 => (0, vec![tcx.types.f64, tcx.types.i32], tcx.types.f64), + sym::sinf32 => (0, vec![tcx.types.f32], tcx.types.f32), + sym::sinf64 => (0, vec![tcx.types.f64], tcx.types.f64), + sym::cosf32 => (0, vec![tcx.types.f32], tcx.types.f32), + sym::cosf64 => (0, vec![tcx.types.f64], tcx.types.f64), + sym::powf32 => (0, vec![tcx.types.f32, tcx.types.f32], tcx.types.f32), + sym::powf64 => (0, vec![tcx.types.f64, tcx.types.f64], tcx.types.f64), + sym::expf32 => (0, vec![tcx.types.f32], tcx.types.f32), + sym::expf64 => (0, vec![tcx.types.f64], tcx.types.f64), + sym::exp2f32 => (0, vec![tcx.types.f32], tcx.types.f32), + sym::exp2f64 => (0, vec![tcx.types.f64], tcx.types.f64), + sym::logf32 => (0, vec![tcx.types.f32], tcx.types.f32), + sym::logf64 => (0, vec![tcx.types.f64], tcx.types.f64), + sym::log10f32 => (0, vec![tcx.types.f32], tcx.types.f32), + sym::log10f64 => (0, vec![tcx.types.f64], tcx.types.f64), + sym::log2f32 => (0, vec![tcx.types.f32], tcx.types.f32), + sym::log2f64 => (0, vec![tcx.types.f64], tcx.types.f64), + sym::fmaf32 => (0, vec![tcx.types.f32, tcx.types.f32, tcx.types.f32], tcx.types.f32), + sym::fmaf64 => (0, vec![tcx.types.f64, tcx.types.f64, tcx.types.f64], tcx.types.f64), + sym::fabsf32 => (0, vec![tcx.types.f32], tcx.types.f32), + sym::fabsf64 => (0, vec![tcx.types.f64], tcx.types.f64), + sym::minnumf32 => (0, vec![tcx.types.f32, tcx.types.f32], tcx.types.f32), + sym::minnumf64 => (0, vec![tcx.types.f64, tcx.types.f64], tcx.types.f64), + sym::maxnumf32 => (0, vec![tcx.types.f32, tcx.types.f32], tcx.types.f32), + sym::maxnumf64 => (0, vec![tcx.types.f64, tcx.types.f64], tcx.types.f64), + sym::copysignf32 => (0, vec![tcx.types.f32, tcx.types.f32], tcx.types.f32), + sym::copysignf64 => (0, vec![tcx.types.f64, tcx.types.f64], tcx.types.f64), + sym::floorf32 => (0, vec![tcx.types.f32], tcx.types.f32), + sym::floorf64 => (0, vec![tcx.types.f64], tcx.types.f64), + sym::ceilf32 => (0, vec![tcx.types.f32], tcx.types.f32), + sym::ceilf64 => (0, vec![tcx.types.f64], tcx.types.f64), + sym::truncf32 => (0, vec![tcx.types.f32], tcx.types.f32), + sym::truncf64 => (0, vec![tcx.types.f64], tcx.types.f64), + sym::rintf32 => (0, vec![tcx.types.f32], tcx.types.f32), + sym::rintf64 => (0, vec![tcx.types.f64], tcx.types.f64), + sym::nearbyintf32 => (0, vec![tcx.types.f32], tcx.types.f32), + sym::nearbyintf64 => (0, vec![tcx.types.f64], tcx.types.f64), + sym::roundf32 => (0, vec![tcx.types.f32], tcx.types.f32), + sym::roundf64 => (0, vec![tcx.types.f64], tcx.types.f64), + + sym::volatile_load | sym::unaligned_volatile_load => { (1, vec![tcx.mk_imm_ptr(param(0))], param(0)) } - "volatile_store" | "unaligned_volatile_store" => { + sym::volatile_store | sym::unaligned_volatile_store => { (1, vec![tcx.mk_mut_ptr(param(0)), param(0)], tcx.mk_unit()) } - "ctpop" | "ctlz" | "ctlz_nonzero" | "cttz" | "cttz_nonzero" | "bswap" - | "bitreverse" => (1, vec![param(0)], param(0)), + sym::ctpop + | sym::ctlz + | sym::ctlz_nonzero + | sym::cttz + | sym::cttz_nonzero + | sym::bswap + | sym::bitreverse => (1, vec![param(0)], param(0)), - "add_with_overflow" | "sub_with_overflow" | "mul_with_overflow" => { + sym::add_with_overflow | sym::sub_with_overflow | sym::mul_with_overflow => { (1, vec![param(0), param(0)], tcx.intern_tup(&[param(0), tcx.types.bool])) } - "ptr_guaranteed_eq" | "ptr_guaranteed_ne" => { + sym::ptr_guaranteed_eq | sym::ptr_guaranteed_ne => { (1, vec![tcx.mk_imm_ptr(param(0)), tcx.mk_imm_ptr(param(0))], tcx.types.bool) } - "ptr_offset_from" => { + sym::ptr_offset_from => { (1, vec![tcx.mk_imm_ptr(param(0)), tcx.mk_imm_ptr(param(0))], tcx.types.isize) } - "unchecked_div" | "unchecked_rem" | "exact_div" => { + sym::unchecked_div | sym::unchecked_rem | sym::exact_div => { (1, vec![param(0), param(0)], param(0)) } - "unchecked_shl" | "unchecked_shr" | "rotate_left" | "rotate_right" => { + sym::unchecked_shl | sym::unchecked_shr | sym::rotate_left | sym::rotate_right => { (1, vec![param(0), param(0)], param(0)) } - "unchecked_add" | "unchecked_sub" | "unchecked_mul" => { + sym::unchecked_add | sym::unchecked_sub | sym::unchecked_mul => { (1, vec![param(0), param(0)], param(0)) } - "wrapping_add" | "wrapping_sub" | "wrapping_mul" => { + sym::wrapping_add | sym::wrapping_sub | sym::wrapping_mul => { (1, vec![param(0), param(0)], param(0)) } - "saturating_add" | "saturating_sub" => (1, vec![param(0), param(0)], param(0)), - "fadd_fast" | "fsub_fast" | "fmul_fast" | "fdiv_fast" | "frem_fast" => { + sym::saturating_add | sym::saturating_sub => (1, vec![param(0), param(0)], param(0)), + sym::fadd_fast | sym::fsub_fast | sym::fmul_fast | sym::fdiv_fast | sym::frem_fast => { (1, vec![param(0), param(0)], param(0)) } - "float_to_int_unchecked" => (2, vec![param(0)], param(1)), + sym::float_to_int_unchecked => (2, vec![param(0)], param(1)), - "assume" => (0, vec![tcx.types.bool], tcx.mk_unit()), - "likely" => (0, vec![tcx.types.bool], tcx.types.bool), - "unlikely" => (0, vec![tcx.types.bool], tcx.types.bool), + sym::assume => (0, vec![tcx.types.bool], tcx.mk_unit()), + sym::likely => (0, vec![tcx.types.bool], tcx.types.bool), + sym::unlikely => (0, vec![tcx.types.bool], tcx.types.bool), - "discriminant_value" => { + sym::discriminant_value => { let assoc_items = tcx.associated_items(tcx.lang_items().discriminant_kind_trait().unwrap()); let discriminant_def_id = assoc_items.in_definition_order().next().unwrap().def_id; @@ -303,7 +336,7 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) { ) } - "try" => { + kw::Try => { let mut_u8 = tcx.mk_mut_ptr(tcx.types.u8); let try_fn_ty = ty::Binder::bind(tcx.mk_fn_sig( iter::once(mut_u8), @@ -326,12 +359,12 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) { ) } - "va_start" | "va_end" => match mk_va_list_ty(hir::Mutability::Mut) { + sym::va_start | sym::va_end => match mk_va_list_ty(hir::Mutability::Mut) { Some((va_list_ref_ty, _)) => (0, vec![va_list_ref_ty], tcx.mk_unit()), None => bug!("`va_list` language item needed for C-variadic intrinsics"), }, - "va_copy" => match mk_va_list_ty(hir::Mutability::Not) { + sym::va_copy => match mk_va_list_ty(hir::Mutability::Not) { Some((va_list_ref_ty, va_list_ty)) => { let va_list_ptr_ty = tcx.mk_mut_ptr(va_list_ty); (0, vec![va_list_ptr_ty, va_list_ref_ty], tcx.mk_unit()) @@ -339,38 +372,38 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) { None => bug!("`va_list` language item needed for C-variadic intrinsics"), }, - "va_arg" => match mk_va_list_ty(hir::Mutability::Mut) { + sym::va_arg => match mk_va_list_ty(hir::Mutability::Mut) { Some((va_list_ref_ty, _)) => (1, vec![va_list_ref_ty], param(0)), None => bug!("`va_list` language item needed for C-variadic intrinsics"), }, - "nontemporal_store" => (1, vec![tcx.mk_mut_ptr(param(0)), param(0)], tcx.mk_unit()), + sym::nontemporal_store => (1, vec![tcx.mk_mut_ptr(param(0)), param(0)], tcx.mk_unit()), - "miri_start_panic" => { + sym::miri_start_panic => { // FIXME - the relevant types aren't lang items, // so it's not trivial to check this return; } - "count_code_region" => { + sym::count_code_region => { (0, vec![tcx.types.u32, tcx.types.u32, tcx.types.u32], tcx.mk_unit()) } - "coverage_counter_add" | "coverage_counter_subtract" => ( + sym::coverage_counter_add | sym::coverage_counter_subtract => ( 0, vec![tcx.types.u32, tcx.types.u32, tcx.types.u32, tcx.types.u32, tcx.types.u32], tcx.mk_unit(), ), - "coverage_unreachable" => (0, vec![tcx.types.u32, tcx.types.u32], tcx.mk_unit()), + sym::coverage_unreachable => (0, vec![tcx.types.u32, tcx.types.u32], tcx.mk_unit()), - ref other => { + other => { struct_span_err!( tcx.sess, it.span, E0093, "unrecognized intrinsic function: `{}`", - *other + other, ) .span_label(it.span, "unrecognized intrinsic") .emit(); @@ -379,7 +412,7 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) { }; (n_tps, inputs, output, unsafety) }; - equate_intrinsic_type(tcx, it, n_tps, Abi::RustIntrinsic, unsafety, inputs, output) + equate_intrinsic_type(tcx, it, def_id, n_tps, Abi::RustIntrinsic, unsafety, inputs, output) } /// Type-check `extern "platform-intrinsic" { ... }` functions. @@ -389,6 +422,7 @@ pub fn check_platform_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) tcx.mk_ty_param(n, name) }; + let def_id = tcx.hir().local_def_id(it.hir_id).to_def_id(); let name = it.ident.as_str(); let (n_tps, inputs, output) = match &*name { @@ -463,6 +497,7 @@ pub fn check_platform_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) equate_intrinsic_type( tcx, it, + def_id, n_tps, Abi::PlatformIntrinsic, hir::Unsafety::Unsafe, diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index 8920203e6af40..cc491c527db0b 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -2063,7 +2063,7 @@ fn compute_sig_of_foreign_fn_decl<'tcx>( ident: Ident, ) -> ty::PolyFnSig<'tcx> { let unsafety = if abi == abi::Abi::RustIntrinsic { - intrinsic_operation_unsafety(&tcx.item_name(def_id).as_str()) + intrinsic_operation_unsafety(tcx.item_name(def_id)) } else { hir::Unsafety::Unsafe }; From dcbe85abad8ddd3a39fcafe70a884db4e71f0b03 Mon Sep 17 00:00:00 2001 From: Yuki Okushi Date: Thu, 2 Jul 2020 02:37:52 +0900 Subject: [PATCH 17/22] Explain exhaustive matching on {usize,isize} maximum values --- .../hair/pattern/check_match.rs | 10 +++++++- ...-gate-precise_pointer_size_matching.stderr | 4 +++ ...non-exhaustive-pattern-pointer-size-int.rs | 21 ++++++++++++++++ ...exhaustive-pattern-pointer-size-int.stderr | 25 +++++++++++++++++++ 4 files changed, 59 insertions(+), 1 deletion(-) create mode 100644 src/test/ui/pattern/usefulness/non-exhaustive-pattern-pointer-size-int.rs create mode 100644 src/test/ui/pattern/usefulness/non-exhaustive-pattern-pointer-size-int.stderr diff --git a/src/librustc_mir_build/hair/pattern/check_match.rs b/src/librustc_mir_build/hair/pattern/check_match.rs index 6fc447a87f57a..6a68c91588944 100644 --- a/src/librustc_mir_build/hair/pattern/check_match.rs +++ b/src/librustc_mir_build/hair/pattern/check_match.rs @@ -468,6 +468,7 @@ fn check_exhaustive<'p, 'tcx>( // In the case of an empty match, replace the '`_` not covered' diagnostic with something more // informative. let mut err; + let joined_patterns = joined_uncovered_patterns(&witnesses); if is_empty_match && !non_empty_enum { err = create_e0004( cx.tcx.sess, @@ -475,7 +476,6 @@ fn check_exhaustive<'p, 'tcx>( format!("non-exhaustive patterns: type `{}` is non-empty", scrut_ty), ); } else { - let joined_patterns = joined_uncovered_patterns(&witnesses); err = create_e0004( cx.tcx.sess, sp, @@ -490,6 +490,14 @@ fn check_exhaustive<'p, 'tcx>( possibly by adding wildcards or more match arms", ); err.note(&format!("the matched value is of type `{}`", scrut_ty)); + if (scrut_ty == cx.tcx.types.usize || scrut_ty == cx.tcx.types.isize) + && joined_patterns == "`_`" + { + err.note("for `usize` and `isize`, no assumptions about the maximum value are permitted"); + err.note( + "to exhaustively match on either pointer-size integer type, wildcards must be used", + ); + } err.emit(); } diff --git a/src/test/ui/feature-gates/feature-gate-precise_pointer_size_matching.stderr b/src/test/ui/feature-gates/feature-gate-precise_pointer_size_matching.stderr index 6c5d0091c5add..8aa1534b27689 100644 --- a/src/test/ui/feature-gates/feature-gate-precise_pointer_size_matching.stderr +++ b/src/test/ui/feature-gates/feature-gate-precise_pointer_size_matching.stderr @@ -6,6 +6,8 @@ LL | match 0usize { | = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms = note: the matched value is of type `usize` + = note: for `usize` and `isize`, no assumptions about the maximum value are permitted + = note: to exhaustively match on either pointer-size integer type, wildcards must be used error[E0004]: non-exhaustive patterns: `_` not covered --> $DIR/feature-gate-precise_pointer_size_matching.rs:10:11 @@ -15,6 +17,8 @@ LL | match 0isize { | = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms = note: the matched value is of type `isize` + = note: for `usize` and `isize`, no assumptions about the maximum value are permitted + = note: to exhaustively match on either pointer-size integer type, wildcards must be used error: aborting due to 2 previous errors diff --git a/src/test/ui/pattern/usefulness/non-exhaustive-pattern-pointer-size-int.rs b/src/test/ui/pattern/usefulness/non-exhaustive-pattern-pointer-size-int.rs new file mode 100644 index 0000000000000..aa6a3ffc522ef --- /dev/null +++ b/src/test/ui/pattern/usefulness/non-exhaustive-pattern-pointer-size-int.rs @@ -0,0 +1,21 @@ +use std::{usize, isize}; + +fn main() { + match 0usize { + //~^ ERROR non-exhaustive patterns + //~| NOTE pattern `_` not covered + //~| NOTE the matched value is of type `usize` + //~| NOTE for `usize` and `isize`, no assumptions about the maximum value are permitted + //~| NOTE to exhaustively match on either pointer-size integer type, wildcards must be used + 0 ..= usize::MAX => {} + } + + match 0isize { + //~^ ERROR non-exhaustive patterns + //~| NOTE pattern `_` not covered + //~| NOTE the matched value is of type `isize` + //~| NOTE for `usize` and `isize`, no assumptions about the maximum value are permitted + //~| NOTE to exhaustively match on either pointer-size integer type, wildcards must be used + isize::MIN ..= isize::MAX => {} + } +} diff --git a/src/test/ui/pattern/usefulness/non-exhaustive-pattern-pointer-size-int.stderr b/src/test/ui/pattern/usefulness/non-exhaustive-pattern-pointer-size-int.stderr new file mode 100644 index 0000000000000..cd47e74fa4643 --- /dev/null +++ b/src/test/ui/pattern/usefulness/non-exhaustive-pattern-pointer-size-int.stderr @@ -0,0 +1,25 @@ +error[E0004]: non-exhaustive patterns: `_` not covered + --> $DIR/non-exhaustive-pattern-pointer-size-int.rs:4:11 + | +LL | match 0usize { + | ^^^^^^ pattern `_` not covered + | + = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms + = note: the matched value is of type `usize` + = note: for `usize` and `isize`, no assumptions about the maximum value are permitted + = note: to exhaustively match on either pointer-size integer type, wildcards must be used + +error[E0004]: non-exhaustive patterns: `_` not covered + --> $DIR/non-exhaustive-pattern-pointer-size-int.rs:13:11 + | +LL | match 0isize { + | ^^^^^^ pattern `_` not covered + | + = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms + = note: the matched value is of type `isize` + = note: for `usize` and `isize`, no assumptions about the maximum value are permitted + = note: to exhaustively match on either pointer-size integer type, wildcards must be used + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0004`. From b93ecc1dacd3d534b0fa24e4b14cd3b07bae9889 Mon Sep 17 00:00:00 2001 From: Yuki Okushi Date: Sun, 5 Jul 2020 03:40:59 +0900 Subject: [PATCH 18/22] Address code reviews --- .../hair/pattern/check_match.rs | 25 +++++++++++++------ ...-gate-precise_pointer_size_matching.stderr | 8 +++--- ...non-exhaustive-pattern-pointer-size-int.rs | 10 +++++--- ...exhaustive-pattern-pointer-size-int.stderr | 21 +++++++++++----- 4 files changed, 43 insertions(+), 21 deletions(-) diff --git a/src/librustc_mir_build/hair/pattern/check_match.rs b/src/librustc_mir_build/hair/pattern/check_match.rs index 6a68c91588944..4bfb6cccbcb30 100644 --- a/src/librustc_mir_build/hair/pattern/check_match.rs +++ b/src/librustc_mir_build/hair/pattern/check_match.rs @@ -12,6 +12,7 @@ use rustc_hir::def_id::DefId; use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor}; use rustc_hir::{HirId, Pat}; use rustc_middle::ty::{self, Ty, TyCtxt}; +use rustc_session::config::nightly_options; use rustc_session::lint::builtin::BINDINGS_WITH_VARIANT_NAME; use rustc_session::lint::builtin::{IRREFUTABLE_LET_PATTERNS, UNREACHABLE_PATTERNS}; use rustc_session::parse::feature_err; @@ -468,7 +469,6 @@ fn check_exhaustive<'p, 'tcx>( // In the case of an empty match, replace the '`_` not covered' diagnostic with something more // informative. let mut err; - let joined_patterns = joined_uncovered_patterns(&witnesses); if is_empty_match && !non_empty_enum { err = create_e0004( cx.tcx.sess, @@ -476,6 +476,7 @@ fn check_exhaustive<'p, 'tcx>( format!("non-exhaustive patterns: type `{}` is non-empty", scrut_ty), ); } else { + let joined_patterns = joined_uncovered_patterns(&witnesses); err = create_e0004( cx.tcx.sess, sp, @@ -487,16 +488,26 @@ fn check_exhaustive<'p, 'tcx>( adt_defined_here(cx, &mut err, scrut_ty, &witnesses); err.help( "ensure that all possible cases are being handled, \ - possibly by adding wildcards or more match arms", + possibly by adding wildcards or more match arms", ); err.note(&format!("the matched value is of type `{}`", scrut_ty)); if (scrut_ty == cx.tcx.types.usize || scrut_ty == cx.tcx.types.isize) - && joined_patterns == "`_`" + && !is_empty_match + && witnesses.len() == 1 + && witnesses[0].is_wildcard() { - err.note("for `usize` and `isize`, no assumptions about the maximum value are permitted"); - err.note( - "to exhaustively match on either pointer-size integer type, wildcards must be used", - ); + err.note(&format!( + "`{}` does not have a fixed maximum value, \ + so a wildcard `_` is necessary to match exhaustively", + scrut_ty, + )); + if nightly_options::is_nightly_build() { + err.help(&format!( + "add `#![feature(precise_pointer_size_matching)]` \ + to the crate attributes to enable precise `{}` matching", + scrut_ty, + )); + } } err.emit(); } diff --git a/src/test/ui/feature-gates/feature-gate-precise_pointer_size_matching.stderr b/src/test/ui/feature-gates/feature-gate-precise_pointer_size_matching.stderr index 8aa1534b27689..c7a63e5d50252 100644 --- a/src/test/ui/feature-gates/feature-gate-precise_pointer_size_matching.stderr +++ b/src/test/ui/feature-gates/feature-gate-precise_pointer_size_matching.stderr @@ -6,8 +6,8 @@ LL | match 0usize { | = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms = note: the matched value is of type `usize` - = note: for `usize` and `isize`, no assumptions about the maximum value are permitted - = note: to exhaustively match on either pointer-size integer type, wildcards must be used + = note: `usize` does not have a fixed maximum value, so a wildcard `_` is necessary to match exhaustively + = help: add `#![feature(precise_pointer_size_matching)]` to the crate attributes to enable precise `usize` matching error[E0004]: non-exhaustive patterns: `_` not covered --> $DIR/feature-gate-precise_pointer_size_matching.rs:10:11 @@ -17,8 +17,8 @@ LL | match 0isize { | = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms = note: the matched value is of type `isize` - = note: for `usize` and `isize`, no assumptions about the maximum value are permitted - = note: to exhaustively match on either pointer-size integer type, wildcards must be used + = note: `isize` does not have a fixed maximum value, so a wildcard `_` is necessary to match exhaustively + = help: add `#![feature(precise_pointer_size_matching)]` to the crate attributes to enable precise `isize` matching error: aborting due to 2 previous errors diff --git a/src/test/ui/pattern/usefulness/non-exhaustive-pattern-pointer-size-int.rs b/src/test/ui/pattern/usefulness/non-exhaustive-pattern-pointer-size-int.rs index aa6a3ffc522ef..0c52876e21f95 100644 --- a/src/test/ui/pattern/usefulness/non-exhaustive-pattern-pointer-size-int.rs +++ b/src/test/ui/pattern/usefulness/non-exhaustive-pattern-pointer-size-int.rs @@ -5,8 +5,7 @@ fn main() { //~^ ERROR non-exhaustive patterns //~| NOTE pattern `_` not covered //~| NOTE the matched value is of type `usize` - //~| NOTE for `usize` and `isize`, no assumptions about the maximum value are permitted - //~| NOTE to exhaustively match on either pointer-size integer type, wildcards must be used + //~| NOTE `usize` does not have a fixed maximum value 0 ..= usize::MAX => {} } @@ -14,8 +13,11 @@ fn main() { //~^ ERROR non-exhaustive patterns //~| NOTE pattern `_` not covered //~| NOTE the matched value is of type `isize` - //~| NOTE for `usize` and `isize`, no assumptions about the maximum value are permitted - //~| NOTE to exhaustively match on either pointer-size integer type, wildcards must be used + //~| NOTE `isize` does not have a fixed maximum value isize::MIN ..= isize::MAX => {} } + + match 7usize {} + //~^ ERROR non-exhaustive patterns + //~| NOTE the matched value is of type `usize` } diff --git a/src/test/ui/pattern/usefulness/non-exhaustive-pattern-pointer-size-int.stderr b/src/test/ui/pattern/usefulness/non-exhaustive-pattern-pointer-size-int.stderr index cd47e74fa4643..d0aa452fd3861 100644 --- a/src/test/ui/pattern/usefulness/non-exhaustive-pattern-pointer-size-int.stderr +++ b/src/test/ui/pattern/usefulness/non-exhaustive-pattern-pointer-size-int.stderr @@ -6,20 +6,29 @@ LL | match 0usize { | = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms = note: the matched value is of type `usize` - = note: for `usize` and `isize`, no assumptions about the maximum value are permitted - = note: to exhaustively match on either pointer-size integer type, wildcards must be used + = note: `usize` does not have a fixed maximum value, so a wildcard `_` is necessary to match exhaustively + = help: add `#![feature(precise_pointer_size_matching)]` to the crate attributes to enable precise `usize` matching error[E0004]: non-exhaustive patterns: `_` not covered - --> $DIR/non-exhaustive-pattern-pointer-size-int.rs:13:11 + --> $DIR/non-exhaustive-pattern-pointer-size-int.rs:12:11 | LL | match 0isize { | ^^^^^^ pattern `_` not covered | = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms = note: the matched value is of type `isize` - = note: for `usize` and `isize`, no assumptions about the maximum value are permitted - = note: to exhaustively match on either pointer-size integer type, wildcards must be used + = note: `isize` does not have a fixed maximum value, so a wildcard `_` is necessary to match exhaustively + = help: add `#![feature(precise_pointer_size_matching)]` to the crate attributes to enable precise `isize` matching -error: aborting due to 2 previous errors +error[E0004]: non-exhaustive patterns: type `usize` is non-empty + --> $DIR/non-exhaustive-pattern-pointer-size-int.rs:20:11 + | +LL | match 7usize {} + | ^^^^^^ + | + = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms + = note: the matched value is of type `usize` + +error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0004`. From 3cb31b6699558737b1a4650537f0facdc8cb7852 Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Thu, 2 Jul 2020 21:49:58 +0100 Subject: [PATCH 19/22] Fix #71977 --- src/librustc_mir_build/hair/pattern/_match.rs | 36 ++++++++++++++++--- .../exhaustiveness-unreachable-pattern.rs | 28 +++++++++++++++ .../exhaustiveness-unreachable-pattern.stderr | 34 ++++++++++++------ .../ui/or-patterns/search-via-bindings.rs | 1 - 4 files changed, 82 insertions(+), 17 deletions(-) diff --git a/src/librustc_mir_build/hair/pattern/_match.rs b/src/librustc_mir_build/hair/pattern/_match.rs index b5a655e4218f1..372cb783f503f 100644 --- a/src/librustc_mir_build/hair/pattern/_match.rs +++ b/src/librustc_mir_build/hair/pattern/_match.rs @@ -276,6 +276,7 @@ use self::Usefulness::*; use self::WitnessPreference::*; use rustc_data_structures::captures::Captures; +use rustc_data_structures::fx::FxHashSet; use rustc_index::vec::Idx; use super::{compare_const_vals, PatternFoldable, PatternFolder}; @@ -1852,16 +1853,35 @@ crate fn is_useful<'p, 'tcx>( // We need to push the already-seen patterns into the matrix in order to detect redundant // branches like `Some(_) | Some(0)`. We also keep track of the unreachable subpatterns. let mut matrix = matrix.clone(); - let mut unreachable_pats = Vec::new(); + // `Vec` of all the unreachable branches of the current or-pattern. + let mut unreachable_branches = Vec::new(); + // Subpatterns that are unreachable from all branches. E.g. in the following case, the last + // `true` is unreachable only from one branch, so it is overall reachable. + // ``` + // match (true, true) { + // (true, true) => {} + // (false | true, false | true) => {} + // } + // ``` + let mut unreachable_subpats = FxHashSet::default(); + // Whether any branch at all is useful. let mut any_is_useful = false; + for v in vs { let res = is_useful(cx, &matrix, &v, witness_preference, hir_id, is_under_guard, false); match res { Useful(pats) => { - any_is_useful = true; - unreachable_pats.extend(pats); + if !any_is_useful { + any_is_useful = true; + // Initialize with the first set of unreachable subpatterns encountered. + unreachable_subpats = pats.into_iter().collect(); + } else { + // Keep the patterns unreachable from both this and previous branches. + unreachable_subpats = + pats.into_iter().filter(|p| unreachable_subpats.contains(p)).collect(); + } } - NotUseful => unreachable_pats.push(v.head().span), + NotUseful => unreachable_branches.push(v.head().span), UsefulWithWitness(_) => { bug!("Encountered or-pat in `v` during exhaustiveness checking") } @@ -1871,7 +1891,13 @@ crate fn is_useful<'p, 'tcx>( matrix.push(v); } } - return if any_is_useful { Useful(unreachable_pats) } else { NotUseful }; + if any_is_useful { + // Collect all the unreachable patterns. + unreachable_branches.extend(unreachable_subpats); + return Useful(unreachable_branches); + } else { + return NotUseful; + } } // FIXME(Nadrieril): Hack to work around type normalization issues (see #72476). diff --git a/src/test/ui/or-patterns/exhaustiveness-unreachable-pattern.rs b/src/test/ui/or-patterns/exhaustiveness-unreachable-pattern.rs index 44bae282d8857..a1147cb5cfc9c 100644 --- a/src/test/ui/or-patterns/exhaustiveness-unreachable-pattern.rs +++ b/src/test/ui/or-patterns/exhaustiveness-unreachable-pattern.rs @@ -29,6 +29,9 @@ fn main() { (1, 4 | 5) => {} //~ ERROR unreachable pattern _ => {} } + match (true, true) { + (false | true, false | true) => (), + } match (Some(0u8),) { (None | Some(1 | 2),) => {} (Some(1),) => {} //~ ERROR unreachable pattern @@ -67,4 +70,29 @@ fn main() { | 1) => {} _ => {} } + + // A subpattern that is only unreachable in one branch is overall reachable. + match (true, true) { + (true, true) => {} + (false | true, false | true) => {} + } + match (true, true) { + (true, false) => {} + (false, true) => {} + (false | true, false | true) => {} + } + // A subpattern that is unreachable in all branches is overall unreachable. + match (true, true) { + (false, true) => {} + (true, true) => {} + (false | true, false + | true) => {} //~ ERROR unreachable + } + match (true, true) { + (true, false) => {} + (true, true) => {} + (false + | true, //~ ERROR unreachable + false | true) => {} + } } diff --git a/src/test/ui/or-patterns/exhaustiveness-unreachable-pattern.stderr b/src/test/ui/or-patterns/exhaustiveness-unreachable-pattern.stderr index bef6f8270bc54..d92b545a8694f 100644 --- a/src/test/ui/or-patterns/exhaustiveness-unreachable-pattern.stderr +++ b/src/test/ui/or-patterns/exhaustiveness-unreachable-pattern.stderr @@ -53,52 +53,64 @@ LL | (1, 4 | 5) => {} | ^^^^^^^^^^ error: unreachable pattern - --> $DIR/exhaustiveness-unreachable-pattern.rs:34:9 + --> $DIR/exhaustiveness-unreachable-pattern.rs:37:9 | LL | (Some(1),) => {} | ^^^^^^^^^^ error: unreachable pattern - --> $DIR/exhaustiveness-unreachable-pattern.rs:35:9 + --> $DIR/exhaustiveness-unreachable-pattern.rs:38:9 | LL | (None,) => {} | ^^^^^^^ error: unreachable pattern - --> $DIR/exhaustiveness-unreachable-pattern.rs:40:9 + --> $DIR/exhaustiveness-unreachable-pattern.rs:43:9 | LL | ((1..=4,),) => {} | ^^^^^^^^^^^ error: unreachable pattern - --> $DIR/exhaustiveness-unreachable-pattern.rs:45:14 + --> $DIR/exhaustiveness-unreachable-pattern.rs:48:14 | LL | (1 | 1,) => {} | ^ error: unreachable pattern - --> $DIR/exhaustiveness-unreachable-pattern.rs:52:15 + --> $DIR/exhaustiveness-unreachable-pattern.rs:53:15 | -LL | | 0] => {} +LL | | 0 | ^ error: unreachable pattern - --> $DIR/exhaustiveness-unreachable-pattern.rs:50:15 + --> $DIR/exhaustiveness-unreachable-pattern.rs:55:15 | -LL | | 0 +LL | | 0] => {} | ^ error: unreachable pattern - --> $DIR/exhaustiveness-unreachable-pattern.rs:60:10 + --> $DIR/exhaustiveness-unreachable-pattern.rs:63:10 | LL | [1 | ^ error: unreachable pattern - --> $DIR/exhaustiveness-unreachable-pattern.rs:66:14 + --> $DIR/exhaustiveness-unreachable-pattern.rs:69:14 | LL | Some(0 | ^ -error: aborting due to 16 previous errors +error: unreachable pattern + --> $DIR/exhaustiveness-unreachable-pattern.rs:89:15 + | +LL | | true) => {} + | ^^^^ + +error: unreachable pattern + --> $DIR/exhaustiveness-unreachable-pattern.rs:95:15 + | +LL | | true, + | ^^^^ + +error: aborting due to 18 previous errors diff --git a/src/test/ui/or-patterns/search-via-bindings.rs b/src/test/ui/or-patterns/search-via-bindings.rs index eb127b881cd37..067e617373a63 100644 --- a/src/test/ui/or-patterns/search-via-bindings.rs +++ b/src/test/ui/or-patterns/search-via-bindings.rs @@ -3,7 +3,6 @@ // run-pass #![feature(or_patterns)] -#![allow(unreachable_patterns)] // FIXME(or-patterns) this shouldn't trigger fn search(target: (bool, bool, bool)) -> u32 { let x = ((false, true), (false, true), (false, true)); From bc0d619325ccca85f804ab7f24752736748482d9 Mon Sep 17 00:00:00 2001 From: Ivan Tham Date: Sun, 5 Jul 2020 15:23:42 +0800 Subject: [PATCH 20/22] Fix spacing in Iterator fold doc --- src/libcore/iter/traits/iterator.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libcore/iter/traits/iterator.rs b/src/libcore/iter/traits/iterator.rs index 530cf881f29da..ce4be973140e5 100644 --- a/src/libcore/iter/traits/iterator.rs +++ b/src/libcore/iter/traits/iterator.rs @@ -1521,7 +1521,7 @@ pub trait Iterator { /// /// let iter = a.iter(); /// - /// let sum: i32 = iter.take(5).fold(0, |acc, i| acc + i ); + /// let sum: i32 = iter.take(5).fold(0, |acc, i| acc + i); /// /// assert_eq!(sum, 6); /// @@ -1535,7 +1535,7 @@ pub trait Iterator { /// let mut iter = a.iter(); /// /// // instead, we add in a .by_ref() - /// let sum: i32 = iter.by_ref().take(2).fold(0, |acc, i| acc + i ); + /// let sum: i32 = iter.by_ref().take(2).fold(0, |acc, i| acc + i); /// /// assert_eq!(sum, 3); /// From 016e9f81573859a4601b645fd1178fdda95b2e73 Mon Sep 17 00:00:00 2001 From: Bastian Kauschke Date: Sun, 5 Jul 2020 11:38:39 +0200 Subject: [PATCH 21/22] expected found `&T` -> `T` --- src/librustc_infer/infer/combine.rs | 8 ++-- src/librustc_middle/ty/relate.rs | 57 +++++++++++++---------------- 2 files changed, 30 insertions(+), 35 deletions(-) diff --git a/src/librustc_infer/infer/combine.rs b/src/librustc_infer/infer/combine.rs index c8d4e9f0e14b9..3b564e03d9a94 100644 --- a/src/librustc_infer/infer/combine.rs +++ b/src/librustc_infer/infer/combine.rs @@ -112,7 +112,7 @@ impl<'infcx, 'tcx> InferCtxt<'infcx, 'tcx> { // All other cases of inference are errors (&ty::Infer(_), _) | (_, &ty::Infer(_)) => { - Err(TypeError::Sorts(ty::relate::expected_found(relation, &a, &b))) + Err(TypeError::Sorts(ty::relate::expected_found(relation, a, b))) } _ => ty::relate::super_relate_tys(relation, a, b), @@ -701,7 +701,7 @@ pub fn const_unification_error<'tcx>( a_is_expected: bool, (a, b): (&'tcx ty::Const<'tcx>, &'tcx ty::Const<'tcx>), ) -> TypeError<'tcx> { - TypeError::ConstMismatch(ty::relate::expected_found_bool(a_is_expected, &a, &b)) + TypeError::ConstMismatch(ty::relate::expected_found_bool(a_is_expected, a, b)) } fn int_unification_error<'tcx>( @@ -709,7 +709,7 @@ fn int_unification_error<'tcx>( v: (ty::IntVarValue, ty::IntVarValue), ) -> TypeError<'tcx> { let (a, b) = v; - TypeError::IntMismatch(ty::relate::expected_found_bool(a_is_expected, &a, &b)) + TypeError::IntMismatch(ty::relate::expected_found_bool(a_is_expected, a, b)) } fn float_unification_error<'tcx>( @@ -717,5 +717,5 @@ fn float_unification_error<'tcx>( v: (ty::FloatVarValue, ty::FloatVarValue), ) -> TypeError<'tcx> { let (ty::FloatVarValue(a), ty::FloatVarValue(b)) = v; - TypeError::FloatMismatch(ty::relate::expected_found_bool(a_is_expected, &a, &b)) + TypeError::FloatMismatch(ty::relate::expected_found_bool(a_is_expected, a, b)) } diff --git a/src/librustc_middle/ty/relate.rs b/src/librustc_middle/ty/relate.rs index cee04ce8c6a83..7946a27b4d968 100644 --- a/src/librustc_middle/ty/relate.rs +++ b/src/librustc_middle/ty/relate.rs @@ -159,8 +159,8 @@ impl<'tcx> Relate<'tcx> for ty::FnSig<'tcx> { if a.c_variadic != b.c_variadic { return Err(TypeError::VariadicMismatch(expected_found( relation, - &a.c_variadic, - &b.c_variadic, + a.c_variadic, + b.c_variadic, ))); } let unsafety = relation.relate(a.unsafety, b.unsafety)?; @@ -200,7 +200,7 @@ impl<'tcx> Relate<'tcx> for ast::Unsafety { b: ast::Unsafety, ) -> RelateResult<'tcx, ast::Unsafety> { if a != b { - Err(TypeError::UnsafetyMismatch(expected_found(relation, &a, &b))) + Err(TypeError::UnsafetyMismatch(expected_found(relation, a, b))) } else { Ok(a) } @@ -213,7 +213,7 @@ impl<'tcx> Relate<'tcx> for abi::Abi { a: abi::Abi, b: abi::Abi, ) -> RelateResult<'tcx, abi::Abi> { - if a == b { Ok(a) } else { Err(TypeError::AbiMismatch(expected_found(relation, &a, &b))) } + if a == b { Ok(a) } else { Err(TypeError::AbiMismatch(expected_found(relation, a, b))) } } } @@ -226,8 +226,8 @@ impl<'tcx> Relate<'tcx> for ty::ProjectionTy<'tcx> { if a.item_def_id != b.item_def_id { Err(TypeError::ProjectionMismatched(expected_found( relation, - &a.item_def_id, - &b.item_def_id, + a.item_def_id, + b.item_def_id, ))) } else { let substs = relation.relate(a.substs, b.substs)?; @@ -245,8 +245,8 @@ impl<'tcx> Relate<'tcx> for ty::ExistentialProjection<'tcx> { if a.item_def_id != b.item_def_id { Err(TypeError::ProjectionMismatched(expected_found( relation, - &a.item_def_id, - &b.item_def_id, + a.item_def_id, + b.item_def_id, ))) } else { let ty = relation.relate_with_variance(ty::Invariant, a.ty, b.ty)?; @@ -264,7 +264,7 @@ impl<'tcx> Relate<'tcx> for ty::TraitRef<'tcx> { ) -> RelateResult<'tcx, ty::TraitRef<'tcx>> { // Different traits cannot be related. if a.def_id != b.def_id { - Err(TypeError::Traits(expected_found(relation, &a.def_id, &b.def_id))) + Err(TypeError::Traits(expected_found(relation, a.def_id, b.def_id))) } else { let substs = relate_substs(relation, None, a.substs, b.substs)?; Ok(ty::TraitRef { def_id: a.def_id, substs }) @@ -280,7 +280,7 @@ impl<'tcx> Relate<'tcx> for ty::ExistentialTraitRef<'tcx> { ) -> RelateResult<'tcx, ty::ExistentialTraitRef<'tcx>> { // Different traits cannot be related. if a.def_id != b.def_id { - Err(TypeError::Traits(expected_found(relation, &a.def_id, &b.def_id))) + Err(TypeError::Traits(expected_found(relation, a.def_id, b.def_id))) } else { let substs = relate_substs(relation, None, a.substs, b.substs)?; Ok(ty::ExistentialTraitRef { def_id: a.def_id, substs }) @@ -305,6 +305,7 @@ impl<'tcx> Relate<'tcx> for GeneratorWitness<'tcx> { } impl<'tcx> Relate<'tcx> for Ty<'tcx> { + #[inline] fn relate>( relation: &mut R, a: Ty<'tcx>, @@ -421,7 +422,7 @@ pub fn super_relate_tys>( let sz_b = sz_b.try_eval_usize(tcx, relation.param_env()); match (sz_a, sz_b) { (Some(sz_a_val), Some(sz_b_val)) => Err(TypeError::FixedArraySize( - expected_found(relation, &sz_a_val, &sz_b_val), + expected_found(relation, sz_a_val, sz_b_val), )), _ => Err(err), } @@ -440,9 +441,9 @@ pub fn super_relate_tys>( as_.iter().zip(bs).map(|(a, b)| relation.relate(a.expect_ty(), b.expect_ty())), )?) } else if !(as_.is_empty() || bs.is_empty()) { - Err(TypeError::TupleSize(expected_found(relation, &as_.len(), &bs.len()))) + Err(TypeError::TupleSize(expected_found(relation, as_.len(), bs.len()))) } else { - Err(TypeError::Sorts(expected_found(relation, &a, &b))) + Err(TypeError::Sorts(expected_found(relation, a, b))) } } @@ -471,7 +472,7 @@ pub fn super_relate_tys>( Ok(tcx.mk_opaque(a_def_id, substs)) } - _ => Err(TypeError::Sorts(expected_found(relation, &a, &b))), + _ => Err(TypeError::Sorts(expected_found(relation, a, b))), } } @@ -521,10 +522,10 @@ pub fn super_relate_consts>( if a_instance == b_instance { Ok(ConstValue::Scalar(a_val)) } else { - Err(TypeError::ConstMismatch(expected_found(relation, &a, &b))) + Err(TypeError::ConstMismatch(expected_found(relation, a, b))) } } else { - Err(TypeError::ConstMismatch(expected_found(relation, &a, &b))) + Err(TypeError::ConstMismatch(expected_found(relation, a, b))) } } @@ -534,7 +535,7 @@ pub fn super_relate_consts>( if a_bytes == b_bytes { Ok(a_val) } else { - Err(TypeError::ConstMismatch(expected_found(relation, &a, &b))) + Err(TypeError::ConstMismatch(expected_found(relation, a, b))) } } @@ -554,7 +555,7 @@ pub fn super_relate_consts>( Ok(a_val) } else { - Err(TypeError::ConstMismatch(expected_found(relation, &a, &b))) + Err(TypeError::ConstMismatch(expected_found(relation, a, b))) } } // FIXME(const_generics): There are probably some `TyKind`s @@ -564,12 +565,12 @@ pub fn super_relate_consts>( DUMMY_SP, &format!("unexpected consts: a: {:?}, b: {:?}", a, b), ); - Err(TypeError::ConstMismatch(expected_found(relation, &a, &b))) + Err(TypeError::ConstMismatch(expected_found(relation, a, b))) } } } - _ => Err(TypeError::ConstMismatch(expected_found(relation, &a, &b))), + _ => Err(TypeError::ConstMismatch(expected_found(relation, a, b))), }; new_val.map(ty::ConstKind::Value) @@ -584,7 +585,7 @@ pub fn super_relate_consts>( relation.relate_with_variance(ty::Variance::Invariant, a_substs, b_substs)?; Ok(ty::ConstKind::Unevaluated(a_def_id, substs, a_promoted)) } - _ => Err(TypeError::ConstMismatch(expected_found(relation, &a, &b))), + _ => Err(TypeError::ConstMismatch(expected_found(relation, a, b))), }; new_const_val.map(|val| tcx.mk_const(ty::Const { val, ty: a.ty })) } @@ -607,7 +608,7 @@ impl<'tcx> Relate<'tcx> for &'tcx ty::List> { b_v.sort_by(|a, b| a.stable_cmp(tcx, b)); b_v.dedup(); if a_v.len() != b_v.len() { - return Err(TypeError::ExistentialMismatch(expected_found(relation, &a, &b))); + return Err(TypeError::ExistentialMismatch(expected_found(relation, a, b))); } let v = a_v.into_iter().zip(b_v.into_iter()).map(|(ep_a, ep_b)| { @@ -616,7 +617,7 @@ impl<'tcx> Relate<'tcx> for &'tcx ty::List> { (Trait(a), Trait(b)) => Ok(Trait(relation.relate(a, b)?)), (Projection(a), Projection(b)) => Ok(Projection(relation.relate(a, b)?)), (AutoTrait(a), AutoTrait(b)) if a == b => Ok(AutoTrait(a)), - _ => Err(TypeError::ExistentialMismatch(expected_found(relation, &a, &b))), + _ => Err(TypeError::ExistentialMismatch(expected_found(relation, a, b))), } }); Ok(tcx.mk_existential_predicates(v)?) @@ -740,20 +741,14 @@ impl<'tcx> Relate<'tcx> for ty::ProjectionPredicate<'tcx> { /////////////////////////////////////////////////////////////////////////// // Error handling -pub fn expected_found(relation: &mut R, a: &T, b: &T) -> ExpectedFound +pub fn expected_found(relation: &mut R, a: T, b: T) -> ExpectedFound where R: TypeRelation<'tcx>, - T: Clone, { expected_found_bool(relation.a_is_expected(), a, b) } -pub fn expected_found_bool(a_is_expected: bool, a: &T, b: &T) -> ExpectedFound -where - T: Clone, -{ - let a = a.clone(); - let b = b.clone(); +pub fn expected_found_bool(a_is_expected: bool, a: T, b: T) -> ExpectedFound { if a_is_expected { ExpectedFound { expected: a, found: b } } else { From 9cb1ffdd4fc372b18258b1bb12c55fd3c53d33f4 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 5 Jul 2020 18:12:21 +0200 Subject: [PATCH 22/22] variant_count: avoid incorrect dummy implementation --- src/libcore/intrinsics.rs | 6 ------ src/libcore/lib.rs | 2 +- src/libcore/mem/mod.rs | 1 + 3 files changed, 2 insertions(+), 7 deletions(-) diff --git a/src/libcore/intrinsics.rs b/src/libcore/intrinsics.rs index aff4e4a8d9825..b3e43cd799405 100644 --- a/src/libcore/intrinsics.rs +++ b/src/libcore/intrinsics.rs @@ -2004,12 +2004,6 @@ extern "rust-intrinsic" { pub fn ptr_guaranteed_ne(ptr: *const T, other: *const T) -> bool; } -#[rustc_const_unstable(feature = "variant_count", issue = "73662")] -#[cfg(bootstrap)] -pub const fn variant_count() -> usize { - 0 -} - // Some functions are defined here because they accidentally got made // available in this module on stable. See . // (`transmute` also falls into this category, but it cannot be wrapped due to the diff --git a/src/libcore/lib.rs b/src/libcore/lib.rs index 50c56434fa9a1..692d91bd61ddf 100644 --- a/src/libcore/lib.rs +++ b/src/libcore/lib.rs @@ -125,7 +125,7 @@ #![feature(unsized_locals)] #![feature(untagged_unions)] #![feature(unwind_attributes)] -#![feature(variant_count)] +#![cfg_attr(not(bootstrap), feature(variant_count))] #![feature(doc_alias)] #![feature(mmx_target_feature)] #![feature(tbm_target_feature)] diff --git a/src/libcore/mem/mod.rs b/src/libcore/mem/mod.rs index 272088815ece9..0a976a4ca00c9 100644 --- a/src/libcore/mem/mod.rs +++ b/src/libcore/mem/mod.rs @@ -1037,6 +1037,7 @@ pub const fn discriminant(v: &T) -> Discriminant { /// assert_eq!(mem::variant_count::>(), 2); /// ``` #[inline(always)] +#[cfg(not(bootstrap))] #[unstable(feature = "variant_count", issue = "73662")] #[rustc_const_unstable(feature = "variant_count", issue = "73662")] pub const fn variant_count() -> usize {