From ca258c5d1fa13523c40ff8b2f46fa33c79110579 Mon Sep 17 00:00:00 2001 From: Without Boats Date: Mon, 20 Aug 2018 20:18:29 +0200 Subject: [PATCH 01/36] Add Error::source method per RFC 2504. --- src/libstd/error.rs | 67 ++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 66 insertions(+), 1 deletion(-) diff --git a/src/libstd/error.rs b/src/libstd/error.rs index 29534696abc5b..af5a0571c884e 100644 --- a/src/libstd/error.rs +++ b/src/libstd/error.rs @@ -138,7 +138,72 @@ pub trait Error: Debug + Display { /// } /// ``` #[stable(feature = "rust1", since = "1.0.0")] - fn cause(&self) -> Option<&dyn Error> { None } + #[rustc_deprecated(since = "1.33.0", reason = "replaced by Error::source, which can support \ + downcasting")] + fn cause(&self) -> Option<&dyn Error> { + self.source() + } + + /// The lower-level source of this error, if any. + /// + /// # Examples + /// + /// ``` + /// use std::error::Error; + /// use std::fmt; + /// + /// #[derive(Debug)] + /// struct SuperError { + /// side: SuperErrorSideKick, + /// } + /// + /// impl fmt::Display for SuperError { + /// fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + /// write!(f, "SuperError is here!") + /// } + /// } + /// + /// impl Error for SuperError { + /// fn description(&self) -> &str { + /// "I'm the superhero of errors" + /// } + /// + /// fn source(&self) -> Option<&dyn (Error + 'static)> { + /// Some(&self.side) + /// } + /// } + /// + /// #[derive(Debug)] + /// struct SuperErrorSideKick; + /// + /// impl fmt::Display for SuperErrorSideKick { + /// fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + /// write!(f, "SuperErrorSideKick is here!") + /// } + /// } + /// + /// impl Error for SuperErrorSideKick { + /// fn description(&self) -> &str { + /// "I'm SuperError side kick" + /// } + /// } + /// + /// fn get_super_error() -> Result<(), SuperError> { + /// Err(SuperError { side: SuperErrorSideKick }) + /// } + /// + /// fn main() { + /// match get_super_error() { + /// Err(e) => { + /// println!("Error: {}", e.description()); + /// println!("Caused by: {}", e.source().unwrap()); + /// } + /// _ => println!("No error"), + /// } + /// } + /// ``` + #[stable(feature = "rust1", since = "1.30.0")] + fn source(&self) -> Option<&(dyn Error + 'static)> { None } /// Get the `TypeId` of `self` #[doc(hidden)] From a49e1ed0cf3300a998499a125ed4b4d9464bc0cd Mon Sep 17 00:00:00 2001 From: Without Boats Date: Mon, 20 Aug 2018 23:27:25 +0200 Subject: [PATCH 02/36] Fix feature name. --- src/libstd/error.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libstd/error.rs b/src/libstd/error.rs index af5a0571c884e..86d45e03f2544 100644 --- a/src/libstd/error.rs +++ b/src/libstd/error.rs @@ -202,7 +202,7 @@ pub trait Error: Debug + Display { /// } /// } /// ``` - #[stable(feature = "rust1", since = "1.30.0")] + #[stable(feature = "error_source", since = "1.30.0")] fn source(&self) -> Option<&(dyn Error + 'static)> { None } /// Get the `TypeId` of `self` From e2e4f57bf84ca3cbdb91ba9d235c12b46666d090 Mon Sep 17 00:00:00 2001 From: Without Boats Date: Tue, 21 Aug 2018 00:58:52 +0200 Subject: [PATCH 03/36] Correctly parenthesize dyn Error + 'static. --- src/libstd/error.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libstd/error.rs b/src/libstd/error.rs index 86d45e03f2544..3de4a1bd4170b 100644 --- a/src/libstd/error.rs +++ b/src/libstd/error.rs @@ -168,7 +168,7 @@ pub trait Error: Debug + Display { /// "I'm the superhero of errors" /// } /// - /// fn source(&self) -> Option<&dyn (Error + 'static)> { + /// fn source(&self) -> Option<&(dyn Error + 'static)> { /// Some(&self.side) /// } /// } From fa75111043975e0da885a72b72b6697dda38642d Mon Sep 17 00:00:00 2001 From: Philipp Krones Date: Tue, 28 Aug 2018 20:43:10 +0200 Subject: [PATCH 04/36] Also link Clippy repo in the CONTRIBUTING.md file --- CONTRIBUTING.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index ea9f2c1943005..21b14d011f911 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -405,7 +405,8 @@ before the PR is merged. [breaking-tools-built-with-the-compiler]: #breaking-tools-built-with-the-compiler Rust's build system builds a number of tools that make use of the -internals of the compiler. This includes clippy, +internals of the compiler. This includes +[Clippy](https://github.com/rust-lang-nursery/rust-clippy), [RLS](https://github.com/rust-lang-nursery/rls) and [rustfmt](https://github.com/rust-lang-nursery/rustfmt). If these tools break because of your changes, you may run into a sort of "chicken and egg" From 0902fc88db6d51f3f22735d26a2b2e8caedd25bc Mon Sep 17 00:00:00 2001 From: Philip Daniels Date: Tue, 28 Aug 2018 22:05:00 +0100 Subject: [PATCH 05/36] Add rust-gdbgui script. This script invokes the gdbgui graphical GDB front-end with the Rust pretty printers loaded. The script does not install gdbgui, that must be done manually. --- src/etc/rust-gdbgui | 65 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 65 insertions(+) create mode 100755 src/etc/rust-gdbgui diff --git a/src/etc/rust-gdbgui b/src/etc/rust-gdbgui new file mode 100755 index 0000000000000..6786fe015bca1 --- /dev/null +++ b/src/etc/rust-gdbgui @@ -0,0 +1,65 @@ +#!/bin/sh +# Copyright 2014 The Rust Project Developers. See the COPYRIGHT +# file at the top-level directory of this distribution and at +# http://rust-lang.org/COPYRIGHT. +# +# Licensed under the Apache License, Version 2.0 or the MIT license +# , at your +# option. This file may not be copied, modified, or distributed +# except according to those terms. + +# Exit if anything fails +set -e + +if [ $# -eq 0 ] || [ "$1" = "-h" ] || [ "$1" = "-help" ] || [ "$1" = "--help" ]; then + echo " +rust-gdbgui +=========== +gdbgui - https://gdbgui.com - is a graphical front-end to GDB +that runs in a browser. This script invokes gdbgui with the Rust +pretty printers loaded. + +Simple usage : rust-gdbgui target\debug\myprog +With arguments: rust-gdbgui 'target\debug\myprog arg1 arg2...' + (note the quotes) + + +Hints +===== +gdbgui won't be able to find the rust 'main' method automatically, so +in its options make sure to disable the 'Add breakpoint to main after +loading executable' setting to avoid a 'File not found: main' warning +on startup. + +Instead, type 'main' into the file browser and you should get +auto-completion on the filename. Just pick 'main.rs', add a breakpoint +by clicking in the line number gutter, and type 'r' or hit the Restart +icon to start your program running. +" + exit 0 +fi + +# Find out where the pretty printer Python module is +RUSTC_SYSROOT=`rustc --print=sysroot` +GDB_PYTHON_MODULE_DIRECTORY="$RUSTC_SYSROOT/lib/rustlib/etc" + +# Set the environment variable `RUST_GDB` to overwrite the call to a +# different/specific command (defaults to `gdb`). +RUST_GDB="${RUST_GDB:-gdb}" + +# Set the environment variable `RUST_GDBGUI` to overwrite the call to a +# different/specific command (defaults to `gdbgui`). +RUST_GDBGUI="${RUST_GDBGUI:-gdbgui}" + +# These arguments get passed through to GDB and make it load the +# Rust pretty printers. +GDB_ARGS="--directory=\"$GDB_PYTHON_MODULE_DIRECTORY\" -iex \"add-auto-load-safe-path $GDB_PYTHON_MODULE_DIRECTORY\"" + +# Finally we execute gdbgui. +PYTHONPATH="$PYTHONPATH:$GDB_PYTHON_MODULE_DIRECTORY" \ + exec ${RUST_GDBGUI} \ + --gdb ${RUST_GDB} \ + --gdb-args "${GDB_ARGS}" \ + "${@}" + From 50057ee3a364d51f5dee611ebd1fd3a05ac77ff5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= Date: Wed, 29 Aug 2018 12:18:05 +0200 Subject: [PATCH 06/36] bench: libcore: fix build failure of any.rs benchmark (use "dyn Any") --- src/libcore/benches/any.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libcore/benches/any.rs b/src/libcore/benches/any.rs index 67e02cf9509b6..f4f01eb1cf5d2 100644 --- a/src/libcore/benches/any.rs +++ b/src/libcore/benches/any.rs @@ -15,7 +15,7 @@ use test::{Bencher, black_box}; fn bench_downcast_ref(b: &mut Bencher) { b.iter(|| { let mut x = 0; - let mut y = &mut x as &mut Any; + let mut y = &mut x as &mut dyn Any; black_box(&mut y); black_box(y.downcast_ref::() == Some(&0)); }); From 5399616f1d98b4bcc1da87af15f75c95e3c2288b Mon Sep 17 00:00:00 2001 From: Otto Rask Date: Wed, 29 Aug 2018 13:20:56 +0300 Subject: [PATCH 07/36] Make Arc cloning mechanics clearer in module docs Add some more wording to module documentation regarding how `Arc::clone()` works, as some users have assumed cloning Arc's to work via dereferencing to inner value as follows: use std::sync::Arc; let myarc = Arc::new(1); let myarcref = myarc.clone(); assert!(1 == myarcref); Instead of the actual mechanic of referencing the existing Arc value: use std::sync::Arg; let myarc = Arc::new(1); let myarcref = myarc.clone(); assert!(myarcref == &myarc); // not sure if assert could assert this in the real world --- src/liballoc/sync.rs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/liballoc/sync.rs b/src/liballoc/sync.rs index 2cd7898f4c781..176743fdd1d38 100644 --- a/src/liballoc/sync.rs +++ b/src/liballoc/sync.rs @@ -49,9 +49,9 @@ const MAX_REFCOUNT: usize = (isize::MAX) as usize; /// /// The type `Arc` provides shared ownership of a value of type `T`, /// allocated in the heap. Invoking [`clone`][clone] on `Arc` produces -/// a new pointer to the same value in the heap. When the last `Arc` -/// pointer to a given value is destroyed, the pointed-to value is -/// also destroyed. +/// a new pointer to the same `Arc` reference value in the heap. When the last +/// `Arc` pointer to a given value is destroyed, the pointed-to value is also +/// destroyed. /// /// Shared references in Rust disallow mutation by default, and `Arc` is no /// exception: you cannot generally obtain a mutable reference to something @@ -107,7 +107,8 @@ const MAX_REFCOUNT: usize = (isize::MAX) as usize; /// // The two syntaxes below are equivalent. /// let a = foo.clone(); /// let b = Arc::clone(&foo); -/// // a and b both point to the same memory location as foo. +/// // a and b both point to the same memory location where foo resides +/// // (not where the value wrapped by foo resides). /// ``` /// /// The [`Arc::clone(&from)`] syntax is the most idiomatic because it conveys more explicitly From 3b98571b325c3fc8c42aa2209333bfec9d838718 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Wed, 29 Aug 2018 23:01:57 +0200 Subject: [PATCH 08/36] Prevent duplicated impl on foreign types --- src/librustdoc/html/render.rs | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index 8fb3b570f8a4b..741efd8becd4e 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -2943,12 +2943,16 @@ fn item_trait( ")?; + let mut foreign_cache = FxHashSet(); for implementor in foreign { - let assoc_link = AssocItemLink::GotoSource( - implementor.impl_item.def_id, &implementor.inner_impl().provided_trait_methods - ); - render_impl(w, cx, &implementor, assoc_link, - RenderMode::Normal, implementor.impl_item.stable_since(), false)?; + if foreign_cache.insert(implementor.inner_impl().to_string()) { + let assoc_link = AssocItemLink::GotoSource( + implementor.impl_item.def_id, + &implementor.inner_impl().provided_trait_methods + ); + render_impl(w, cx, &implementor, assoc_link, + RenderMode::Normal, implementor.impl_item.stable_since(), false)?; + } } } From 7a083ca25f14833d704d2efba5ca9b431f6c65ad Mon Sep 17 00:00:00 2001 From: F001 Date: Thu, 30 Aug 2018 12:18:11 +0800 Subject: [PATCH 09/36] introduce Guard enum --- src/librustc/cfg/construct.rs | 5 +++-- src/librustc/hir/intravisit.rs | 6 +++++- src/librustc/hir/lowering.rs | 5 ++++- src/librustc/hir/mod.rs | 7 ++++++- src/librustc/hir/print.rs | 12 ++++++++---- src/librustc/ich/impls_hir.rs | 4 ++++ src/librustc/middle/expr_use_visitor.rs | 4 +++- src/librustc/middle/liveness.rs | 7 ++++++- src/librustc/middle/region.rs | 6 ++++-- src/librustc_mir/build/matches/mod.rs | 6 ++++-- src/librustc_mir/hair/cx/expr.rs | 5 ++++- src/librustc_mir/hair/mod.rs | 7 ++++++- src/librustc_mir/hair/pattern/check_match.rs | 17 +++++++++++++---- src/librustc_passes/rvalue_promotion.rs | 2 +- src/librustc_resolve/lib.rs | 5 ++++- src/librustc_save_analysis/dump_visitor.rs | 5 ++++- src/librustc_typeck/check/_match.rs | 6 ++++-- src/libsyntax/ast.rs | 7 ++++++- src/libsyntax/fold.rs | 12 +++++++++++- src/libsyntax/parse/parser.rs | 4 ++-- src/libsyntax/print/pprust.rs | 12 ++++++++---- src/libsyntax/visit.rs | 6 +++++- 22 files changed, 115 insertions(+), 35 deletions(-) diff --git a/src/librustc/cfg/construct.rs b/src/librustc/cfg/construct.rs index 98cfa094c169a..1b97480920321 100644 --- a/src/librustc/cfg/construct.rs +++ b/src/librustc/cfg/construct.rs @@ -488,8 +488,9 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> { // expression to target let guard_start = self.add_dummy_node(&[pat_exit]); // Visit the guard expression - let guard_exit = self.expr(&guard, guard_start); - + let guard_exit = match guard { + hir::Guard::If(ref e) => self.expr(e, guard_start), + }; // #47295: We used to have very special case code // here for when a pair of arms are both formed // solely from constants, and if so, not add these diff --git a/src/librustc/hir/intravisit.rs b/src/librustc/hir/intravisit.rs index d853d3d9a7fb4..8129cc18d46c2 100644 --- a/src/librustc/hir/intravisit.rs +++ b/src/librustc/hir/intravisit.rs @@ -1102,7 +1102,11 @@ pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr) { pub fn walk_arm<'v, V: Visitor<'v>>(visitor: &mut V, arm: &'v Arm) { walk_list!(visitor, visit_pat, &arm.pats); - walk_list!(visitor, visit_expr, &arm.guard); + if let Some(ref g) = arm.guard { + match g { + Guard::If(ref e) => visitor.visit_expr(e), + } + } visitor.visit_expr(&arm.body); walk_list!(visitor, visit_attribute, &arm.attrs); } diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index b5f5f4d5c1179..bb4fabf1c3e5e 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -1053,7 +1053,10 @@ impl<'a> LoweringContext<'a> { hir::Arm { attrs: self.lower_attrs(&arm.attrs), pats: arm.pats.iter().map(|x| self.lower_pat(x)).collect(), - guard: arm.guard.as_ref().map(|ref x| P(self.lower_expr(x))), + guard: match arm.guard { + Some(Guard::If(ref x)) => Some(hir::Guard::If(P(self.lower_expr(x)))), + _ => None, + }, body: P(self.lower_expr(&arm.body)), } } diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs index 43cc33f422f53..a4806502ab383 100644 --- a/src/librustc/hir/mod.rs +++ b/src/librustc/hir/mod.rs @@ -1204,10 +1204,15 @@ impl DeclKind { pub struct Arm { pub attrs: HirVec, pub pats: HirVec>, - pub guard: Option>, + pub guard: Option, pub body: P, } +#[derive(Clone, RustcEncodable, RustcDecodable, Debug)] +pub enum Guard { + If(P), +} + #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] pub struct Field { pub id: NodeId, diff --git a/src/librustc/hir/print.rs b/src/librustc/hir/print.rs index 9fe462e65a2cb..193fff1f5b68e 100644 --- a/src/librustc/hir/print.rs +++ b/src/librustc/hir/print.rs @@ -1951,10 +1951,14 @@ impl<'a> State<'a> { self.print_pat(&p)?; } self.s.space()?; - if let Some(ref e) = arm.guard { - self.word_space("if")?; - self.print_expr(&e)?; - self.s.space()?; + if let Some(ref g) = arm.guard { + match g { + hir::Guard::If(e) => { + self.word_space("if")?; + self.print_expr(&e)?; + self.s.space()?; + } + } } self.word_space("=>")?; diff --git a/src/librustc/ich/impls_hir.rs b/src/librustc/ich/impls_hir.rs index 76e57558bfe07..c780ede75a42f 100644 --- a/src/librustc/ich/impls_hir.rs +++ b/src/librustc/ich/impls_hir.rs @@ -493,6 +493,10 @@ impl_stable_hash_for!(struct hir::Arm { body }); +impl_stable_hash_for!(enum hir::Guard { + If(expr), +}); + impl_stable_hash_for!(struct hir::Field { id -> _, ident, diff --git a/src/librustc/middle/expr_use_visitor.rs b/src/librustc/middle/expr_use_visitor.rs index 5beafe2b601bf..705237aa832f0 100644 --- a/src/librustc/middle/expr_use_visitor.rs +++ b/src/librustc/middle/expr_use_visitor.rs @@ -792,7 +792,9 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> { } if let Some(ref guard) = arm.guard { - self.consume_expr(&guard); + match guard { + hir::Guard::If(ref e) => self.consume_expr(e), + } } self.consume_expr(&arm.body); diff --git a/src/librustc/middle/liveness.rs b/src/librustc/middle/liveness.rs index 7d9590ee578e6..9850e2e8b1c57 100644 --- a/src/librustc/middle/liveness.rs +++ b/src/librustc/middle/liveness.rs @@ -1028,7 +1028,12 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { let body_succ = self.propagate_through_expr(&arm.body, succ); let guard_succ = - self.propagate_through_opt_expr(arm.guard.as_ref().map(|e| &**e), body_succ); + self.propagate_through_opt_expr( + arm.guard.as_ref().map(|g| + match g { + hir::Guard::If(e) => &**e, + }), + body_succ); // only consider the first pattern; any later patterns must have // the same bindings, and we also consider the first pattern to be // the "authoritative" set of ids diff --git a/src/librustc/middle/region.rs b/src/librustc/middle/region.rs index be1d93dbad1b8..5302bc806c721 100644 --- a/src/librustc/middle/region.rs +++ b/src/librustc/middle/region.rs @@ -884,8 +884,10 @@ fn resolve_block<'a, 'tcx>(visitor: &mut RegionResolutionVisitor<'a, 'tcx>, blk: fn resolve_arm<'a, 'tcx>(visitor: &mut RegionResolutionVisitor<'a, 'tcx>, arm: &'tcx hir::Arm) { visitor.terminating_scopes.insert(arm.body.hir_id.local_id); - if let Some(ref expr) = arm.guard { - visitor.terminating_scopes.insert(expr.hir_id.local_id); + if let Some(ref g) = arm.guard { + match g { + hir::Guard::If(ref expr) => visitor.terminating_scopes.insert(expr.hir_id.local_id), + }; } intravisit::walk_arm(visitor, arm); diff --git a/src/librustc_mir/build/matches/mod.rs b/src/librustc_mir/build/matches/mod.rs index b317bb7cff0e3..d3e67ea7b7d71 100644 --- a/src/librustc_mir/build/matches/mod.rs +++ b/src/librustc_mir/build/matches/mod.rs @@ -453,7 +453,7 @@ pub struct Candidate<'pat, 'tcx:'pat> { bindings: Vec>, // ...and the guard must be evaluated... - guard: Option>, + guard: Option>, // ...and then we branch to arm with this index. arm_index: usize, @@ -998,7 +998,9 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { // the block to branch to if the guard fails; if there is no // guard, this block is simply unreachable - let guard = self.hir.mirror(guard); + let guard = match guard { + Guard::If(e) => self.hir.mirror(e), + }; let source_info = self.source_info(guard.span); let cond = unpack!(block = self.as_local_operand(block, guard)); if autoref { diff --git a/src/librustc_mir/hair/cx/expr.rs b/src/librustc_mir/hair/cx/expr.rs index b60da286d9555..d90e9ed329b57 100644 --- a/src/librustc_mir/hair/cx/expr.rs +++ b/src/librustc_mir/hair/cx/expr.rs @@ -736,7 +736,10 @@ impl ToBorrowKind for hir::Mutability { fn convert_arm<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, arm: &'tcx hir::Arm) -> Arm<'tcx> { Arm { patterns: arm.pats.iter().map(|p| cx.pattern_from_hir(p)).collect(), - guard: arm.guard.to_ref(), + guard: match arm.guard { + Some(hir::Guard::If(ref e)) => Some(Guard::If(e.to_ref())), + _ => None, + }, body: arm.body.to_ref(), // BUG: fix this lint_level: LintLevel::Inherited, diff --git a/src/librustc_mir/hair/mod.rs b/src/librustc_mir/hair/mod.rs index c39aa9ca7806d..ab272763d8e8a 100644 --- a/src/librustc_mir/hair/mod.rs +++ b/src/librustc_mir/hair/mod.rs @@ -304,11 +304,16 @@ pub struct FruInfo<'tcx> { #[derive(Clone, Debug)] pub struct Arm<'tcx> { pub patterns: Vec>, - pub guard: Option>, + pub guard: Option>, pub body: ExprRef<'tcx>, pub lint_level: LintLevel, } +#[derive(Clone, Debug)] +pub enum Guard<'tcx> { + If(ExprRef<'tcx>), +} + #[derive(Copy, Clone, Debug)] pub enum LogicalOp { And, diff --git a/src/librustc_mir/hair/pattern/check_match.rs b/src/librustc_mir/hair/pattern/check_match.rs index 35f9dcee99f82..986bbced020bf 100644 --- a/src/librustc_mir/hair/pattern/check_match.rs +++ b/src/librustc_mir/hair/pattern/check_match.rs @@ -208,7 +208,9 @@ impl<'a, 'tcx> MatchVisitor<'a, 'tcx> { } (pattern, &**pat) }).collect(), - arm.guard.as_ref().map(|e| &**e) + arm.guard.as_ref().map(|g| match g { + hir::Guard::If(ref e) => &**e, + }) )).collect(); // Bail out early if inlining failed. @@ -575,12 +577,19 @@ fn check_legality_of_move_bindings(cx: &MatchVisitor, /// assign. /// /// FIXME: this should be done by borrowck. -fn check_for_mutation_in_guard(cx: &MatchVisitor, guard: &hir::Expr) { +fn check_for_mutation_in_guard(cx: &MatchVisitor, guard: &hir::Guard) { let mut checker = MutationChecker { cx, }; - ExprUseVisitor::new(&mut checker, cx.tcx, cx.param_env, cx.region_scope_tree, cx.tables, None) - .walk_expr(guard); + match guard { + hir::Guard::If(expr) => + ExprUseVisitor::new(&mut checker, + cx.tcx, + cx.param_env, + cx.region_scope_tree, + cx.tables, + None).walk_expr(expr), + }; } struct MutationChecker<'a, 'tcx: 'a> { diff --git a/src/librustc_passes/rvalue_promotion.rs b/src/librustc_passes/rvalue_promotion.rs index 114fd8754a21f..864d9e1a16f06 100644 --- a/src/librustc_passes/rvalue_promotion.rs +++ b/src/librustc_passes/rvalue_promotion.rs @@ -582,7 +582,7 @@ fn check_expr_kind<'a, 'tcx>( for index in hirvec_arm.iter() { let _ = v.check_expr(&*index.body); match index.guard { - Some(ref expr) => { + Some(hir::Guard::If(ref expr)) => { let _ = v.check_expr(&expr); }, None => {}, diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 71a7fde202942..96df0cbfc07c7 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -2691,7 +2691,10 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> { // This has to happen *after* we determine which pat_idents are variants self.check_consistent_bindings(&arm.pats); - walk_list!(self, visit_expr, &arm.guard); + match arm.guard { + Some(ast::Guard::If(ref expr)) => self.visit_expr(expr), + _ => {} + } self.visit_expr(&arm.body); self.ribs[ValueNS].pop(); diff --git a/src/librustc_save_analysis/dump_visitor.rs b/src/librustc_save_analysis/dump_visitor.rs index dc9310cdcdaa4..565986066dad2 100644 --- a/src/librustc_save_analysis/dump_visitor.rs +++ b/src/librustc_save_analysis/dump_visitor.rs @@ -1663,7 +1663,10 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> Visitor<'l> for DumpVisitor<'l, 'tc fn visit_arm(&mut self, arm: &'l ast::Arm) { self.process_var_decl_multi(&arm.pats); - walk_list!(self, visit_expr, &arm.guard); + match arm.guard { + Some(ast::Guard::If(ref expr)) => self.visit_expr(expr), + _ => {} + } self.visit_expr(&arm.body); } diff --git a/src/librustc_typeck/check/_match.rs b/src/librustc_typeck/check/_match.rs index c14a07b7cf5d0..d8c090dd6a7e0 100644 --- a/src/librustc_typeck/check/_match.rs +++ b/src/librustc_typeck/check/_match.rs @@ -663,9 +663,11 @@ https://doc.rust-lang.org/reference/types.html#trait-objects"); }; for (i, (arm, pats_diverge)) in arms.iter().zip(all_arm_pats_diverge).enumerate() { - if let Some(ref e) = arm.guard { + if let Some(ref g) = arm.guard { self.diverges.set(pats_diverge); - self.check_expr_has_type_or_error(e, tcx.types.bool); + match g { + hir::Guard::If(e) => self.check_expr_has_type_or_error(e, tcx.types.bool), + }; } self.diverges.set(pats_diverge); diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index ec6ac86ba6bd3..63aaa487bf898 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -857,10 +857,15 @@ pub struct Local { pub struct Arm { pub attrs: Vec, pub pats: Vec>, - pub guard: Option>, + pub guard: Option, pub body: P, } +#[derive(Clone, RustcEncodable, RustcDecodable, Debug)] +pub enum Guard { + If(P), +} + #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] pub struct Field { pub ident: Ident, diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs index 50a49e2f548e8..82dae3bc97324 100644 --- a/src/libsyntax/fold.rs +++ b/src/libsyntax/fold.rs @@ -117,6 +117,10 @@ pub trait Folder : Sized { noop_fold_arm(a, self) } + fn fold_guard(&mut self, g: Guard) -> Guard { + noop_fold_guard(g, self) + } + fn fold_pat(&mut self, p: P) -> P { noop_fold_pat(p, self) } @@ -353,11 +357,17 @@ pub fn noop_fold_arm(Arm {attrs, pats, guard, body}: Arm, Arm { attrs: fold_attrs(attrs, fld), pats: pats.move_map(|x| fld.fold_pat(x)), - guard: guard.map(|x| fld.fold_expr(x)), + guard: guard.map(|x| fld.fold_guard(x)), body: fld.fold_expr(body), } } +pub fn noop_fold_guard(g: Guard, fld: &mut T) -> Guard { + match g { + Guard::If(e) => Guard::If(fld.fold_expr(e)), + } +} + pub fn noop_fold_ty_binding(b: TypeBinding, fld: &mut T) -> TypeBinding { TypeBinding { id: fld.new_id(b.id), diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index b1e2e69863d97..ceef03bb6536e 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -12,7 +12,7 @@ use rustc_target::spec::abi::{self, Abi}; use ast::{AngleBracketedArgs, ParenthesisedArgs, AttrStyle, BareFnTy}; use ast::{GenericBound, TraitBoundModifier}; use ast::Unsafety; -use ast::{Mod, AnonConst, Arg, Arm, Attribute, BindingMode, TraitItemKind}; +use ast::{Mod, AnonConst, Arg, Arm, Guard, Attribute, BindingMode, TraitItemKind}; use ast::Block; use ast::{BlockCheckMode, CaptureBy, Movability}; use ast::{Constness, Crate}; @@ -3509,7 +3509,7 @@ impl<'a> Parser<'a> { self.eat(&token::BinOp(token::Or)); let pats = self.parse_pats()?; let guard = if self.eat_keyword(keywords::If) { - Some(self.parse_expr()?) + Some(Guard::If(self.parse_expr()?)) } else { None }; diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index 3065e795ed81f..da3ba928effd7 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -2704,10 +2704,14 @@ impl<'a> State<'a> { self.print_outer_attributes(&arm.attrs)?; self.print_pats(&arm.pats)?; self.s.space()?; - if let Some(ref e) = arm.guard { - self.word_space("if")?; - self.print_expr(e)?; - self.s.space()?; + if let Some(ref g) = arm.guard { + match g { + ast::Guard::If(ref e) => { + self.word_space("if")?; + self.print_expr(e)?; + self.s.space()?; + } + } } self.word_space("=>")?; diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs index 51be129737e56..fccc80b668f3e 100644 --- a/src/libsyntax/visit.rs +++ b/src/libsyntax/visit.rs @@ -819,7 +819,11 @@ pub fn walk_expr<'a, V: Visitor<'a>>(visitor: &mut V, expression: &'a Expr) { pub fn walk_arm<'a, V: Visitor<'a>>(visitor: &mut V, arm: &'a Arm) { walk_list!(visitor, visit_pat, &arm.pats); - walk_list!(visitor, visit_expr, &arm.guard); + if let Some(ref g) = &arm.guard { + match g { + Guard::If(ref e) => visitor.visit_expr(e), + } + } visitor.visit_expr(&arm.body); walk_list!(visitor, visit_attribute, &arm.attrs); } From 60202199936365e7b2adc70189fbaa664ce729a6 Mon Sep 17 00:00:00 2001 From: Otto Rask Date: Thu, 30 Aug 2018 12:20:41 +0300 Subject: [PATCH 10/36] Rephrase Arc documentation changes regarding clones Make it clearer that `Arc::clone()` in fact creates a whole new Arc with the internal pointer pointing to the same location as the source Arc. --- src/liballoc/sync.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/liballoc/sync.rs b/src/liballoc/sync.rs index 176743fdd1d38..72a4740b15660 100644 --- a/src/liballoc/sync.rs +++ b/src/liballoc/sync.rs @@ -49,8 +49,9 @@ const MAX_REFCOUNT: usize = (isize::MAX) as usize; /// /// The type `Arc` provides shared ownership of a value of type `T`, /// allocated in the heap. Invoking [`clone`][clone] on `Arc` produces -/// a new pointer to the same `Arc` reference value in the heap. When the last -/// `Arc` pointer to a given value is destroyed, the pointed-to value is also +/// a new `Arc` instance, which points to the same value on the heap as the +/// source `Arc`, while increasing a reference count. When the last `Arc` +/// pointer to a given value is destroyed, the pointed-to value is also /// destroyed. /// /// Shared references in Rust disallow mutation by default, and `Arc` is no @@ -107,8 +108,7 @@ const MAX_REFCOUNT: usize = (isize::MAX) as usize; /// // The two syntaxes below are equivalent. /// let a = foo.clone(); /// let b = Arc::clone(&foo); -/// // a and b both point to the same memory location where foo resides -/// // (not where the value wrapped by foo resides). +/// // a and b both point to the same memory location as foo /// ``` /// /// The [`Arc::clone(&from)`] syntax is the most idiomatic because it conveys more explicitly From 251f26298a5484b1cf6cd505c555d71d34a75010 Mon Sep 17 00:00:00 2001 From: Basile Desloges Date: Wed, 29 Aug 2018 17:45:55 +0200 Subject: [PATCH 11/36] Add regression test for issue #52060 --- src/test/ui/issues/issue-52060.rs | 8 ++++++++ src/test/ui/issues/issue-52060.stderr | 17 +++++++++++++++++ 2 files changed, 25 insertions(+) create mode 100644 src/test/ui/issues/issue-52060.rs create mode 100644 src/test/ui/issues/issue-52060.stderr diff --git a/src/test/ui/issues/issue-52060.rs b/src/test/ui/issues/issue-52060.rs new file mode 100644 index 0000000000000..54eff228934e3 --- /dev/null +++ b/src/test/ui/issues/issue-52060.rs @@ -0,0 +1,8 @@ +// Regression test for https://github.com/rust-lang/rust/issues/52060 +// The compiler shouldn't ICE in this case +static A: &'static [u32] = &[1]; +static B: [u32; 1] = [0; A.len()]; +//~^ ERROR [E0013] +//~| ERROR `core::slice::::len` is not yet stable as a const fn + +fn main() {} diff --git a/src/test/ui/issues/issue-52060.stderr b/src/test/ui/issues/issue-52060.stderr new file mode 100644 index 0000000000000..988bfd480e6ad --- /dev/null +++ b/src/test/ui/issues/issue-52060.stderr @@ -0,0 +1,17 @@ +error[E0013]: constants cannot refer to statics, use a constant instead + --> $DIR/issue-52060.rs:4:26 + | +LL | static B: [u32; 1] = [0; A.len()]; + | ^ + +error: `core::slice::::len` is not yet stable as a const fn + --> $DIR/issue-52060.rs:4:26 + | +LL | static B: [u32; 1] = [0; A.len()]; + | ^^^^^^^ + | + = help: in Nightly builds, add `#![feature(const_slice_len)]` to the crate attributes to enable + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0013`. From 47aa4758664ee7b054261f09de3375cfb3cc926d Mon Sep 17 00:00:00 2001 From: Philip Daniels Date: Thu, 30 Aug 2018 20:23:41 +0100 Subject: [PATCH 12/36] Fix direction of slashes in the help text example. --- src/etc/rust-gdbgui | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/etc/rust-gdbgui b/src/etc/rust-gdbgui index 6786fe015bca1..7e179ba927dff 100755 --- a/src/etc/rust-gdbgui +++ b/src/etc/rust-gdbgui @@ -20,8 +20,8 @@ gdbgui - https://gdbgui.com - is a graphical front-end to GDB that runs in a browser. This script invokes gdbgui with the Rust pretty printers loaded. -Simple usage : rust-gdbgui target\debug\myprog -With arguments: rust-gdbgui 'target\debug\myprog arg1 arg2...' +Simple usage : rust-gdbgui target/debug/myprog +With arguments: rust-gdbgui 'target/debug/myprog arg1 arg2...' (note the quotes) @@ -32,7 +32,7 @@ in its options make sure to disable the 'Add breakpoint to main after loading executable' setting to avoid a 'File not found: main' warning on startup. -Instead, type 'main' into the file browser and you should get +Instead, type 'main' into gdbgui's file browser and you should get auto-completion on the filename. Just pick 'main.rs', add a breakpoint by clicking in the line number gutter, and type 'r' or hit the Restart icon to start your program running. From 70ed4f972e73f5fe8c11c4ac0cf98d13b30083b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Thu, 30 Aug 2018 16:00:09 -0700 Subject: [PATCH 13/36] Point at def span on incorrect panic or alloc error handler --- src/librustc_typeck/check/mod.rs | 2 ++ .../alloc-error/alloc-error-handler-bad-signature-3.stderr | 6 ++---- .../ui/panic-handler/panic-handler-bad-signature-3.stderr | 6 ++---- 3 files changed, 6 insertions(+), 8 deletions(-) diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index bbb45c04e4e98..9db0f9052d79f 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -1178,6 +1178,7 @@ fn check_fn<'a, 'gcx, 'tcx>(inherited: &'a Inherited<'a, 'gcx, 'tcx>, } } } else { + let span = fcx.tcx.sess.source_map().def_span(span); fcx.tcx.sess.span_err(span, "function should have one argument"); } } else { @@ -1226,6 +1227,7 @@ fn check_fn<'a, 'gcx, 'tcx>(inherited: &'a Inherited<'a, 'gcx, 'tcx>, } } } else { + let span = fcx.tcx.sess.source_map().def_span(span); fcx.tcx.sess.span_err(span, "function should have one argument"); } } else { diff --git a/src/test/ui/alloc-error/alloc-error-handler-bad-signature-3.stderr b/src/test/ui/alloc-error/alloc-error-handler-bad-signature-3.stderr index 9b792c46c24b9..e7885537b06bb 100644 --- a/src/test/ui/alloc-error/alloc-error-handler-bad-signature-3.stderr +++ b/src/test/ui/alloc-error/alloc-error-handler-bad-signature-3.stderr @@ -1,10 +1,8 @@ error: function should have one argument --> $DIR/alloc-error-handler-bad-signature-3.rs:20:1 | -LL | / fn oom() -> ! { //~ ERROR function should have one argument -LL | | loop {} -LL | | } - | |_^ +LL | fn oom() -> ! { //~ ERROR function should have one argument + | ^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/panic-handler/panic-handler-bad-signature-3.stderr b/src/test/ui/panic-handler/panic-handler-bad-signature-3.stderr index 0eb0d4e10004b..5d0395e17f54d 100644 --- a/src/test/ui/panic-handler/panic-handler-bad-signature-3.stderr +++ b/src/test/ui/panic-handler/panic-handler-bad-signature-3.stderr @@ -1,10 +1,8 @@ error: function should have one argument --> $DIR/panic-handler-bad-signature-3.rs:20:1 | -LL | / fn panic() -> ! { //~ ERROR function should have one argument -LL | | loop {} -LL | | } - | |_^ +LL | fn panic() -> ! { //~ ERROR function should have one argument + | ^^^^^^^^^^^^^^^ error: aborting due to previous error From da9ba98fad3a8278d8c6ff570d74592bc10e9870 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Thu, 30 Aug 2018 16:01:08 -0700 Subject: [PATCH 14/36] Format code --- src/librustc_mir/hair/pattern/check_match.rs | 16 ++++++++++------ src/librustc_save_analysis/span_utils.rs | 3 +-- 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/src/librustc_mir/hair/pattern/check_match.rs b/src/librustc_mir/hair/pattern/check_match.rs index 604cc61a17ecb..890a7b5cda2a7 100644 --- a/src/librustc_mir/hair/pattern/check_match.rs +++ b/src/librustc_mir/hair/pattern/check_match.rs @@ -540,12 +540,16 @@ fn check_legality_of_move_bindings(cx: &MatchVisitor, "cannot bind by-move into a pattern guard") .span_label(p.span, "moves value into pattern guard") .emit(); - } else if by_ref_span.is_some() { - struct_span_err!(cx.tcx.sess, p.span, E0009, - "cannot bind by-move and by-ref in the same pattern") - .span_label(p.span, "by-move pattern here") - .span_label(by_ref_span.unwrap(), "both by-ref and by-move used") - .emit(); + } else if let Some(by_ref_span) = by_ref_span { + struct_span_err!( + cx.tcx.sess, + p.span, + E0009, + "cannot bind by-move and by-ref in the same pattern", + ) + .span_label(p.span, "by-move pattern here") + .span_label(by_ref_span, "both by-ref and by-move used") + .emit(); } }; diff --git a/src/librustc_save_analysis/span_utils.rs b/src/librustc_save_analysis/span_utils.rs index e1a3829cd7538..cc5c722e4f619 100644 --- a/src/librustc_save_analysis/span_utils.rs +++ b/src/librustc_save_analysis/span_utils.rs @@ -154,8 +154,7 @@ impl<'a> SpanUtils<'a> { let loc = self.sess.source_map().lookup_char_pos(span.lo()); span_bug!( span, - "Mis-counted brackets when breaking path? Parsing '{}' \ - in {}, line {}", + "Mis-counted brackets when breaking path? Parsing '{}' in {}, line {}", self.snippet(span), loc.file.name, loc.line From 013710e8e8b322f1e902b1234ee674e395c44859 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Thu, 30 Aug 2018 16:01:42 -0700 Subject: [PATCH 15/36] Use suggestion for dereference help --- src/librustc_typeck/check/op.rs | 37 ++++++++++++++++---------- src/test/ui/issues/issue-5239-1.stderr | 4 ++- 2 files changed, 26 insertions(+), 15 deletions(-) diff --git a/src/librustc_typeck/check/op.rs b/src/librustc_typeck/check/op.rs index b7cf6819e2180..edfa62f109538 100644 --- a/src/librustc_typeck/check/op.rs +++ b/src/librustc_typeck/check/op.rs @@ -256,14 +256,19 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { let source_map = self.tcx.sess.source_map(); match is_assign { IsAssign::Yes => { - let mut err = struct_span_err!(self.tcx.sess, expr.span, E0368, - "binary assignment operation `{}=` \ - cannot be applied to type `{}`", - op.node.as_str(), - lhs_ty); - err.span_label(lhs_expr.span, - format!("cannot use `{}=` on type `{}`", - op.node.as_str(), lhs_ty)); + let mut err = struct_span_err!( + self.tcx.sess, + expr.span, + E0368, + "binary assignment operation `{}=` cannot be applied to type `{}`", + op.node.as_str(), + lhs_ty, + ); + err.span_label( + lhs_expr.span, + format!("cannot use `{}=` on type `{}`", + op.node.as_str(), lhs_ty), + ); let mut suggested_deref = false; if let Ref(_, mut rty, _) = lhs_ty.sty { if { @@ -280,13 +285,17 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { rty = rty_inner; } let msg = &format!( - "`{}=` can be used on '{}', you can \ - dereference `{2}`: `*{2}`", - op.node.as_str(), - rty, - lstring + "`{}=` can be used on '{}', you can dereference `{}`", + op.node.as_str(), + rty, + lstring, + ); + err.span_suggestion_with_applicability( + lhs_expr.span, + msg, + format!("*{}", lstring), + errors::Applicability::MachineApplicable, ); - err.help(msg); suggested_deref = true; } } diff --git a/src/test/ui/issues/issue-5239-1.stderr b/src/test/ui/issues/issue-5239-1.stderr index 7ae01fb7d6012..f9191a9fd8229 100644 --- a/src/test/ui/issues/issue-5239-1.stderr +++ b/src/test/ui/issues/issue-5239-1.stderr @@ -5,8 +5,10 @@ LL | let x = |ref x: isize| { x += 1; }; | -^^^^^ | | | cannot use `+=` on type `&isize` +help: `+=` can be used on 'isize', you can dereference `x` | - = help: `+=` can be used on 'isize', you can dereference `x`: `*x` +LL | let x = |ref x: isize| { *x += 1; }; + | ^^ error: aborting due to previous error From 472ca7159812f8c360697f63454ee7bda1e02570 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Wed, 22 Aug 2018 15:56:37 +0200 Subject: [PATCH 16/36] Implement the `min_const_fn` feature gate --- src/libcore/mem.rs | 28 ++ src/librustc/ich/impls_mir.rs | 1 + src/librustc/ich/impls_syntax.rs | 3 +- src/librustc/middle/stability.rs | 2 +- src/librustc/mir/mod.rs | 2 + src/librustc/ty/context.rs | 31 ++ src/librustc_mir/hair/cx/mod.rs | 8 +- src/librustc_mir/transform/check_unsafety.rs | 33 +- src/librustc_mir/transform/mod.rs | 1 + src/librustc_mir/transform/qualify_consts.rs | 20 +- .../transform/qualify_min_const_fn.rs | 378 ++++++++++++++++++ src/librustc_passes/rvalue_promotion.rs | 4 +- src/librustc_typeck/check/intrinsic.rs | 33 +- src/librustc_typeck/collect.rs | 15 +- src/libstd/io/lazy.rs | 38 +- src/libstd/io/stdio.rs | 20 +- src/libsyntax/attr/builtin.rs | 26 +- src/libsyntax/attr/mod.rs | 2 +- src/libsyntax/feature_gate.rs | 29 +- src/test/mir-opt/lower_128bit_test.rs | 152 +++---- src/test/run-pass/invalid_const_promotion.rs | 4 +- src/test/ui/consts/const-size_of-cycle.stderr | 8 +- .../min_const_fn/min_const_fn.nll.stderr | 224 +++++++++++ .../ui/consts/min_const_fn/min_const_fn.rs | 156 ++++++++ .../consts/min_const_fn/min_const_fn.stderr | 213 ++++++++++ .../min_const_fn/min_const_fn_dyn.nll.stderr | 25 ++ .../consts/min_const_fn/min_const_fn_dyn.rs | 27 ++ .../min_const_fn/min_const_fn_dyn.stderr | 14 + .../min_const_fn/min_const_fn_fn_ptr.rs | 29 ++ .../min_const_fn/min_const_fn_fn_ptr.stderr | 14 + .../min_const_fn_libstd_stability.rs | 38 ++ .../min_const_fn_libstd_stability.stderr | 20 + .../min_const_fn/min_const_fn_unsafe.rs | 38 ++ .../min_const_fn/min_const_fn_unsafe.stderr | 59 +++ src/test/ui/error-codes/E0308.stderr | 4 +- .../ui/feature-gates/feature-gate-const_fn.rs | 11 +- .../feature-gate-const_fn.stderr | 38 +- .../feature-gate-min_const_fn.rs | 46 +++ .../feature-gate-min_const_fn.stderr | 62 +++ 39 files changed, 1626 insertions(+), 230 deletions(-) create mode 100644 src/librustc_mir/transform/qualify_min_const_fn.rs create mode 100644 src/test/ui/consts/min_const_fn/min_const_fn.nll.stderr create mode 100644 src/test/ui/consts/min_const_fn/min_const_fn.rs create mode 100644 src/test/ui/consts/min_const_fn/min_const_fn.stderr create mode 100644 src/test/ui/consts/min_const_fn/min_const_fn_dyn.nll.stderr create mode 100644 src/test/ui/consts/min_const_fn/min_const_fn_dyn.rs create mode 100644 src/test/ui/consts/min_const_fn/min_const_fn_dyn.stderr create mode 100644 src/test/ui/consts/min_const_fn/min_const_fn_fn_ptr.rs create mode 100644 src/test/ui/consts/min_const_fn/min_const_fn_fn_ptr.stderr create mode 100644 src/test/ui/consts/min_const_fn/min_const_fn_libstd_stability.rs create mode 100644 src/test/ui/consts/min_const_fn/min_const_fn_libstd_stability.stderr create mode 100644 src/test/ui/consts/min_const_fn/min_const_fn_unsafe.rs create mode 100644 src/test/ui/consts/min_const_fn/min_const_fn_unsafe.stderr create mode 100644 src/test/ui/feature-gates/feature-gate-min_const_fn.rs create mode 100644 src/test/ui/feature-gates/feature-gate-min_const_fn.stderr diff --git a/src/libcore/mem.rs b/src/libcore/mem.rs index f2852d98282b7..e00a22bf8b6c3 100644 --- a/src/libcore/mem.rs +++ b/src/libcore/mem.rs @@ -285,6 +285,15 @@ pub fn forget(t: T) { /// [alignment]: ./fn.align_of.html #[inline] #[stable(feature = "rust1", since = "1.0.0")] +#[cfg(not(stage0))] +pub const fn size_of() -> usize { + intrinsics::size_of::() +} + +#[inline] +#[stable(feature = "rust1", since = "1.0.0")] +#[cfg(stage0)] +/// Ceci n'est pas la documentation pub const fn size_of() -> usize { unsafe { intrinsics::size_of::() } } @@ -334,6 +343,16 @@ pub fn size_of_val(val: &T) -> usize { #[inline] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_deprecated(reason = "use `align_of` instead", since = "1.2.0")] +#[cfg(not(stage0))] +pub fn min_align_of() -> usize { + intrinsics::min_align_of::() +} + +#[inline] +#[stable(feature = "rust1", since = "1.0.0")] +#[rustc_deprecated(reason = "use `align_of` instead", since = "1.2.0")] +#[cfg(stage0)] +/// Ceci n'est pas la documentation pub fn min_align_of() -> usize { unsafe { intrinsics::min_align_of::() } } @@ -376,6 +395,15 @@ pub fn min_align_of_val(val: &T) -> usize { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] +#[cfg(not(stage0))] +pub const fn align_of() -> usize { + intrinsics::min_align_of::() +} + +#[inline] +#[stable(feature = "rust1", since = "1.0.0")] +#[cfg(stage0)] +/// Ceci n'est pas la documentation pub const fn align_of() -> usize { unsafe { intrinsics::min_align_of::() } } diff --git a/src/librustc/ich/impls_mir.rs b/src/librustc/ich/impls_mir.rs index 1c9387d02d5a3..f11e448796462 100644 --- a/src/librustc/ich/impls_mir.rs +++ b/src/librustc/ich/impls_mir.rs @@ -65,6 +65,7 @@ for mir::UnsafetyViolationKind { match *self { mir::UnsafetyViolationKind::General => {} + mir::UnsafetyViolationKind::MinConstFn => {} mir::UnsafetyViolationKind::ExternStatic(lint_node_id) | mir::UnsafetyViolationKind::BorrowPacked(lint_node_id) => { lint_node_id.hash_stable(hcx, hasher); diff --git a/src/librustc/ich/impls_syntax.rs b/src/librustc/ich/impls_syntax.rs index ac5fdb2fe2797..a15411c7d8369 100644 --- a/src/librustc/ich/impls_syntax.rs +++ b/src/librustc/ich/impls_syntax.rs @@ -130,7 +130,7 @@ impl_stable_hash_for!(struct ::syntax::attr::Stability { level, feature, rustc_depr, - rustc_const_unstable + const_stability }); impl<'a> HashStable> @@ -161,7 +161,6 @@ for ::syntax::attr::StabilityLevel { } impl_stable_hash_for!(struct ::syntax::attr::RustcDeprecation { since, reason }); -impl_stable_hash_for!(struct ::syntax::attr::RustcConstUnstable { feature }); impl_stable_hash_for!(enum ::syntax::attr::IntType { diff --git a/src/librustc/middle/stability.rs b/src/librustc/middle/stability.rs index 85195b0f62e7c..f237c5b397bd5 100644 --- a/src/librustc/middle/stability.rs +++ b/src/librustc/middle/stability.rs @@ -440,7 +440,7 @@ impl<'a, 'tcx> Index<'tcx> { }, feature: Symbol::intern("rustc_private"), rustc_depr: None, - rustc_const_unstable: None, + const_stability: None, }); annotator.parent_stab = Some(stability); } diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs index 0840f333c876b..0e60d6565176a 100644 --- a/src/librustc/mir/mod.rs +++ b/src/librustc/mir/mod.rs @@ -2394,6 +2394,8 @@ impl Location { #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)] pub enum UnsafetyViolationKind { General, + /// unsafety is not allowed at all in min const fn + MinConstFn, ExternStatic(ast::NodeId), BorrowPacked(ast::NodeId), } diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index de50598c42c9d..6981d92f05f00 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -1099,6 +1099,37 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { local as usize == global as usize } + /// Returns true if this function must conform to `min_const_fn` + pub fn is_min_const_fn(self, def_id: DefId) -> bool { + if self.features().staged_api { + // some intrinsics are waved through if called inside the + // standard library. Users never need to call them directly + if let abi::Abi::RustIntrinsic = self.fn_sig(def_id).abi() { + assert!(!self.is_const_fn(def_id)); + match &self.item_name(def_id).as_str()[..] { + | "size_of" + | "min_align_of" + => return true, + _ => {}, + } + } + // in order for a libstd function to be considered min_const_fn + // it needs to be stable and have no `rustc_const_unstable` attribute + match self.lookup_stability(def_id) { + // stable functions with unstable const fn aren't `min_const_fn` + Some(&attr::Stability { const_stability: Some(_), .. }) => false, + // unstable functions don't need to conform + Some(&attr::Stability { ref level, .. }) if level.is_unstable() => false, + // everything else needs to conform, because it would be callable from + // other `min_const_fn` functions + _ => true, + } + } else { + // users enabling the `const_fn` can do what they want + !self.sess.features_untracked().const_fn + } + } + /// Create a type context and call the closure with a `TyCtxt` reference /// to the context. The closure enforces that the type context and any interned /// value (types, substs, etc.) can only be used while `ty::tls` has a valid diff --git a/src/librustc_mir/hair/cx/mod.rs b/src/librustc_mir/hair/cx/mod.rs index c9fd1d04e547b..b4257a40e38af 100644 --- a/src/librustc_mir/hair/cx/mod.rs +++ b/src/librustc_mir/hair/cx/mod.rs @@ -18,7 +18,6 @@ use hair::*; use rustc_data_structures::indexed_vec::Idx; use rustc::hir::def_id::{DefId, LOCAL_CRATE}; -use rustc::hir::map::blocks::FnLikeNode; use rustc::hir::Node; use rustc::middle::region; use rustc::infer::InferCtxt; @@ -67,10 +66,7 @@ impl<'a, 'gcx, 'tcx> Cx<'a, 'gcx, 'tcx> { let constness = match body_owner_kind { hir::BodyOwnerKind::Const | hir::BodyOwnerKind::Static(_) => hir::Constness::Const, - hir::BodyOwnerKind::Fn => { - let fn_like = FnLikeNode::from_node(infcx.tcx.hir.get(src_id)); - fn_like.map_or(hir::Constness::NotConst, |f| f.constness()) - } + hir::BodyOwnerKind::Fn => hir::Constness::NotConst, }; let attrs = tcx.hir.attrs(src_id); @@ -83,7 +79,7 @@ impl<'a, 'gcx, 'tcx> Cx<'a, 'gcx, 'tcx> { // Respect -C overflow-checks. check_overflow |= tcx.sess.overflow_checks(); - // Constants and const fn's always need overflow checks. + // Constants always need overflow checks. check_overflow |= constness == hir::Constness::Const; let lint_level = lint_level_for_hir_id(tcx, src_id); diff --git a/src/librustc_mir/transform/check_unsafety.rs b/src/librustc_mir/transform/check_unsafety.rs index f6006ae045ee7..ec7fd371a442b 100644 --- a/src/librustc_mir/transform/check_unsafety.rs +++ b/src/librustc_mir/transform/check_unsafety.rs @@ -28,6 +28,7 @@ use util; pub struct UnsafetyChecker<'a, 'tcx: 'a> { mir: &'a Mir<'tcx>, + min_const_fn: bool, source_scope_local_data: &'a IndexVec, violations: Vec, source_info: SourceInfo, @@ -38,12 +39,16 @@ pub struct UnsafetyChecker<'a, 'tcx: 'a> { } impl<'a, 'gcx, 'tcx> UnsafetyChecker<'a, 'tcx> { - fn new(mir: &'a Mir<'tcx>, - source_scope_local_data: &'a IndexVec, - tcx: TyCtxt<'a, 'tcx, 'tcx>, - param_env: ty::ParamEnv<'tcx>) -> Self { + fn new( + min_const_fn: bool, + mir: &'a Mir<'tcx>, + source_scope_local_data: &'a IndexVec, + tcx: TyCtxt<'a, 'tcx, 'tcx>, + param_env: ty::ParamEnv<'tcx>, + ) -> Self { Self { mir, + min_const_fn, source_scope_local_data, violations: vec![], source_info: SourceInfo { @@ -269,6 +274,15 @@ impl<'a, 'tcx> UnsafetyChecker<'a, 'tcx> { fn register_violations(&mut self, violations: &[UnsafetyViolation], unsafe_blocks: &[(ast::NodeId, bool)]) { + if self.min_const_fn { + for violation in violations { + let mut violation = violation.clone(); + violation.kind = UnsafetyViolationKind::MinConstFn; + if !self.violations.contains(&violation) { + self.violations.push(violation) + } + } + } let within_unsafe = match self.source_scope_local_data[self.source_info.scope].safety { Safety::Safe => { for violation in violations { @@ -276,7 +290,6 @@ impl<'a, 'tcx> UnsafetyChecker<'a, 'tcx> { self.violations.push(violation.clone()) } } - false } Safety::BuiltinUnsafe | Safety::FnUnsafe => true, @@ -369,6 +382,7 @@ fn unsafety_check_result<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) let param_env = tcx.param_env(def_id); let mut checker = UnsafetyChecker::new( + tcx.is_const_fn(def_id) && tcx.is_min_const_fn(def_id), mir, source_scope_local_data, tcx, param_env); checker.visit_mir(mir); @@ -478,6 +492,15 @@ pub fn check_unsafety<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) { .note(&details.as_str()[..]) .emit(); } + UnsafetyViolationKind::MinConstFn => { + tcx.sess.struct_span_err( + source_info.span, + &format!("{} is unsafe and unsafe operations \ + are not allowed in const fn", description)) + .span_label(source_info.span, &description.as_str()[..]) + .note(&details.as_str()[..]) + .emit(); + } UnsafetyViolationKind::ExternStatic(lint_node_id) => { tcx.lint_node_note(SAFE_EXTERN_STATICS, lint_node_id, diff --git a/src/librustc_mir/transform/mod.rs b/src/librustc_mir/transform/mod.rs index 90dfebeef1b0c..1e05b07030ef8 100644 --- a/src/librustc_mir/transform/mod.rs +++ b/src/librustc_mir/transform/mod.rs @@ -36,6 +36,7 @@ pub mod elaborate_drops; pub mod add_call_guards; pub mod promote_consts; pub mod qualify_consts; +mod qualify_min_const_fn; pub mod remove_noop_landing_pads; pub mod dump_mir; pub mod deaggregator; diff --git a/src/librustc_mir/transform/qualify_consts.rs b/src/librustc_mir/transform/qualify_consts.rs index 36dcd1714716c..c696318d283ce 100644 --- a/src/librustc_mir/transform/qualify_consts.rs +++ b/src/librustc_mir/transform/qualify_consts.rs @@ -916,9 +916,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> { ); } } else if let Some(&attr::Stability { - rustc_const_unstable: Some(attr::RustcConstUnstable { - feature: ref feature_name - }), + const_stability: Some(ref feature_name), .. }) = self.tcx.lookup_stability(def_id) { if // feature-gate is not enabled, @@ -1175,8 +1173,20 @@ impl MirPass for QualifyAndPromoteConstants { let (temps, candidates) = { let mut qualifier = Qualifier::new(tcx, def_id, mir, mode); if mode == Mode::ConstFn { - // Enforce a constant-like CFG for `const fn`. - qualifier.qualify_const(); + if tcx.is_min_const_fn(def_id) { + // enforce `min_const_fn` for stable const fns + use super::qualify_min_const_fn::is_min_const_fn; + if let Err((span, err)) = is_min_const_fn(tcx, def_id, mir) { + tcx.sess.span_err(span, &err); + } else { + // this should not produce any errors, but better safe than sorry + // FIXME(#53819) + qualifier.qualify_const(); + } + } else { + // Enforce a constant-like CFG for `const fn`. + qualifier.qualify_const(); + } } else { while let Some((bb, data)) = qualifier.rpo.next() { qualifier.visit_basic_block_data(bb, data); diff --git a/src/librustc_mir/transform/qualify_min_const_fn.rs b/src/librustc_mir/transform/qualify_min_const_fn.rs new file mode 100644 index 0000000000000..53ba4b03cb734 --- /dev/null +++ b/src/librustc_mir/transform/qualify_min_const_fn.rs @@ -0,0 +1,378 @@ +use rustc::hir::def_id::DefId; +use rustc::hir; +use rustc::mir::*; +use rustc::ty::{self, Predicate, TyCtxt}; +use std::borrow::Cow; +use syntax_pos::Span; + +mod helper { + pub struct IsMinConstFn(()); + /// This should only ever be used *once* and then passed around as a token. + pub fn ensure_that_you_really_intended_to_create_an_instance_of_this() -> IsMinConstFn { + IsMinConstFn(()) + } +} + +use self::helper::*; + +type McfResult = Result)>; + +pub fn is_min_const_fn( + tcx: TyCtxt<'a, 'tcx, 'tcx>, + def_id: DefId, + mir: &'a Mir<'tcx>, +) -> McfResult { + let mut current = def_id; + loop { + let predicates = tcx.predicates_of(current); + for predicate in &predicates.predicates { + match predicate { + | Predicate::RegionOutlives(_) + | Predicate::TypeOutlives(_) + | Predicate::WellFormed(_) + | Predicate::ConstEvaluatable(..) => continue, + | Predicate::ObjectSafe(_) => { + bug!("object safe predicate on function: {:#?}", predicate) + } + Predicate::ClosureKind(..) => { + bug!("closure kind predicate on function: {:#?}", predicate) + } + Predicate::Subtype(_) => bug!("subtype predicate on function: {:#?}", predicate), + Predicate::Projection(_) => { + let span = tcx.def_span(current); + // we'll hit a `Predicate::Trait` later which will report an error + tcx.sess + .delay_span_bug(span, "projection without trait bound"); + continue; + } + Predicate::Trait(pred) => { + if Some(pred.def_id()) == tcx.lang_items().sized_trait() { + continue; + } + match pred.skip_binder().self_ty().sty { + ty::Param(ref p) => { + let generics = tcx.generics_of(current); + let def = generics.type_param(p, tcx); + let span = tcx.def_span(def.def_id); + return Err(( + span, + "trait bounds other than `Sized` \ + on const fn parameters are unstable" + .into(), + )); + } + // other kinds of bounds are either tautologies + // or cause errors in other passes + _ => continue, + } + } + } + } + match predicates.parent { + Some(parent) => current = parent, + None => break, + } + } + + let mut token = ensure_that_you_really_intended_to_create_an_instance_of_this(); + + for local in mir.vars_iter() { + return Err(( + mir.local_decls[local].source_info.span, + "local variables in const fn are unstable".into(), + )); + } + for local in &mir.local_decls { + token = check_ty(tcx, local.ty, local.source_info.span, token)?; + } + // impl trait is gone in MIR, so check the return type manually + token = check_ty( + tcx, + tcx.fn_sig(def_id).output().skip_binder(), + mir.local_decls.iter().next().unwrap().source_info.span, + token, + )?; + + for bb in mir.basic_blocks() { + token = check_terminator(tcx, mir, bb.terminator(), token)?; + for stmt in &bb.statements { + token = check_statement(tcx, mir, stmt, token)?; + } + } + Ok(token) +} + +fn check_ty( + tcx: TyCtxt<'a, 'tcx, 'tcx>, + ty: ty::Ty<'tcx>, + span: Span, + token: IsMinConstFn, +) -> McfResult { + for ty in ty.walk() { + match ty.sty { + ty::Ref(_, _, hir::Mutability::MutMutable) => return Err(( + span, + "mutable references in const fn are unstable".into(), + )), + ty::Anon(..) => return Err((span, "`impl Trait` in const fn is unstable".into())), + ty::FnPtr(..) => { + return Err((span, "function pointers in const fn are unstable".into())) + } + ty::Dynamic(preds, _) => { + for pred in preds.iter() { + match pred.skip_binder() { + | ty::ExistentialPredicate::AutoTrait(_) + | ty::ExistentialPredicate::Projection(_) => { + return Err(( + span, + "trait bounds other than `Sized` \ + on const fn parameters are unstable" + .into(), + )) + } + ty::ExistentialPredicate::Trait(trait_ref) => { + if Some(trait_ref.def_id) != tcx.lang_items().sized_trait() { + return Err(( + span, + "trait bounds other than `Sized` \ + on const fn parameters are unstable" + .into(), + )); + } + } + } + } + } + _ => {} + } + } + Ok(token) +} + +fn check_rvalue( + tcx: TyCtxt<'a, 'tcx, 'tcx>, + mir: &'a Mir<'tcx>, + rvalue: &Rvalue<'tcx>, + span: Span, + token: IsMinConstFn, +) -> McfResult { + match rvalue { + Rvalue::Repeat(operand, _) | Rvalue::Use(operand) => { + check_operand(tcx, mir, operand, span, token) + } + Rvalue::Len(place) | Rvalue::Discriminant(place) | Rvalue::Ref(_, _, place) => { + check_place(tcx, mir, place, span, token, PlaceMode::Read) + } + Rvalue::Cast(_, operand, cast_ty) => { + use rustc::ty::cast::CastTy; + let cast_in = CastTy::from_ty(operand.ty(mir, tcx)).expect("bad input type for cast"); + let cast_out = CastTy::from_ty(cast_ty).expect("bad output type for cast"); + match (cast_in, cast_out) { + (CastTy::Ptr(_), CastTy::Int(_)) | (CastTy::FnPtr, CastTy::Int(_)) => Err(( + span, + "casting pointers to ints is unstable in const fn".into(), + )), + (CastTy::RPtr(_), CastTy::Float) => bug!(), + (CastTy::RPtr(_), CastTy::Int(_)) => bug!(), + (CastTy::Ptr(_), CastTy::RPtr(_)) => bug!(), + _ => check_operand(tcx, mir, operand, span, token), + } + } + // binops are fine on integers + Rvalue::BinaryOp(_, lhs, rhs) | Rvalue::CheckedBinaryOp(_, lhs, rhs) => { + let token = check_operand(tcx, mir, lhs, span, token)?; + let token = check_operand(tcx, mir, rhs, span, token)?; + let ty = lhs.ty(mir, tcx); + if ty.is_integral() || ty.is_bool() || ty.is_char() { + Ok(token) + } else { + Err(( + span, + "only int, `bool` and `char` operations are stable in const fn".into(), + )) + } + } + // checked by regular const fn checks + Rvalue::NullaryOp(..) => Ok(token), + Rvalue::UnaryOp(_, operand) => { + let ty = operand.ty(mir, tcx); + if ty.is_integral() || ty.is_bool() { + check_operand(tcx, mir, operand, span, token) + } else { + Err(( + span, + "only int and `bool` operations are stable in const fn".into(), + )) + } + } + Rvalue::Aggregate(_, operands) => { + let mut token = token; + for operand in operands { + token = check_operand(tcx, mir, operand, span, token)?; + } + Ok(token) + } + } +} + +enum PlaceMode { + Assign, + Read, +} + +fn check_statement( + tcx: TyCtxt<'a, 'tcx, 'tcx>, + mir: &'a Mir<'tcx>, + statement: &Statement<'tcx>, + token: IsMinConstFn, +) -> McfResult { + let span = statement.source_info.span; + match &statement.kind { + StatementKind::Assign(place, rval) => { + let token = check_place(tcx, mir, place, span, token, PlaceMode::Assign)?; + check_rvalue(tcx, mir, rval, span, token) + } + + StatementKind::ReadForMatch(_) => Err((span, "match in const fn is unstable".into())), + + // just an assignment + StatementKind::SetDiscriminant { .. } => Ok(token), + + | StatementKind::InlineAsm { .. } => { + Err((span, "cannot use inline assembly in const fn".into())) + } + + // These are all NOPs + | StatementKind::StorageLive(_) + | StatementKind::StorageDead(_) + | StatementKind::Validate(..) + | StatementKind::EndRegion(_) + | StatementKind::UserAssertTy(..) + | StatementKind::Nop => Ok(token), + } +} + +fn check_operand( + tcx: TyCtxt<'a, 'tcx, 'tcx>, + mir: &'a Mir<'tcx>, + operand: &Operand<'tcx>, + span: Span, + token: IsMinConstFn, +) -> McfResult { + match operand { + Operand::Move(place) | Operand::Copy(place) => { + check_place(tcx, mir, place, span, token, PlaceMode::Read) + } + Operand::Constant(_) => Ok(token), + } +} + +fn check_place( + tcx: TyCtxt<'a, 'tcx, 'tcx>, + mir: &'a Mir<'tcx>, + place: &Place<'tcx>, + span: Span, + token: IsMinConstFn, + mode: PlaceMode, +) -> McfResult { + match place { + Place::Local(l) => match mode { + PlaceMode::Assign => match mir.local_kind(*l) { + LocalKind::Temp | LocalKind::ReturnPointer => Ok(token), + LocalKind::Arg | LocalKind::Var => { + Err((span, "assignments in const fn are unstable".into())) + } + }, + PlaceMode::Read => Ok(token), + }, + // promoteds are always fine, they are essentially constants + Place::Promoted(_) => Ok(token), + Place::Static(_) => Err((span, "cannot access `static` items in const fn".into())), + Place::Projection(proj) => { + match proj.elem { + | ProjectionElem::Deref | ProjectionElem::Field(..) | ProjectionElem::Index(_) => { + check_place(tcx, mir, &proj.base, span, token, mode) + } + // slice patterns are unstable + | ProjectionElem::ConstantIndex { .. } | ProjectionElem::Subslice { .. } => { + return Err((span, "slice patterns in const fn are unstable".into())) + } + | ProjectionElem::Downcast(..) => { + Err((span, "`match` or `if let` in `const fn` is unstable".into())) + } + } + } + } +} + +fn check_terminator( + tcx: TyCtxt<'a, 'tcx, 'tcx>, + mir: &'a Mir<'tcx>, + terminator: &Terminator<'tcx>, + token: IsMinConstFn, +) -> McfResult { + let span = terminator.source_info.span; + match &terminator.kind { + | TerminatorKind::Goto { .. } + | TerminatorKind::Return + | TerminatorKind::Resume => Ok(token), + + TerminatorKind::Drop { location, .. } => { + check_place(tcx, mir, location, span, token, PlaceMode::Read) + } + TerminatorKind::DropAndReplace { location, value, .. } => { + let token = check_place(tcx, mir, location, span, token, PlaceMode::Read)?; + check_operand(tcx, mir, value, span, token) + }, + TerminatorKind::SwitchInt { .. } => Err(( + span, + "`if`, `match`, `&&` and `||` are not stable in const fn".into(), + )), + | TerminatorKind::Abort | TerminatorKind::Unreachable => { + Err((span, "const fn with unreachable code is not stable".into())) + } + | TerminatorKind::GeneratorDrop | TerminatorKind::Yield { .. } => { + Err((span, "const fn generators are unstable".into())) + } + + TerminatorKind::Call { + func, + args, + destination: _, + cleanup: _, + } => { + let fn_ty = func.ty(mir, tcx); + if let ty::FnDef(def_id, _) = fn_ty.sty { + if tcx.is_min_const_fn(def_id) { + let mut token = check_operand(tcx, mir, func, span, token)?; + + for arg in args { + token = check_operand(tcx, mir, arg, span, token)?; + } + Ok(token) + } else { + Err(( + span, + "can only call other `min_const_fn` within a `min_const_fn`".into(), + )) + } + } else { + Err((span, "can only call other const fns within const fn".into())) + } + } + + TerminatorKind::Assert { + cond, + expected: _, + msg: _, + target: _, + cleanup: _, + } => check_operand(tcx, mir, cond, span, token), + + | TerminatorKind::FalseEdges { .. } | TerminatorKind::FalseUnwind { .. } => span_bug!( + terminator.source_info.span, + "min_const_fn encountered `{:#?}`", + terminator + ), + } +} diff --git a/src/librustc_passes/rvalue_promotion.rs b/src/librustc_passes/rvalue_promotion.rs index fca1c7f27ab37..f9f74b77e6c46 100644 --- a/src/librustc_passes/rvalue_promotion.rs +++ b/src/librustc_passes/rvalue_promotion.rs @@ -178,9 +178,7 @@ impl<'a, 'gcx> CheckCrateVisitor<'a, 'gcx> { } if let Some(&attr::Stability { - rustc_const_unstable: Some(attr::RustcConstUnstable { - feature: ref feature_name - }), + const_stability: Some(ref feature_name), .. }) = self.tcx.lookup_stability(def_id) { let stable_check = // feature-gate is enabled, diff --git a/src/librustc_typeck/check/intrinsic.rs b/src/librustc_typeck/check/intrinsic.rs index 23872ddf2f64b..c7db3debf5a0d 100644 --- a/src/librustc_typeck/check/intrinsic.rs +++ b/src/librustc_typeck/check/intrinsic.rs @@ -26,12 +26,15 @@ use rustc::hir; use std::iter; -fn equate_intrinsic_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, - it: &hir::ForeignItem, - n_tps: usize, - abi: Abi, - inputs: Vec>, - output: Ty<'tcx>) { +fn equate_intrinsic_type<'a, 'tcx>( + tcx: TyCtxt<'a, 'tcx, 'tcx>, + it: &hir::ForeignItem, + n_tps: usize, + abi: Abi, + safety: hir::Unsafety, + inputs: Vec>, + output: Ty<'tcx>, +) { let def_id = tcx.hir.local_def_id(it.id); match it.node { @@ -65,7 +68,7 @@ fn equate_intrinsic_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, inputs.into_iter(), output, false, - hir::Unsafety::Unsafe, + safety, abi ))); let cause = ObligationCause::new(it.span, it.id, ObligationCauseCode::IntrinsicType); @@ -78,7 +81,7 @@ pub fn check_intrinsic_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, it: &hir::ForeignItem) { let param = |n| tcx.mk_ty_param(n, Symbol::intern(&format!("P{}", n)).as_interned_str()); let name = it.name.as_str(); - let (n_tps, inputs, output) = if name.starts_with("atomic_") { + let (n_tps, inputs, output, unsafety) = if name.starts_with("atomic_") { let split : Vec<&str> = name.split('_').collect(); assert!(split.len() >= 2, "Atomic intrinsic not correct format"); @@ -109,10 +112,14 @@ pub fn check_intrinsic_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, return; } }; - (n_tps, inputs, output) + (n_tps, inputs, output, hir::Unsafety::Unsafe) } else if &name[..] == "abort" || &name[..] == "unreachable" { - (0, Vec::new(), tcx.types.never) + (0, Vec::new(), tcx.types.never, hir::Unsafety::Unsafe) } else { + let unsafety = match &name[..] { + "size_of" | "min_align_of" => hir::Unsafety::Normal, + _ => hir::Unsafety::Unsafe, + }; let (n_tps, inputs, output) = match &name[..] { "breakpoint" => (0, Vec::new(), tcx.mk_nil()), "size_of" | @@ -327,9 +334,9 @@ pub fn check_intrinsic_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, return; } }; - (n_tps, inputs, output) + (n_tps, inputs, output, unsafety) }; - equate_intrinsic_type(tcx, it, n_tps, Abi::RustIntrinsic, inputs, output) + equate_intrinsic_type(tcx, it, n_tps, Abi::RustIntrinsic, unsafety, inputs, output) } /// Type-check `extern "platform-intrinsic" { ... }` functions. @@ -439,7 +446,7 @@ pub fn check_platform_intrinsic_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, } }; - equate_intrinsic_type(tcx, it, n_tps, Abi::PlatformIntrinsic, + equate_intrinsic_type(tcx, it, n_tps, Abi::PlatformIntrinsic, hir::Unsafety::Unsafe, inputs, output) } diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index a42667ab45fc8..b956c72b3a2da 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -1981,12 +1981,15 @@ fn compute_sig_of_foreign_fn_decl<'a, 'tcx>( decl: &hir::FnDecl, abi: abi::Abi, ) -> ty::PolyFnSig<'tcx> { - let fty = AstConv::ty_of_fn( - &ItemCtxt::new(tcx, def_id), - hir::Unsafety::Unsafe, - abi, - decl, - ); + let unsafety = if abi == abi::Abi::RustIntrinsic { + match &*tcx.item_name(def_id).as_str() { + "size_of" | "min_align_of" => hir::Unsafety::Normal, + _ => hir::Unsafety::Unsafe, + } + } else { + hir::Unsafety::Unsafe + }; + let fty = AstConv::ty_of_fn(&ItemCtxt::new(tcx, def_id), unsafety, abi, decl); // feature gate SIMD types in FFI, since I (huonw) am not sure the // ABIs are handled at all correctly. diff --git a/src/libstd/io/lazy.rs b/src/libstd/io/lazy.rs index 4fb367fb6ba52..24965ff693184 100644 --- a/src/libstd/io/lazy.rs +++ b/src/libstd/io/lazy.rs @@ -18,7 +18,6 @@ pub struct Lazy { // We never call `lock.init()`, so it is UB to attempt to acquire this mutex reentrantly! lock: Mutex, ptr: Cell<*mut Arc>, - init: fn() -> Arc, } #[inline] @@ -26,33 +25,32 @@ const fn done() -> *mut Arc { 1_usize as *mut _ } unsafe impl Sync for Lazy {} -impl Lazy { - /// Safety: `init` must not call `get` on the variable that is being - /// initialized. - pub const unsafe fn new(init: fn() -> Arc) -> Lazy { +impl Lazy { + pub const fn new() -> Lazy { Lazy { lock: Mutex::new(), ptr: Cell::new(ptr::null_mut()), - init, } } +} - pub fn get(&'static self) -> Option> { - unsafe { - let _guard = self.lock.lock(); - let ptr = self.ptr.get(); - if ptr.is_null() { - Some(self.init()) - } else if ptr == done() { - None - } else { - Some((*ptr).clone()) - } +impl Lazy { + /// Safety: `init` must not call `get` on the variable that is being + /// initialized. + pub unsafe fn get(&'static self, init: fn() -> Arc) -> Option> { + let _guard = self.lock.lock(); + let ptr = self.ptr.get(); + if ptr.is_null() { + Some(self.init(init)) + } else if ptr == done() { + None + } else { + Some((*ptr).clone()) } } // Must only be called with `lock` held - unsafe fn init(&'static self) -> Arc { + unsafe fn init(&'static self, init: fn() -> Arc) -> Arc { // If we successfully register an at exit handler, then we cache the // `Arc` allocation in our own internal box (it will get deallocated by // the at exit handler). Otherwise we just return the freshly allocated @@ -66,8 +64,8 @@ impl Lazy { }); // This could reentrantly call `init` again, which is a problem // because our `lock` allows reentrancy! - // That's why `new` is unsafe and requires the caller to ensure no reentrancy happens. - let ret = (self.init)(); + // That's why `get` is unsafe and requires the caller to ensure no reentrancy happens. + let ret = init(); if registered.is_ok() { self.ptr.set(Box::into_raw(Box::new(ret.clone()))); } diff --git a/src/libstd/io/stdio.rs b/src/libstd/io/stdio.rs index 1f256f518c7ce..a413432cdaabc 100644 --- a/src/libstd/io/stdio.rs +++ b/src/libstd/io/stdio.rs @@ -197,9 +197,11 @@ pub struct StdinLock<'a> { /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn stdin() -> Stdin { - static INSTANCE: Lazy>>> = unsafe { Lazy::new(stdin_init) }; + static INSTANCE: Lazy>>> = Lazy::new(); return Stdin { - inner: INSTANCE.get().expect("cannot access stdin during shutdown"), + inner: unsafe { + INSTANCE.get(stdin_init).expect("cannot access stdin during shutdown") + }, }; fn stdin_init() -> Arc>>> { @@ -396,10 +398,11 @@ pub struct StdoutLock<'a> { /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn stdout() -> Stdout { - static INSTANCE: Lazy>>>> - = unsafe { Lazy::new(stdout_init) }; + static INSTANCE: Lazy>>>> = Lazy::new(); return Stdout { - inner: INSTANCE.get().expect("cannot access stdout during shutdown"), + inner: unsafe { + INSTANCE.get(stdout_init).expect("cannot access stdout during shutdown") + }, }; fn stdout_init() -> Arc>>>> { @@ -533,10 +536,11 @@ pub struct StderrLock<'a> { /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn stderr() -> Stderr { - static INSTANCE: Lazy>>> = - unsafe { Lazy::new(stderr_init) }; + static INSTANCE: Lazy>>> = Lazy::new(); return Stderr { - inner: INSTANCE.get().expect("cannot access stderr during shutdown"), + inner: unsafe { + INSTANCE.get(stderr_init).expect("cannot access stderr during shutdown") + }, }; fn stderr_init() -> Arc>>> { diff --git a/src/libsyntax/attr/builtin.rs b/src/libsyntax/attr/builtin.rs index ecd52a62eab26..3eecdf14a4e50 100644 --- a/src/libsyntax/attr/builtin.rs +++ b/src/libsyntax/attr/builtin.rs @@ -107,7 +107,11 @@ pub struct Stability { pub level: StabilityLevel, pub feature: Symbol, pub rustc_depr: Option, - pub rustc_const_unstable: Option, + /// `None` means the function is stable but needs to be allowed by the + /// `min_const_fn` feature + /// `Some` contains the feature gate required to be able to use the function + /// as const fn + pub const_stability: Option, } /// The available stability levels. @@ -141,11 +145,6 @@ pub struct RustcDeprecation { pub reason: Symbol, } -#[derive(RustcEncodable, RustcDecodable, PartialEq, PartialOrd, Clone, Debug, Eq, Hash)] -pub struct RustcConstUnstable { - pub feature: Symbol, -} - /// Check if `attrs` contains an attribute like `#![feature(feature_name)]`. /// This will not perform any "sanity checks" on the form of the attributes. pub fn contains_feature_attr(attrs: &[Attribute], feature_name: &str) -> bool { @@ -176,7 +175,7 @@ fn find_stability_generic<'a, I>(diagnostic: &Handler, let mut stab: Option = None; let mut rustc_depr: Option = None; - let mut rustc_const_unstable: Option = None; + let mut rustc_const_unstable: Option = None; 'outer: for attr in attrs_iter { if ![ @@ -191,6 +190,7 @@ fn find_stability_generic<'a, I>(diagnostic: &Handler, mark_used(attr); let meta = attr.meta(); + // attributes with data if let Some(MetaItem { node: MetaItemKind::List(ref metas), .. }) = meta { let meta = meta.as_ref().unwrap(); let get = |meta: &MetaItem, item: &mut Option| { @@ -272,9 +272,7 @@ fn find_stability_generic<'a, I>(diagnostic: &Handler, get_meta!(feature); if let Some(feature) = feature { - rustc_const_unstable = Some(RustcConstUnstable { - feature - }); + rustc_const_unstable = Some(feature); } else { span_err!(diagnostic, attr.span(), E0629, "missing 'feature'"); continue @@ -330,7 +328,7 @@ fn find_stability_generic<'a, I>(diagnostic: &Handler, }, feature, rustc_depr: None, - rustc_const_unstable: None, + const_stability: None, }) } (None, _, _) => { @@ -379,7 +377,7 @@ fn find_stability_generic<'a, I>(diagnostic: &Handler, }, feature, rustc_depr: None, - rustc_const_unstable: None, + const_stability: None, }) } (None, _) => { @@ -412,9 +410,9 @@ fn find_stability_generic<'a, I>(diagnostic: &Handler, } // Merge the const-unstable info into the stability info - if let Some(rustc_const_unstable) = rustc_const_unstable { + if let Some(feature) = rustc_const_unstable { if let Some(ref mut stab) = stab { - stab.rustc_const_unstable = Some(rustc_const_unstable); + stab.const_stability = Some(feature); } else { span_err!(diagnostic, item_sp, E0630, "rustc_const_unstable attribute must be paired with \ diff --git a/src/libsyntax/attr/mod.rs b/src/libsyntax/attr/mod.rs index cd9d76822106c..19bbbceff5fc0 100644 --- a/src/libsyntax/attr/mod.rs +++ b/src/libsyntax/attr/mod.rs @@ -15,7 +15,7 @@ mod builtin; pub use self::builtin::{ cfg_matches, contains_feature_attr, eval_condition, find_crate_name, find_deprecation, find_repr_attrs, find_stability, find_unwind_attr, Deprecation, InlineAttr, IntType, ReprAttr, - RustcConstUnstable, RustcDeprecation, Stability, StabilityLevel, UnwindAttr, + RustcDeprecation, Stability, StabilityLevel, UnwindAttr, }; pub use self::IntType::*; pub use self::ReprAttr::*; diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index 080860f17f5dd..f226c9dd979d4 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -40,6 +40,16 @@ use symbol::{keywords, Symbol}; use std::{env, path}; macro_rules! set { + // The const_fn feature also enables the min_const_fn feature, because `min_const_fn` allows + // the declaration `const fn`, but the `const_fn` feature gate enables things inside those + // functions that we do not want to expose to the user for now. + (const_fn) => {{ + fn f(features: &mut Features, _: Span) { + features.const_fn = true; + features.min_const_fn = true; + } + f as fn(&mut Features, Span) + }}; ($field: ident) => {{ fn f(features: &mut Features, _: Span) { features.$field = true; @@ -206,25 +216,28 @@ declare_features! ( // #23121. Array patterns have some hazards yet. (active, slice_patterns, "1.0.0", Some(23121), None), - // Allows the definition of `const fn` functions. + // Allows the definition of `const fn` functions with some advanced features. (active, const_fn, "1.2.0", Some(24111), None), + // Allows the definition of `const fn` functions. + (active, min_const_fn, "1.30.0", Some(53555), None), + // Allows let bindings and destructuring in `const fn` functions and constants. (active, const_let, "1.22.1", Some(48821), None), - // Allows accessing fields of unions inside const fn + // Allows accessing fields of unions inside const fn. (active, const_fn_union, "1.27.0", Some(51909), None), - // Allows casting raw pointers to `usize` during const eval + // Allows casting raw pointers to `usize` during const eval. (active, const_raw_ptr_to_usize_cast, "1.27.0", Some(51910), None), - // Allows dereferencing raw pointers during const eval + // Allows dereferencing raw pointers during const eval. (active, const_raw_ptr_deref, "1.27.0", Some(51911), None), - // Allows reinterpretation of the bits of a value of one type as another type during const eval + // Allows reinterpretation of the bits of a value of one type as another type during const eval. (active, const_transmute, "1.29.0", Some(53605), None), - // Allows comparing raw pointers during const eval + // Allows comparing raw pointers during const eval. (active, const_compare_raw_pointers, "1.27.0", Some(53020), None), // Allows panicking during const eval (produces compile-time errors) @@ -1786,7 +1799,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { gate_feature_post!(&self, async_await, span, "async fn is unstable"); } if header.constness.node == ast::Constness::Const { - gate_feature_post!(&self, const_fn, span, "const fn is unstable"); + gate_feature_post!(&self, min_const_fn, span, "const fn is unstable"); } // stability of const fn methods are covered in // visit_trait_item and visit_impl_item below; this is @@ -1844,7 +1857,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { match ii.node { ast::ImplItemKind::Method(ref sig, _) => { if sig.header.constness.node == ast::Constness::Const { - gate_feature_post!(&self, const_fn, ii.span, "const fn is unstable"); + gate_feature_post!(&self, min_const_fn, ii.span, "const fn is unstable"); } } ast::ImplItemKind::Existential(..) => { diff --git a/src/test/mir-opt/lower_128bit_test.rs b/src/test/mir-opt/lower_128bit_test.rs index b4b54e13a698e..72c0e33cd9ecf 100644 --- a/src/test/mir-opt/lower_128bit_test.rs +++ b/src/test/mir-opt/lower_128bit_test.rs @@ -10,7 +10,7 @@ // ignore-emscripten -// compile-flags: -Z lower_128bit_ops=yes -C debug_assertions=no +// compile-flags: -Z lower_128bit_ops=yes -C debug_assertions=no -O #![feature(const_fn)] @@ -63,103 +63,65 @@ fn main() { // END RUST SOURCE // START rustc.const_signed.Lower128Bit.after.mir -// _8 = _1; -// _9 = const compiler_builtins::int::addsub::rust_i128_addo(move _8, const 1i128) -> bb10; -// ... -// _7 = move (_9.0: i128); -// ... -// _10 = const compiler_builtins::int::addsub::rust_i128_subo(move _7, const 2i128) -> bb11; -// ... -// _6 = move (_10.0: i128); -// ... -// _11 = const compiler_builtins::int::mul::rust_i128_mulo(move _6, const 3i128) -> bb12; -// ... -// _5 = move (_11.0: i128); -// ... -// _12 = Eq(const 4i128, const 0i128); -// assert(!move _12, "attempt to divide by zero") -> bb4; -// ... -// _13 = Eq(const 4i128, const -1i128); -// _14 = Eq(_5, const -170141183460469231731687303715884105728i128); -// _15 = BitAnd(move _13, move _14); -// assert(!move _15, "attempt to divide with overflow") -> bb5; -// ... -// _4 = const compiler_builtins::int::sdiv::rust_i128_div(move _5, const 4i128) -> bb13; -// ... -// _17 = Eq(const 5i128, const -1i128); -// _18 = Eq(_4, const -170141183460469231731687303715884105728i128); -// _19 = BitAnd(move _17, move _18); -// assert(!move _19, "attempt to calculate the remainder with overflow") -> bb7; -// ... -// _3 = const compiler_builtins::int::sdiv::rust_i128_rem(move _4, const 5i128) -> bb15; -// ... -// _2 = move (_20.0: i128); -// ... -// _23 = const 7i32 as u128 (Misc); -// _21 = const compiler_builtins::int::shift::rust_i128_shro(move _2, move _23) -> bb16; -// ... -// _0 = move (_21.0: i128); -// ... -// assert(!move (_9.1: bool), "attempt to add with overflow") -> bb1; -// ... -// assert(!move (_10.1: bool), "attempt to subtract with overflow") -> bb2; -// ... -// assert(!move (_11.1: bool), "attempt to multiply with overflow") -> bb3; -// ... -// _16 = Eq(const 5i128, const 0i128); -// assert(!move _16, "attempt to calculate the remainder with a divisor of zero") -> bb6; -// ... -// assert(!move (_20.1: bool), "attempt to shift left with overflow") -> bb8; -// ... -// _22 = const 6i32 as u128 (Misc); -// _20 = const compiler_builtins::int::shift::rust_i128_shlo(move _3, move _22) -> bb14; -// ... -// assert(!move (_21.1: bool), "attempt to shift right with overflow") -> bb9; +// _7 = const compiler_builtins::int::addsub::rust_i128_add(move _8, const 1i128) -> bb7; +// ... +// _10 = Eq(const 4i128, const -1i128); +// _11 = Eq(_5, const -170141183460469231731687303715884105728i128); +// _12 = BitAnd(move _10, move _11); +// assert(!move _12, "attempt to divide with overflow") -> bb2; +// ... +// _4 = const compiler_builtins::int::sdiv::rust_i128_div(move _5, const 4i128) -> bb8; +// ... +// _14 = Eq(const 5i128, const -1i128); +// _15 = Eq(_4, const -170141183460469231731687303715884105728i128); +// _16 = BitAnd(move _14, move _15); +// assert(!move _16, "attempt to calculate the remainder with overflow") -> bb4; +// ... +// _3 = const compiler_builtins::int::sdiv::rust_i128_rem(move _4, const 5i128) -> bb11; +// ... +// _9 = Eq(const 4i128, const 0i128); +// assert(!move _9, "attempt to divide by zero") -> bb1; +// ... +// _5 = const compiler_builtins::int::mul::rust_i128_mul(move _6, const 3i128) -> bb5; +// ... +// _6 = const compiler_builtins::int::addsub::rust_i128_sub(move _7, const 2i128) -> bb6; +// ... +// _13 = Eq(const 5i128, const 0i128); +// assert(!move _13, "attempt to calculate the remainder with a divisor of zero") -> bb3; +// ... +// _17 = const 7i32 as u32 (Misc); +// _0 = const compiler_builtins::int::shift::rust_i128_shr(move _2, move _17) -> bb9; +// ... +// _18 = const 6i32 as u32 (Misc); +// _2 = const compiler_builtins::int::shift::rust_i128_shl(move _3, move _18) -> bb10; // END rustc.const_signed.Lower128Bit.after.mir // START rustc.const_unsigned.Lower128Bit.after.mir -// _8 = _1; -// _9 = const compiler_builtins::int::addsub::rust_u128_addo(move _8, const 1u128) -> bb8; -// ... -// _7 = move (_9.0: u128); -// ... -// _10 = const compiler_builtins::int::addsub::rust_u128_subo(move _7, const 2u128) -> bb9; -// ... -// _6 = move (_10.0: u128); -// ... -// _11 = const compiler_builtins::int::mul::rust_u128_mulo(move _6, const 3u128) -> bb10; -// ... -// _5 = move (_11.0: u128); -// ... -// _12 = Eq(const 4u128, const 0u128); -// assert(!move _12, "attempt to divide by zero") -> bb4; -// ... -// _4 = const compiler_builtins::int::udiv::rust_u128_div(move _5, const 4u128) -> bb11; -// ... -// _3 = const compiler_builtins::int::udiv::rust_u128_rem(move _4, const 5u128) -> bb13; -// ... -// _2 = move (_14.0: u128); -// ... -// _17 = const 7i32 as u128 (Misc); -// _15 = const compiler_builtins::int::shift::rust_u128_shro(move _2, move _17) -> bb14; -// ... -// _0 = move (_15.0: u128); -// ... -// assert(!move (_9.1: bool), "attempt to add with overflow") -> bb1; -// ... -// assert(!move (_10.1: bool), "attempt to subtract with overflow") -> bb2; -// ... -// assert(!move (_11.1: bool), "attempt to multiply with overflow") -> bb3; -// ... -// _13 = Eq(const 5u128, const 0u128); -// assert(!move _13, "attempt to calculate the remainder with a divisor of zero") -> bb5; -// ... -// assert(!move (_14.1: bool), "attempt to shift left with overflow") -> bb6; -// ... -// _16 = const 6i32 as u128 (Misc); -// _14 = const compiler_builtins::int::shift::rust_u128_shlo(move _3, move _16) -> bb12; -// ... -// assert(!move (_15.1: bool), "attempt to shift right with overflow") -> bb7; +// _8 = _1; +// _7 = const compiler_builtins::int::addsub::rust_u128_add(move _8, const 1u128) -> bb5; +// ... +// _4 = const compiler_builtins::int::udiv::rust_u128_div(move _5, const 4u128) -> bb6; +// ... +// _3 = const compiler_builtins::int::udiv::rust_u128_rem(move _4, const 5u128) -> bb9; +// ... +// _9 = Eq(const 4u128, const 0u128); +// assert(!move _9, "attempt to divide by zero") -> bb1; +// ... +// _5 = const compiler_builtins::int::mul::rust_u128_mul(move _6, const 3u128) -> bb3; +// ... +// _6 = const compiler_builtins::int::addsub::rust_u128_sub(move _7, const 2u128) -> bb4; +// ... +// _10 = Eq(const 5u128, const 0u128); +// assert(!move _10, "attempt to calculate the remainder with a divisor of zero") -> bb2; +// ... +// return; +// ... +// _11 = const 7i32 as u32 (Misc); +// _0 = const compiler_builtins::int::shift::rust_u128_shr(move _2, move _11) -> bb7; +// ... +// _12 = const 6i32 as u32 (Misc); +// _2 = const compiler_builtins::int::shift::rust_u128_shl(move _3, move _12) -> bb8; + // END rustc.const_unsigned.Lower128Bit.after.mir // START rustc.test_signed.Lower128Bit.after.mir diff --git a/src/test/run-pass/invalid_const_promotion.rs b/src/test/run-pass/invalid_const_promotion.rs index 53cb4c4b009e5..a18d82fb7a4e7 100644 --- a/src/test/run-pass/invalid_const_promotion.rs +++ b/src/test/run-pass/invalid_const_promotion.rs @@ -11,6 +11,8 @@ // ignore-wasm32 // ignore-emscripten +// compile-flags: -C debug_assertions=yes + #![feature(const_fn, libc)] #![allow(const_err)] @@ -19,7 +21,7 @@ extern crate libc; use std::env; use std::process::{Command, Stdio}; -// this will panic in debug mode +// this will panic in debug mode and overflow in release mode const fn bar() -> usize { 0 - 1 } fn foo() { diff --git a/src/test/ui/consts/const-size_of-cycle.stderr b/src/test/ui/consts/const-size_of-cycle.stderr index 16d87f7e31c9b..ab8b5792e681d 100644 --- a/src/test/ui/consts/const-size_of-cycle.stderr +++ b/src/test/ui/consts/const-size_of-cycle.stderr @@ -4,14 +4,14 @@ note: ...which requires normalizing `ParamEnvAnd { param_env: ParamEnv { caller_ note: ...which requires const-evaluating `Foo::bytes::{{constant}}`... --> $SRC_DIR/libcore/mem.rs:LL:COL | -LL | unsafe { intrinsics::size_of::() } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | intrinsics::size_of::() + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: ...which again requires computing layout of `Foo`, completing the cycle note: cycle used when const-evaluating `Foo::bytes::{{constant}}` --> $SRC_DIR/libcore/mem.rs:LL:COL | -LL | unsafe { intrinsics::size_of::() } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | intrinsics::size_of::() + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/consts/min_const_fn/min_const_fn.nll.stderr b/src/test/ui/consts/min_const_fn/min_const_fn.nll.stderr new file mode 100644 index 0000000000000..b156e5a9731da --- /dev/null +++ b/src/test/ui/consts/min_const_fn/min_const_fn.nll.stderr @@ -0,0 +1,224 @@ +error[E0493]: destructors cannot be evaluated at compile-time + --> $DIR/min_const_fn.rs:49:25 + | +LL | const fn into_inner(self) -> T { self.0 } //~ destructors cannot be evaluated + | ^^^^ constant functions cannot evaluate destructors + +error: mutable references in const fn are unstable + --> $DIR/min_const_fn.rs:51:5 + | +LL | const fn get_mut(&mut self) -> &mut T { &mut self.0 } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0493]: destructors cannot be evaluated at compile-time + --> $DIR/min_const_fn.rs:56:28 + | +LL | const fn into_inner_lt(self) -> T { self.0 } //~ destructors cannot be evaluated + | ^^^^ constant functions cannot evaluate destructors + +error: mutable references in const fn are unstable + --> $DIR/min_const_fn.rs:58:5 + | +LL | const fn get_mut_lt(&'a mut self) -> &mut T { &mut self.0 } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0493]: destructors cannot be evaluated at compile-time + --> $DIR/min_const_fn.rs:63:27 + | +LL | const fn into_inner_s(self) -> T { self.0 } //~ ERROR destructors + | ^^^^ constant functions cannot evaluate destructors + +error: mutable references in const fn are unstable + --> $DIR/min_const_fn.rs:65:5 + | +LL | const fn get_mut_s(&mut self) -> &mut T { &mut self.0 } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: mutable references in const fn are unstable + --> $DIR/min_const_fn.rs:70:5 + | +LL | const fn get_mut_sq(&mut self) -> &mut T { &mut self.0 } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: trait bounds other than `Sized` on const fn parameters are unstable + --> $DIR/min_const_fn.rs:88:16 + | +LL | const fn foo11(t: T) -> T { t } + | ^ + +error: trait bounds other than `Sized` on const fn parameters are unstable + --> $DIR/min_const_fn.rs:90:18 + | +LL | const fn foo11_2(t: T) -> T { t } + | ^ + +error: only int, `bool` and `char` operations are stable in const fn + --> $DIR/min_const_fn.rs:92:33 + | +LL | const fn foo19(f: f32) -> f32 { f * 2.0 } + | ^^^^^^^ + +error: only int, `bool` and `char` operations are stable in const fn + --> $DIR/min_const_fn.rs:94:35 + | +LL | const fn foo19_2(f: f32) -> f32 { 2.0 - f } + | ^^^^^^^ + +error: only int and `bool` operations are stable in const fn + --> $DIR/min_const_fn.rs:96:35 + | +LL | const fn foo19_3(f: f32) -> f32 { -f } + | ^^ + +error: only int, `bool` and `char` operations are stable in const fn + --> $DIR/min_const_fn.rs:98:43 + | +LL | const fn foo19_4(f: f32, g: f32) -> f32 { f / g } + | ^^^^^ + +error: cannot access `static` items in const fn + --> $DIR/min_const_fn.rs:102:27 + | +LL | const fn foo25() -> u32 { BAR } //~ ERROR cannot access `static` items in const fn + | ^^^ + +error: cannot access `static` items in const fn + --> $DIR/min_const_fn.rs:103:36 + | +LL | const fn foo26() -> &'static u32 { &BAR } //~ ERROR cannot access `static` items + | ^^^^ + +error: casting pointers to ints is unstable in const fn + --> $DIR/min_const_fn.rs:104:42 + | +LL | const fn foo30(x: *const u32) -> usize { x as usize } + | ^^^^^^^^^^ + +error: casting pointers to ints is unstable in const fn + --> $DIR/min_const_fn.rs:106:42 + | +LL | const fn foo30_2(x: *mut u32) -> usize { x as usize } + | ^^^^^^^^^^ + +error: `if`, `match`, `&&` and `||` are not stable in const fn + --> $DIR/min_const_fn.rs:108:38 + | +LL | const fn foo30_4(b: bool) -> usize { if b { 1 } else { 42 } } + | ^^^^^^^^^^^^^^^^^^^^^^ + +error: `if`, `match`, `&&` and `||` are not stable in const fn + --> $DIR/min_const_fn.rs:110:29 + | +LL | const fn foo30_5(b: bool) { while b { } } //~ ERROR not stable in const fn + | ^^^^^^^^^^^ + +error: local variables in const fn are unstable + --> $DIR/min_const_fn.rs:111:34 + | +LL | const fn foo30_6() -> bool { let x = true; x } //~ ERROR local variables in const fn are unstable + | ^ + +error: `if`, `match`, `&&` and `||` are not stable in const fn + --> $DIR/min_const_fn.rs:112:44 + | +LL | const fn foo36(a: bool, b: bool) -> bool { a && b } + | ^^^^^^ + +error: `if`, `match`, `&&` and `||` are not stable in const fn + --> $DIR/min_const_fn.rs:114:44 + | +LL | const fn foo37(a: bool, b: bool) -> bool { a || b } + | ^^^^^^ + +error: mutable references in const fn are unstable + --> $DIR/min_const_fn.rs:116:14 + | +LL | const fn inc(x: &mut i32) { *x += 1 } + | ^ + +error: trait bounds other than `Sized` on const fn parameters are unstable + --> $DIR/min_const_fn.rs:121:6 + | +LL | impl Foo { + | ^ + +error: trait bounds other than `Sized` on const fn parameters are unstable + --> $DIR/min_const_fn.rs:126:6 + | +LL | impl Foo { + | ^ + +error: trait bounds other than `Sized` on const fn parameters are unstable + --> $DIR/min_const_fn.rs:131:6 + | +LL | impl Foo { + | ^ + +error: `impl Trait` in const fn is unstable + --> $DIR/min_const_fn.rs:137:1 + | +LL | const fn no_rpit2() -> AlanTuring { AlanTuring(0) } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: trait bounds other than `Sized` on const fn parameters are unstable + --> $DIR/min_const_fn.rs:139:34 + | +LL | const fn no_apit2(_x: AlanTuring) {} + | ^^^^^^^^^^^^^^^^^^^^ + +error: trait bounds other than `Sized` on const fn parameters are unstable + --> $DIR/min_const_fn.rs:141:22 + | +LL | const fn no_apit(_x: impl std::fmt::Debug) {} //~ ERROR trait bounds other than `Sized` + | ^^^^^^^^^^^^^^^^^^^^ + +error: `impl Trait` in const fn is unstable + --> $DIR/min_const_fn.rs:142:1 + | +LL | const fn no_rpit() -> impl std::fmt::Debug {} //~ ERROR `impl Trait` in const fn is unstable + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: trait bounds other than `Sized` on const fn parameters are unstable + --> $DIR/min_const_fn.rs:143:23 + | +LL | const fn no_dyn_trait(_x: &dyn std::fmt::Debug) {} //~ ERROR trait bounds other than `Sized` + | ^^ + +error: trait bounds other than `Sized` on const fn parameters are unstable + --> $DIR/min_const_fn.rs:144:1 + | +LL | const fn no_dyn_trait_ret() -> &'static dyn std::fmt::Debug { &() } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0597]: borrowed value does not live long enough + --> $DIR/min_const_fn.rs:144:64 + | +LL | const fn no_dyn_trait_ret() -> &'static dyn std::fmt::Debug { &() } + | ^^ - temporary value only lives until here + | | + | temporary value does not live long enough + | + = note: borrowed value must be valid for the static lifetime... + +error: trait bounds other than `Sized` on const fn parameters are unstable + --> $DIR/min_const_fn.rs:149:41 + | +LL | const fn really_no_traits_i_mean_it() { (&() as &std::fmt::Debug, ()).1 } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: function pointers in const fn are unstable + --> $DIR/min_const_fn.rs:152:21 + | +LL | const fn no_fn_ptrs(_x: fn()) {} + | ^^ + +error: function pointers in const fn are unstable + --> $DIR/min_const_fn.rs:154:1 + | +LL | const fn no_fn_ptrs2() -> fn() { fn foo() {} foo } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 36 previous errors + +Some errors occurred: E0493, E0597. +For more information about an error, try `rustc --explain E0493`. diff --git a/src/test/ui/consts/min_const_fn/min_const_fn.rs b/src/test/ui/consts/min_const_fn/min_const_fn.rs new file mode 100644 index 0000000000000..b861e312d4245 --- /dev/null +++ b/src/test/ui/consts/min_const_fn/min_const_fn.rs @@ -0,0 +1,156 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(min_const_fn)] + +// ok +const fn foo1() {} +const fn foo2(x: i32) -> i32 { x } +const fn foo3(x: T) -> T { x } +const fn foo7() { + ( + foo1(), + foo2(420), + foo3(69), + ).0 +} +const fn foo12(t: T) -> T { t } +const fn foo13(t: &T) -> &T { t } +const fn foo14<'a, T: 'a>(t: &'a T) -> &'a T { t } +const fn foo15(t: T) -> T where T: Sized { t } +const fn foo15_2(t: &T) -> &T where T: ?Sized { t } +const fn foo16(f: f32) -> f32 { f } +const fn foo17(f: f32) -> u32 { f as u32 } +const fn foo18(i: i32) -> i32 { i * 3 } +const fn foo20(b: bool) -> bool { !b } +const fn foo21(t: T, u: U) -> (T, U) { (t, u) } +const fn foo22(s: &[u8], i: usize) -> u8 { s[i] } +const FOO: u32 = 42; +const fn foo23() -> u32 { FOO } +const fn foo24() -> &'static u32 { &FOO } +const fn foo27(x: &u32) -> u32 { *x } +const fn foo28(x: u32) -> u32 { *&x } +const fn foo29(x: u32) -> i32 { x as i32 } +const fn foo31(a: bool, b: bool) -> bool { a & b } +const fn foo32(a: bool, b: bool) -> bool { a | b } +const fn foo33(a: bool, b: bool) -> bool { a & b } +const fn foo34(a: bool, b: bool) -> bool { a | b } +const fn foo35(a: bool, b: bool) -> bool { a ^ b } +struct Foo(T); +impl Foo { + const fn new(t: T) -> Self { Foo(t) } + const fn into_inner(self) -> T { self.0 } //~ destructors cannot be evaluated + const fn get(&self) -> &T { &self.0 } + const fn get_mut(&mut self) -> &mut T { &mut self.0 } + //~^ mutable references in const fn are unstable +} +impl<'a, T> Foo { + const fn new_lt(t: T) -> Self { Foo(t) } + const fn into_inner_lt(self) -> T { self.0 } //~ destructors cannot be evaluated + const fn get_lt(&'a self) -> &T { &self.0 } + const fn get_mut_lt(&'a mut self) -> &mut T { &mut self.0 } + //~^ mutable references in const fn are unstable +} +impl Foo { + const fn new_s(t: T) -> Self { Foo(t) } + const fn into_inner_s(self) -> T { self.0 } //~ ERROR destructors + const fn get_s(&self) -> &T { &self.0 } + const fn get_mut_s(&mut self) -> &mut T { &mut self.0 } + //~^ mutable references in const fn are unstable +} +impl Foo { + const fn get_sq(&self) -> &T { &self.0 } + const fn get_mut_sq(&mut self) -> &mut T { &mut self.0 } + //~^ mutable references in const fn are unstable +} + + +const fn char_ops(c: char, d: char) -> bool { c == d } +const fn char_ops2(c: char, d: char) -> bool { c < d } +const fn char_ops3(c: char, d: char) -> bool { c != d } +const fn i32_ops(c: i32, d: i32) -> bool { c == d } +const fn i32_ops2(c: i32, d: i32) -> bool { c < d } +const fn i32_ops3(c: i32, d: i32) -> bool { c != d } +const fn i32_ops4(c: i32, d: i32) -> i32 { c + d } +const fn char_cast(u: u8) -> char { u as char } +const unsafe fn foo4() -> i32 { 42 } +const unsafe fn foo5() -> *const T { 0 as *const T } +const unsafe fn foo6() -> *mut T { 0 as *mut T } + +// not ok +const fn foo11(t: T) -> T { t } +//~^ ERROR trait bounds other than `Sized` on const fn parameters are unstable +const fn foo11_2(t: T) -> T { t } +//~^ ERROR trait bounds other than `Sized` on const fn parameters are unstable +const fn foo19(f: f32) -> f32 { f * 2.0 } +//~^ ERROR only int, `bool` and `char` operations are stable in const fn +const fn foo19_2(f: f32) -> f32 { 2.0 - f } +//~^ ERROR only int, `bool` and `char` operations are stable in const fn +const fn foo19_3(f: f32) -> f32 { -f } +//~^ ERROR only int and `bool` operations are stable in const fn +const fn foo19_4(f: f32, g: f32) -> f32 { f / g } +//~^ ERROR only int, `bool` and `char` operations are stable in const fn + +static BAR: u32 = 42; +const fn foo25() -> u32 { BAR } //~ ERROR cannot access `static` items in const fn +const fn foo26() -> &'static u32 { &BAR } //~ ERROR cannot access `static` items +const fn foo30(x: *const u32) -> usize { x as usize } +//~^ ERROR casting pointers to int +const fn foo30_2(x: *mut u32) -> usize { x as usize } +//~^ ERROR casting pointers to int +const fn foo30_4(b: bool) -> usize { if b { 1 } else { 42 } } +//~^ ERROR `if`, `match`, `&&` and `||` are not stable in const fn +const fn foo30_5(b: bool) { while b { } } //~ ERROR not stable in const fn +const fn foo30_6() -> bool { let x = true; x } //~ ERROR local variables in const fn are unstable +const fn foo36(a: bool, b: bool) -> bool { a && b } +//~^ ERROR `if`, `match`, `&&` and `||` are not stable in const fn +const fn foo37(a: bool, b: bool) -> bool { a || b } +//~^ ERROR `if`, `match`, `&&` and `||` are not stable in const fn +const fn inc(x: &mut i32) { *x += 1 } +//~^ ERROR mutable references in const fn are unstable + +fn main() {} + +impl Foo { +//~^ ERROR trait bounds other than `Sized` on const fn parameters are unstable + const fn foo(&self) {} +} + +impl Foo { +//~^ ERROR trait bounds other than `Sized` on const fn parameters are unstable + const fn foo2(&self) {} +} + +impl Foo { +//~^ ERROR trait bounds other than `Sized` on const fn parameters are unstable + const fn foo3(&self) {} +} + +struct AlanTuring(T); +const fn no_rpit2() -> AlanTuring { AlanTuring(0) } +//~^ ERROR `impl Trait` in const fn is unstable +const fn no_apit2(_x: AlanTuring) {} +//~^ ERROR trait bounds other than `Sized` +const fn no_apit(_x: impl std::fmt::Debug) {} //~ ERROR trait bounds other than `Sized` +const fn no_rpit() -> impl std::fmt::Debug {} //~ ERROR `impl Trait` in const fn is unstable +const fn no_dyn_trait(_x: &dyn std::fmt::Debug) {} //~ ERROR trait bounds other than `Sized` +const fn no_dyn_trait_ret() -> &'static dyn std::fmt::Debug { &() } +//~^ ERROR trait bounds other than `Sized` + +const fn no_unsafe() { unsafe {} } + +const fn really_no_traits_i_mean_it() { (&() as &std::fmt::Debug, ()).1 } +//~^ ERROR trait bounds other than `Sized` + +const fn no_fn_ptrs(_x: fn()) {} +//~^ ERROR function pointers in const fn are unstable +const fn no_fn_ptrs2() -> fn() { fn foo() {} foo } +//~^ ERROR function pointers in const fn are unstable + diff --git a/src/test/ui/consts/min_const_fn/min_const_fn.stderr b/src/test/ui/consts/min_const_fn/min_const_fn.stderr new file mode 100644 index 0000000000000..019948c31b15c --- /dev/null +++ b/src/test/ui/consts/min_const_fn/min_const_fn.stderr @@ -0,0 +1,213 @@ +error[E0493]: destructors cannot be evaluated at compile-time + --> $DIR/min_const_fn.rs:49:25 + | +LL | const fn into_inner(self) -> T { self.0 } //~ destructors cannot be evaluated + | ^^^^ constant functions cannot evaluate destructors + +error: mutable references in const fn are unstable + --> $DIR/min_const_fn.rs:51:5 + | +LL | const fn get_mut(&mut self) -> &mut T { &mut self.0 } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0493]: destructors cannot be evaluated at compile-time + --> $DIR/min_const_fn.rs:56:28 + | +LL | const fn into_inner_lt(self) -> T { self.0 } //~ destructors cannot be evaluated + | ^^^^ constant functions cannot evaluate destructors + +error: mutable references in const fn are unstable + --> $DIR/min_const_fn.rs:58:5 + | +LL | const fn get_mut_lt(&'a mut self) -> &mut T { &mut self.0 } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0493]: destructors cannot be evaluated at compile-time + --> $DIR/min_const_fn.rs:63:27 + | +LL | const fn into_inner_s(self) -> T { self.0 } //~ ERROR destructors + | ^^^^ constant functions cannot evaluate destructors + +error: mutable references in const fn are unstable + --> $DIR/min_const_fn.rs:65:5 + | +LL | const fn get_mut_s(&mut self) -> &mut T { &mut self.0 } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: mutable references in const fn are unstable + --> $DIR/min_const_fn.rs:70:5 + | +LL | const fn get_mut_sq(&mut self) -> &mut T { &mut self.0 } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: trait bounds other than `Sized` on const fn parameters are unstable + --> $DIR/min_const_fn.rs:88:16 + | +LL | const fn foo11(t: T) -> T { t } + | ^ + +error: trait bounds other than `Sized` on const fn parameters are unstable + --> $DIR/min_const_fn.rs:90:18 + | +LL | const fn foo11_2(t: T) -> T { t } + | ^ + +error: only int, `bool` and `char` operations are stable in const fn + --> $DIR/min_const_fn.rs:92:33 + | +LL | const fn foo19(f: f32) -> f32 { f * 2.0 } + | ^^^^^^^ + +error: only int, `bool` and `char` operations are stable in const fn + --> $DIR/min_const_fn.rs:94:35 + | +LL | const fn foo19_2(f: f32) -> f32 { 2.0 - f } + | ^^^^^^^ + +error: only int and `bool` operations are stable in const fn + --> $DIR/min_const_fn.rs:96:35 + | +LL | const fn foo19_3(f: f32) -> f32 { -f } + | ^^ + +error: only int, `bool` and `char` operations are stable in const fn + --> $DIR/min_const_fn.rs:98:43 + | +LL | const fn foo19_4(f: f32, g: f32) -> f32 { f / g } + | ^^^^^ + +error: cannot access `static` items in const fn + --> $DIR/min_const_fn.rs:102:27 + | +LL | const fn foo25() -> u32 { BAR } //~ ERROR cannot access `static` items in const fn + | ^^^ + +error: cannot access `static` items in const fn + --> $DIR/min_const_fn.rs:103:36 + | +LL | const fn foo26() -> &'static u32 { &BAR } //~ ERROR cannot access `static` items + | ^^^^ + +error: casting pointers to ints is unstable in const fn + --> $DIR/min_const_fn.rs:104:42 + | +LL | const fn foo30(x: *const u32) -> usize { x as usize } + | ^^^^^^^^^^ + +error: casting pointers to ints is unstable in const fn + --> $DIR/min_const_fn.rs:106:42 + | +LL | const fn foo30_2(x: *mut u32) -> usize { x as usize } + | ^^^^^^^^^^ + +error: `if`, `match`, `&&` and `||` are not stable in const fn + --> $DIR/min_const_fn.rs:108:38 + | +LL | const fn foo30_4(b: bool) -> usize { if b { 1 } else { 42 } } + | ^^^^^^^^^^^^^^^^^^^^^^ + +error: `if`, `match`, `&&` and `||` are not stable in const fn + --> $DIR/min_const_fn.rs:110:29 + | +LL | const fn foo30_5(b: bool) { while b { } } //~ ERROR not stable in const fn + | ^^^^^^^^^^^ + +error: local variables in const fn are unstable + --> $DIR/min_const_fn.rs:111:34 + | +LL | const fn foo30_6() -> bool { let x = true; x } //~ ERROR local variables in const fn are unstable + | ^ + +error: `if`, `match`, `&&` and `||` are not stable in const fn + --> $DIR/min_const_fn.rs:112:44 + | +LL | const fn foo36(a: bool, b: bool) -> bool { a && b } + | ^^^^^^ + +error: `if`, `match`, `&&` and `||` are not stable in const fn + --> $DIR/min_const_fn.rs:114:44 + | +LL | const fn foo37(a: bool, b: bool) -> bool { a || b } + | ^^^^^^ + +error: mutable references in const fn are unstable + --> $DIR/min_const_fn.rs:116:14 + | +LL | const fn inc(x: &mut i32) { *x += 1 } + | ^ + +error: trait bounds other than `Sized` on const fn parameters are unstable + --> $DIR/min_const_fn.rs:121:6 + | +LL | impl Foo { + | ^ + +error: trait bounds other than `Sized` on const fn parameters are unstable + --> $DIR/min_const_fn.rs:126:6 + | +LL | impl Foo { + | ^ + +error: trait bounds other than `Sized` on const fn parameters are unstable + --> $DIR/min_const_fn.rs:131:6 + | +LL | impl Foo { + | ^ + +error: `impl Trait` in const fn is unstable + --> $DIR/min_const_fn.rs:137:1 + | +LL | const fn no_rpit2() -> AlanTuring { AlanTuring(0) } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: trait bounds other than `Sized` on const fn parameters are unstable + --> $DIR/min_const_fn.rs:139:34 + | +LL | const fn no_apit2(_x: AlanTuring) {} + | ^^^^^^^^^^^^^^^^^^^^ + +error: trait bounds other than `Sized` on const fn parameters are unstable + --> $DIR/min_const_fn.rs:141:22 + | +LL | const fn no_apit(_x: impl std::fmt::Debug) {} //~ ERROR trait bounds other than `Sized` + | ^^^^^^^^^^^^^^^^^^^^ + +error: `impl Trait` in const fn is unstable + --> $DIR/min_const_fn.rs:142:1 + | +LL | const fn no_rpit() -> impl std::fmt::Debug {} //~ ERROR `impl Trait` in const fn is unstable + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: trait bounds other than `Sized` on const fn parameters are unstable + --> $DIR/min_const_fn.rs:143:23 + | +LL | const fn no_dyn_trait(_x: &dyn std::fmt::Debug) {} //~ ERROR trait bounds other than `Sized` + | ^^ + +error: trait bounds other than `Sized` on const fn parameters are unstable + --> $DIR/min_const_fn.rs:144:1 + | +LL | const fn no_dyn_trait_ret() -> &'static dyn std::fmt::Debug { &() } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: trait bounds other than `Sized` on const fn parameters are unstable + --> $DIR/min_const_fn.rs:149:41 + | +LL | const fn really_no_traits_i_mean_it() { (&() as &std::fmt::Debug, ()).1 } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: function pointers in const fn are unstable + --> $DIR/min_const_fn.rs:152:21 + | +LL | const fn no_fn_ptrs(_x: fn()) {} + | ^^ + +error: function pointers in const fn are unstable + --> $DIR/min_const_fn.rs:154:1 + | +LL | const fn no_fn_ptrs2() -> fn() { fn foo() {} foo } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 35 previous errors + +For more information about this error, try `rustc --explain E0493`. diff --git a/src/test/ui/consts/min_const_fn/min_const_fn_dyn.nll.stderr b/src/test/ui/consts/min_const_fn/min_const_fn_dyn.nll.stderr new file mode 100644 index 0000000000000..cfcc7990fb30d --- /dev/null +++ b/src/test/ui/consts/min_const_fn/min_const_fn_dyn.nll.stderr @@ -0,0 +1,25 @@ +error: trait bounds other than `Sized` on const fn parameters are unstable + --> $DIR/min_const_fn_dyn.rs:21:5 + | +LL | x.0.field; + | ^^^^^^^^^ + +error: trait bounds other than `Sized` on const fn parameters are unstable + --> $DIR/min_const_fn_dyn.rs:24:66 + | +LL | const fn no_inner_dyn_trait_ret() -> Hide { Hide(HasDyn { field: &0 }) } + | ^^ + +error[E0597]: borrowed value does not live long enough + --> $DIR/min_const_fn_dyn.rs:24:67 + | +LL | const fn no_inner_dyn_trait_ret() -> Hide { Hide(HasDyn { field: &0 }) } + | ^ - temporary value only lives until here + | | + | temporary value does not live long enough + | + = note: borrowed value must be valid for the static lifetime... + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0597`. diff --git a/src/test/ui/consts/min_const_fn/min_const_fn_dyn.rs b/src/test/ui/consts/min_const_fn/min_const_fn_dyn.rs new file mode 100644 index 0000000000000..38e2825643009 --- /dev/null +++ b/src/test/ui/consts/min_const_fn/min_const_fn_dyn.rs @@ -0,0 +1,27 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(min_const_fn)] + +struct HasDyn { + field: &'static dyn std::fmt::Debug, +} + +struct Hide(HasDyn); + +const fn no_inner_dyn_trait(_x: Hide) {} +const fn no_inner_dyn_trait2(x: Hide) { + x.0.field; +//~^ ERROR trait bounds other than `Sized` +} +const fn no_inner_dyn_trait_ret() -> Hide { Hide(HasDyn { field: &0 }) } +//~^ ERROR trait bounds other than `Sized` + +fn main() {} diff --git a/src/test/ui/consts/min_const_fn/min_const_fn_dyn.stderr b/src/test/ui/consts/min_const_fn/min_const_fn_dyn.stderr new file mode 100644 index 0000000000000..3a1055f2ede15 --- /dev/null +++ b/src/test/ui/consts/min_const_fn/min_const_fn_dyn.stderr @@ -0,0 +1,14 @@ +error: trait bounds other than `Sized` on const fn parameters are unstable + --> $DIR/min_const_fn_dyn.rs:21:5 + | +LL | x.0.field; + | ^^^^^^^^^ + +error: trait bounds other than `Sized` on const fn parameters are unstable + --> $DIR/min_const_fn_dyn.rs:24:66 + | +LL | const fn no_inner_dyn_trait_ret() -> Hide { Hide(HasDyn { field: &0 }) } + | ^^ + +error: aborting due to 2 previous errors + diff --git a/src/test/ui/consts/min_const_fn/min_const_fn_fn_ptr.rs b/src/test/ui/consts/min_const_fn/min_const_fn_fn_ptr.rs new file mode 100644 index 0000000000000..100d275f97e73 --- /dev/null +++ b/src/test/ui/consts/min_const_fn/min_const_fn_fn_ptr.rs @@ -0,0 +1,29 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(min_const_fn)] + +struct HasPtr { + field: fn(), +} + +struct Hide(HasPtr); + +fn field() {} + +const fn no_inner_dyn_trait(_x: Hide) {} +const fn no_inner_dyn_trait2(x: Hide) { + x.0.field; +//~^ ERROR function pointers in const fn +} +const fn no_inner_dyn_trait_ret() -> Hide { Hide(HasPtr { field }) } +//~^ ERROR function pointers in const fn + +fn main() {} diff --git a/src/test/ui/consts/min_const_fn/min_const_fn_fn_ptr.stderr b/src/test/ui/consts/min_const_fn/min_const_fn_fn_ptr.stderr new file mode 100644 index 0000000000000..c10af3d2c8e71 --- /dev/null +++ b/src/test/ui/consts/min_const_fn/min_const_fn_fn_ptr.stderr @@ -0,0 +1,14 @@ +error: function pointers in const fn are unstable + --> $DIR/min_const_fn_fn_ptr.rs:23:5 + | +LL | x.0.field; + | ^^^^^^^^^ + +error: function pointers in const fn are unstable + --> $DIR/min_const_fn_fn_ptr.rs:26:59 + | +LL | const fn no_inner_dyn_trait_ret() -> Hide { Hide(HasPtr { field }) } + | ^^^^^ + +error: aborting due to 2 previous errors + diff --git a/src/test/ui/consts/min_const_fn/min_const_fn_libstd_stability.rs b/src/test/ui/consts/min_const_fn/min_const_fn_libstd_stability.rs new file mode 100644 index 0000000000000..4ce62ecc48533 --- /dev/null +++ b/src/test/ui/consts/min_const_fn/min_const_fn_libstd_stability.rs @@ -0,0 +1,38 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![unstable(feature = "humans", + reason = "who ever let humans program computers, + we're apparently really bad at it", + issue = "0")] + +#![feature(rustc_const_unstable, const_fn, foo)] +#![feature(staged_api)] + +#[stable(feature = "rust1", since = "1.0.0")] +#[rustc_const_unstable(feature="foo")] +const fn foo() -> u32 { 42 } + +#[stable(feature = "rust1", since = "1.0.0")] +// can't call non-min_const_fn +const fn bar() -> u32 { foo() } //~ ERROR can only call other `min_const_fn` + +#[unstable(feature = "rust1", issue="0")] +const fn foo2() -> u32 { 42 } + +#[stable(feature = "rust1", since = "1.0.0")] +// can't call non-min_const_fn +const fn bar2() -> u32 { foo2() } //~ ERROR can only call other `min_const_fn` + +#[stable(feature = "rust1", since = "1.0.0")] +// conformity is required, even with `const_fn` feature gate +const fn bar3() -> u32 { (5f32 + 6f32) as u32 } //~ ERROR only int, `bool` and `char` operations + +fn main() {} diff --git a/src/test/ui/consts/min_const_fn/min_const_fn_libstd_stability.stderr b/src/test/ui/consts/min_const_fn/min_const_fn_libstd_stability.stderr new file mode 100644 index 0000000000000..8e47090890db3 --- /dev/null +++ b/src/test/ui/consts/min_const_fn/min_const_fn_libstd_stability.stderr @@ -0,0 +1,20 @@ +error: can only call other `min_const_fn` within a `min_const_fn` + --> $DIR/min_const_fn_libstd_stability.rs:25:25 + | +LL | const fn bar() -> u32 { foo() } //~ ERROR can only call other `min_const_fn` + | ^^^^^ + +error: can only call other `min_const_fn` within a `min_const_fn` + --> $DIR/min_const_fn_libstd_stability.rs:32:26 + | +LL | const fn bar2() -> u32 { foo2() } //~ ERROR can only call other `min_const_fn` + | ^^^^^^ + +error: only int, `bool` and `char` operations are stable in const fn + --> $DIR/min_const_fn_libstd_stability.rs:36:26 + | +LL | const fn bar3() -> u32 { (5f32 + 6f32) as u32 } //~ ERROR only int, `bool` and `char` operations + | ^^^^^^^^^^^^^ + +error: aborting due to 3 previous errors + diff --git a/src/test/ui/consts/min_const_fn/min_const_fn_unsafe.rs b/src/test/ui/consts/min_const_fn/min_const_fn_unsafe.rs new file mode 100644 index 0000000000000..e7caa4c6cb426 --- /dev/null +++ b/src/test/ui/consts/min_const_fn/min_const_fn_unsafe.rs @@ -0,0 +1,38 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(min_const_fn)] + +// ok +const unsafe fn foo4() -> i32 { 42 } +const unsafe fn foo5() -> *const T { 0 as *const T } +const unsafe fn foo6() -> *mut T { 0 as *mut T } +const fn no_unsafe() { unsafe {} } + +// not ok +const fn foo8() -> i32 { + unsafe { foo4() } //~ ERROR unsafe operations are not allowed in const fn +} +const fn foo9() -> *const String { + unsafe { foo5::() } //~ ERROR unsafe operations are not allowed in const fn +} +const fn foo10() -> *const Vec> { + unsafe { foo6::>>() } //~ ERROR not allowed in const fn +} +const unsafe fn foo30_3(x: *mut usize) -> usize { *x } //~ ERROR not allowed in const fn +//~^ dereferencing raw pointers in constant functions + +fn main() {} + +const unsafe fn no_union() { + union Foo { x: (), y: () } + Foo { x: () }.y //~ ERROR not allowed in const fn + //~^ unions in const fn +} diff --git a/src/test/ui/consts/min_const_fn/min_const_fn_unsafe.stderr b/src/test/ui/consts/min_const_fn/min_const_fn_unsafe.stderr new file mode 100644 index 0000000000000..17cba8569c148 --- /dev/null +++ b/src/test/ui/consts/min_const_fn/min_const_fn_unsafe.stderr @@ -0,0 +1,59 @@ +error[E0658]: dereferencing raw pointers in constant functions is unstable (see issue #51911) + --> $DIR/min_const_fn_unsafe.rs:29:51 + | +LL | const unsafe fn foo30_3(x: *mut usize) -> usize { *x } //~ ERROR not allowed in const fn + | ^^ + | + = help: add #![feature(const_raw_ptr_deref)] to the crate attributes to enable + +error[E0658]: unions in const fn are unstable (see issue #51909) + --> $DIR/min_const_fn_unsafe.rs:36:5 + | +LL | Foo { x: () }.y //~ ERROR not allowed in const fn + | ^^^^^^^^^^^^^^^ + | + = help: add #![feature(const_fn_union)] to the crate attributes to enable + +error: call to unsafe function is unsafe and unsafe operations are not allowed in const fn + --> $DIR/min_const_fn_unsafe.rs:21:14 + | +LL | unsafe { foo4() } //~ ERROR unsafe operations are not allowed in const fn + | ^^^^^^ call to unsafe function + | + = note: consult the function's documentation for information on how to avoid undefined behavior + +error: call to unsafe function is unsafe and unsafe operations are not allowed in const fn + --> $DIR/min_const_fn_unsafe.rs:24:14 + | +LL | unsafe { foo5::() } //~ ERROR unsafe operations are not allowed in const fn + | ^^^^^^^^^^^^^^^^ call to unsafe function + | + = note: consult the function's documentation for information on how to avoid undefined behavior + +error: call to unsafe function is unsafe and unsafe operations are not allowed in const fn + --> $DIR/min_const_fn_unsafe.rs:27:14 + | +LL | unsafe { foo6::>>() } //~ ERROR not allowed in const fn + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ call to unsafe function + | + = note: consult the function's documentation for information on how to avoid undefined behavior + +error: dereference of raw pointer is unsafe and unsafe operations are not allowed in const fn + --> $DIR/min_const_fn_unsafe.rs:29:51 + | +LL | const unsafe fn foo30_3(x: *mut usize) -> usize { *x } //~ ERROR not allowed in const fn + | ^^ dereference of raw pointer + | + = note: raw pointers may be NULL, dangling or unaligned; they can violate aliasing rules and cause data races: all of these are undefined behavior + +error: access to union field is unsafe and unsafe operations are not allowed in const fn + --> $DIR/min_const_fn_unsafe.rs:36:5 + | +LL | Foo { x: () }.y //~ ERROR not allowed in const fn + | ^^^^^^^^^^^^^^^ access to union field + | + = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior + +error: aborting due to 7 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/error-codes/E0308.stderr b/src/test/ui/error-codes/E0308.stderr index 490a8e0ff0f1d..438dd50f2bfa8 100644 --- a/src/test/ui/error-codes/E0308.stderr +++ b/src/test/ui/error-codes/E0308.stderr @@ -4,8 +4,8 @@ error[E0308]: intrinsic has wrong type LL | fn size_of(); //~ ERROR E0308 | ^^^^^^^^^^^^^^^^ expected (), found usize | - = note: expected type `unsafe extern "rust-intrinsic" fn()` - found type `unsafe extern "rust-intrinsic" fn() -> usize` + = note: expected type `extern "rust-intrinsic" fn()` + found type `extern "rust-intrinsic" fn() -> usize` error: aborting due to previous error diff --git a/src/test/ui/feature-gates/feature-gate-const_fn.rs b/src/test/ui/feature-gates/feature-gate-const_fn.rs index 1d1dedddaaa3e..f774658975b79 100644 --- a/src/test/ui/feature-gates/feature-gate-const_fn.rs +++ b/src/test/ui/feature-gates/feature-gate-const_fn.rs @@ -8,9 +8,11 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// Test use of const fn without feature gate. +// Test use of const fn without the `const_fn` feature gate. +// `min_const_fn` is checked in its own file +#![feature(min_const_fn)] -const fn foo() -> usize { 0 } //~ ERROR const fn is unstable +const fn foo() -> usize { 0 } // ok trait Foo { const fn foo() -> u32; //~ ERROR const fn is unstable @@ -20,12 +22,11 @@ trait Foo { } impl Foo { - const fn baz() -> u32 { 0 } //~ ERROR const fn is unstable + const fn baz() -> u32 { 0 } // ok } impl Foo for u32 { - const fn foo() -> u32 { 0 } //~ ERROR const fn is unstable - //~| ERROR trait fns cannot be declared const + const fn foo() -> u32 { 0 } //~ ERROR trait fns cannot be declared const } static FOO: usize = foo(); diff --git a/src/test/ui/feature-gates/feature-gate-const_fn.stderr b/src/test/ui/feature-gates/feature-gate-const_fn.stderr index d7c00a3e0cb40..26c0c7877b4ec 100644 --- a/src/test/ui/feature-gates/feature-gate-const_fn.stderr +++ b/src/test/ui/feature-gates/feature-gate-const_fn.stderr @@ -1,31 +1,23 @@ error[E0379]: trait fns cannot be declared const - --> $DIR/feature-gate-const_fn.rs:16:5 + --> $DIR/feature-gate-const_fn.rs:18:5 | LL | const fn foo() -> u32; //~ ERROR const fn is unstable | ^^^^^ trait fns cannot be const error[E0379]: trait fns cannot be declared const - --> $DIR/feature-gate-const_fn.rs:18:5 + --> $DIR/feature-gate-const_fn.rs:20:5 | LL | const fn bar() -> u32 { 0 } //~ ERROR const fn is unstable | ^^^^^ trait fns cannot be const error[E0379]: trait fns cannot be declared const - --> $DIR/feature-gate-const_fn.rs:27:5 + --> $DIR/feature-gate-const_fn.rs:29:5 | -LL | const fn foo() -> u32 { 0 } //~ ERROR const fn is unstable +LL | const fn foo() -> u32 { 0 } //~ ERROR trait fns cannot be declared const | ^^^^^ trait fns cannot be const error[E0658]: const fn is unstable (see issue #24111) - --> $DIR/feature-gate-const_fn.rs:13:1 - | -LL | const fn foo() -> usize { 0 } //~ ERROR const fn is unstable - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = help: add #![feature(const_fn)] to the crate attributes to enable - -error[E0658]: const fn is unstable (see issue #24111) - --> $DIR/feature-gate-const_fn.rs:16:5 + --> $DIR/feature-gate-const_fn.rs:18:5 | LL | const fn foo() -> u32; //~ ERROR const fn is unstable | ^^^^^^^^^^^^^^^^^^^^^^ @@ -33,30 +25,14 @@ LL | const fn foo() -> u32; //~ ERROR const fn is unstable = help: add #![feature(const_fn)] to the crate attributes to enable error[E0658]: const fn is unstable (see issue #24111) - --> $DIR/feature-gate-const_fn.rs:18:5 + --> $DIR/feature-gate-const_fn.rs:20:5 | LL | const fn bar() -> u32 { 0 } //~ ERROR const fn is unstable | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = help: add #![feature(const_fn)] to the crate attributes to enable -error[E0658]: const fn is unstable (see issue #24111) - --> $DIR/feature-gate-const_fn.rs:23:5 - | -LL | const fn baz() -> u32 { 0 } //~ ERROR const fn is unstable - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = help: add #![feature(const_fn)] to the crate attributes to enable - -error[E0658]: const fn is unstable (see issue #24111) - --> $DIR/feature-gate-const_fn.rs:27:5 - | -LL | const fn foo() -> u32 { 0 } //~ ERROR const fn is unstable - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = help: add #![feature(const_fn)] to the crate attributes to enable - -error: aborting due to 8 previous errors +error: aborting due to 5 previous errors Some errors occurred: E0379, E0658. For more information about an error, try `rustc --explain E0379`. diff --git a/src/test/ui/feature-gates/feature-gate-min_const_fn.rs b/src/test/ui/feature-gates/feature-gate-min_const_fn.rs new file mode 100644 index 0000000000000..e052ba9c8b43a --- /dev/null +++ b/src/test/ui/feature-gates/feature-gate-min_const_fn.rs @@ -0,0 +1,46 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Test use of min_const_fn without feature gate. + +const fn foo() -> usize { 0 } //~ ERROR const fn is unstable + +trait Foo { + const fn foo() -> u32; //~ ERROR const fn is unstable + //~| ERROR trait fns cannot be declared const + const fn bar() -> u32 { 0 } //~ ERROR const fn is unstable + //~| ERROR trait fns cannot be declared const +} + +impl Foo { + const fn baz() -> u32 { 0 } //~ ERROR const fn is unstable +} + +impl Foo for u32 { + const fn foo() -> u32 { 0 } //~ ERROR const fn is unstable + //~| ERROR trait fns cannot be declared const +} + +static FOO: usize = foo(); +const BAR: usize = foo(); + +macro_rules! constant { + ($n:ident: $t:ty = $v:expr) => { + const $n: $t = $v; + } +} + +constant! { + BAZ: usize = foo() +} + +fn main() { + let x: [usize; foo()] = []; +} diff --git a/src/test/ui/feature-gates/feature-gate-min_const_fn.stderr b/src/test/ui/feature-gates/feature-gate-min_const_fn.stderr new file mode 100644 index 0000000000000..aa7750362b2fd --- /dev/null +++ b/src/test/ui/feature-gates/feature-gate-min_const_fn.stderr @@ -0,0 +1,62 @@ +error[E0379]: trait fns cannot be declared const + --> $DIR/feature-gate-min_const_fn.rs:16:5 + | +LL | const fn foo() -> u32; //~ ERROR const fn is unstable + | ^^^^^ trait fns cannot be const + +error[E0379]: trait fns cannot be declared const + --> $DIR/feature-gate-min_const_fn.rs:18:5 + | +LL | const fn bar() -> u32 { 0 } //~ ERROR const fn is unstable + | ^^^^^ trait fns cannot be const + +error[E0379]: trait fns cannot be declared const + --> $DIR/feature-gate-min_const_fn.rs:27:5 + | +LL | const fn foo() -> u32 { 0 } //~ ERROR const fn is unstable + | ^^^^^ trait fns cannot be const + +error[E0658]: const fn is unstable (see issue #53555) + --> $DIR/feature-gate-min_const_fn.rs:13:1 + | +LL | const fn foo() -> usize { 0 } //~ ERROR const fn is unstable + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add #![feature(min_const_fn)] to the crate attributes to enable + +error[E0658]: const fn is unstable (see issue #24111) + --> $DIR/feature-gate-min_const_fn.rs:16:5 + | +LL | const fn foo() -> u32; //~ ERROR const fn is unstable + | ^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add #![feature(const_fn)] to the crate attributes to enable + +error[E0658]: const fn is unstable (see issue #24111) + --> $DIR/feature-gate-min_const_fn.rs:18:5 + | +LL | const fn bar() -> u32 { 0 } //~ ERROR const fn is unstable + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add #![feature(const_fn)] to the crate attributes to enable + +error[E0658]: const fn is unstable (see issue #53555) + --> $DIR/feature-gate-min_const_fn.rs:23:5 + | +LL | const fn baz() -> u32 { 0 } //~ ERROR const fn is unstable + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add #![feature(min_const_fn)] to the crate attributes to enable + +error[E0658]: const fn is unstable (see issue #53555) + --> $DIR/feature-gate-min_const_fn.rs:27:5 + | +LL | const fn foo() -> u32 { 0 } //~ ERROR const fn is unstable + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add #![feature(min_const_fn)] to the crate attributes to enable + +error: aborting due to 8 previous errors + +Some errors occurred: E0379, E0658. +For more information about an error, try `rustc --explain E0379`. From 7b3d930ca6f8269d07bce30ace4a9be2f316a63a Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Wed, 29 Aug 2018 13:00:14 +0200 Subject: [PATCH 17/36] Libstd only has `min_const_fn` const fns --- src/libstd/lib.rs | 3 +- .../min_const_fn/min_const_fn_libstd.rs | 38 +++++++++++++++++++ 2 files changed, 40 insertions(+), 1 deletion(-) create mode 100644 src/test/ui/consts/min_const_fn/min_const_fn_libstd.rs diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs index 310475d31fded..e7195b3e21ee3 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -250,7 +250,8 @@ #![feature(cfg_target_vendor)] #![feature(char_error_internals)] #![feature(compiler_builtins_lib)] -#![feature(const_fn)] +#![cfg_attr(stage0, feature(const_fn))] +#![cfg_attr(not(stage0), feature(min_const_fn))] #![feature(const_int_ops)] #![feature(const_ip)] #![feature(core_intrinsics)] diff --git a/src/test/ui/consts/min_const_fn/min_const_fn_libstd.rs b/src/test/ui/consts/min_const_fn/min_const_fn_libstd.rs new file mode 100644 index 0000000000000..fcc9545d97f15 --- /dev/null +++ b/src/test/ui/consts/min_const_fn/min_const_fn_libstd.rs @@ -0,0 +1,38 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(integer_atomics, min_const_fn)] + +// compile-pass + +use std::cell::UnsafeCell; +use std::sync::atomic::AtomicU32; +pub struct Condvar { + condvar: UnsafeCell, +} + +unsafe impl Send for Condvar {} +unsafe impl Sync for Condvar {} + +#[repr(C)] +#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] +struct NoWait(u32); + +const CONDVAR_HAS_NO_WAITERS: NoWait = NoWait(42); + +impl Condvar { + pub const fn new() -> Condvar { + Condvar { + condvar: UnsafeCell::new(AtomicU32::new(CONDVAR_HAS_NO_WAITERS.0)), + } + } +} + +fn main() {} From d125e904b5e298f710c7a5a1aaa3ebd953d2ced3 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Wed, 29 Aug 2018 13:20:43 +0200 Subject: [PATCH 18/36] Restrict most uses of `const_fn` to `min_const_fn` --- src/liballoc/lib.rs | 3 ++- src/liballoc/tests/lib.rs | 3 ++- src/librustc/lib.rs | 3 ++- src/librustc_mir/lib.rs | 1 - src/librustc_target/lib.rs | 3 ++- .../codegen-units/item-collection/unreferenced-const-fn.rs | 2 +- src/test/codegen/link-dead-code.rs | 2 +- src/test/compile-fail/issue-43733-2.rs | 2 +- src/test/mir-opt/lower_128bit_debug_test.rs | 2 +- src/test/mir-opt/lower_128bit_test.rs | 2 +- src/test/run-fail/issue-29798.rs | 2 +- src/test/run-pass/auxiliary/const_fn_lib.rs | 2 +- src/test/run-pass/auxiliary/issue-36954.rs | 2 +- src/test/run-pass/const-fn-const-eval.rs | 2 +- src/test/run-pass/const-fn-method.rs | 2 +- src/test/run-pass/const-fn-nested.rs | 2 +- src/test/run-pass/const-meth-pattern.rs | 2 +- src/test/run-pass/const-pattern-variant.rs | 2 +- src/test/run-pass/const-size_of-align_of.rs | 2 +- src/test/run-pass/const-unsafe-fn.rs | 2 +- src/test/run-pass/consts-in-patterns.rs | 2 +- src/test/run-pass/ctfe/ice-48279.rs | 2 +- src/test/run-pass/ctfe/match-const-fn-structs.rs | 2 +- src/test/run-pass/ctfe/return-in-const-fn.rs | 2 +- src/test/run-pass/issue-28822.rs | 2 +- src/test/run-pass/issue-29927.rs | 2 +- src/test/run-pass/issue-33537.rs | 2 +- src/test/run-pass/issue-37991.rs | 2 +- src/test/run-pass/issue29927-1.rs | 2 +- src/test/rustdoc/auxiliary/issue-27362.rs | 2 +- src/test/rustdoc/const-fn.rs | 2 +- src/test/rustdoc/const.rs | 2 +- src/test/ui/borrowck/move-in-static-initializer-issue-38520.rs | 2 +- src/test/ui/consts/auxiliary/const_fn_lib.rs | 2 +- src/test/ui/consts/const-eval/issue-43197.rs | 2 +- src/test/ui/consts/const-eval/issue-47971.rs | 2 +- src/test/ui/consts/const-pattern-not-const-evaluable.rs | 2 +- src/test/ui/consts/const-size_of-cycle.rs | 2 -- src/test/ui/infinite/infinite-recursion-const-fn.rs | 2 +- src/test/ui/issues/issue-44415.rs | 2 +- src/test/ui/unsafe/unsafe-const-fn.rs | 2 +- 41 files changed, 43 insertions(+), 42 deletions(-) diff --git a/src/liballoc/lib.rs b/src/liballoc/lib.rs index 676c977514f32..452d2b1472ff4 100644 --- a/src/liballoc/lib.rs +++ b/src/liballoc/lib.rs @@ -88,7 +88,8 @@ #![feature(box_syntax)] #![feature(cfg_target_has_atomic)] #![feature(coerce_unsized)] -#![feature(const_fn)] +#![cfg_attr(stage0, feature(const_fn))] +#![cfg_attr(not(stage0), feature(min_const_fn))] #![feature(core_intrinsics)] #![feature(custom_attribute)] #![feature(dropck_eyepatch)] diff --git a/src/liballoc/tests/lib.rs b/src/liballoc/tests/lib.rs index 3a84f9e7e47ba..710c659ac5396 100644 --- a/src/liballoc/tests/lib.rs +++ b/src/liballoc/tests/lib.rs @@ -11,7 +11,8 @@ #![feature(allocator_api)] #![feature(alloc_system)] #![feature(box_syntax)] -#![feature(const_fn)] +#![cfg_attr(stage0, feature(const_fn))] +#![cfg_attr(not(stage0), feature(min_const_fn))] #![feature(drain_filter)] #![feature(exact_size_is_empty)] #![feature(pattern)] diff --git a/src/librustc/lib.rs b/src/librustc/lib.rs index d014f319564fe..d79281666d639 100644 --- a/src/librustc/lib.rs +++ b/src/librustc/lib.rs @@ -42,7 +42,8 @@ #![feature(box_patterns)] #![feature(box_syntax)] -#![feature(const_fn)] +#![cfg_attr(stage0, feature(const_fn))] +#![cfg_attr(not(stage0), feature(min_const_fn))] #![feature(core_intrinsics)] #![feature(drain_filter)] #![cfg_attr(windows, feature(libc))] diff --git a/src/librustc_mir/lib.rs b/src/librustc_mir/lib.rs index f91ff3642cd10..6f087221b8024 100644 --- a/src/librustc_mir/lib.rs +++ b/src/librustc_mir/lib.rs @@ -23,7 +23,6 @@ Rust MIR: a lowered representation of Rust. Also: an experiment! #![feature(box_patterns)] #![feature(box_syntax)] #![feature(crate_visibility_modifier)] -#![feature(const_fn)] #![feature(core_intrinsics)] #![feature(decl_macro)] #![cfg_attr(stage0, feature(macro_vis_matcher))] diff --git a/src/librustc_target/lib.rs b/src/librustc_target/lib.rs index 1e70a806cce89..e4d958e3b6f35 100644 --- a/src/librustc_target/lib.rs +++ b/src/librustc_target/lib.rs @@ -22,7 +22,8 @@ html_root_url = "https://doc.rust-lang.org/nightly/")] #![feature(box_syntax)] -#![feature(const_fn)] +#![cfg_attr(stage0, feature(const_fn))] +#![cfg_attr(not(stage0), feature(min_const_fn))] #![cfg_attr(not(stage0), feature(nll))] #![cfg_attr(not(stage0), feature(infer_outlives_requirements))] #![feature(slice_patterns)] diff --git a/src/test/codegen-units/item-collection/unreferenced-const-fn.rs b/src/test/codegen-units/item-collection/unreferenced-const-fn.rs index c2ff846721c5f..1462417643600 100644 --- a/src/test/codegen-units/item-collection/unreferenced-const-fn.rs +++ b/src/test/codegen-units/item-collection/unreferenced-const-fn.rs @@ -13,7 +13,7 @@ // NB: We do not expect *any* monomorphization to be generated here. -#![feature(const_fn)] +#![feature(min_const_fn)] #![deny(dead_code)] #![crate_type = "rlib"] diff --git a/src/test/codegen/link-dead-code.rs b/src/test/codegen/link-dead-code.rs index 9cabcd9157a6a..3ea20aa921e1b 100644 --- a/src/test/codegen/link-dead-code.rs +++ b/src/test/codegen/link-dead-code.rs @@ -10,7 +10,7 @@ // compile-flags:-Clink-dead-code -#![feature(const_fn)] +#![feature(min_const_fn)] #![crate_type = "rlib"] // This test makes sure that, when -Clink-dead-code is specified, we generate diff --git a/src/test/compile-fail/issue-43733-2.rs b/src/test/compile-fail/issue-43733-2.rs index a5ba9ef9bd35d..fea81f0cc8fa4 100644 --- a/src/test/compile-fail/issue-43733-2.rs +++ b/src/test/compile-fail/issue-43733-2.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(const_fn)] +#![feature(min_const_fn)] #![feature(cfg_target_thread_local, thread_local_internals)] // On platforms *without* `#[thread_local]`, use diff --git a/src/test/mir-opt/lower_128bit_debug_test.rs b/src/test/mir-opt/lower_128bit_debug_test.rs index 646c4312fc21f..1bf740fdec619 100644 --- a/src/test/mir-opt/lower_128bit_debug_test.rs +++ b/src/test/mir-opt/lower_128bit_debug_test.rs @@ -15,7 +15,7 @@ // compile-flags: -Z lower_128bit_ops=yes -C debug_assertions=yes -#![feature(const_fn)] +#![feature(min_const_fn)] static TEST_SIGNED: i128 = const_signed(-222); static TEST_UNSIGNED: u128 = const_unsigned(200); diff --git a/src/test/mir-opt/lower_128bit_test.rs b/src/test/mir-opt/lower_128bit_test.rs index 72c0e33cd9ecf..235df8a6785d4 100644 --- a/src/test/mir-opt/lower_128bit_test.rs +++ b/src/test/mir-opt/lower_128bit_test.rs @@ -12,7 +12,7 @@ // compile-flags: -Z lower_128bit_ops=yes -C debug_assertions=no -O -#![feature(const_fn)] +#![feature(min_const_fn)] static TEST_SIGNED: i128 = const_signed(-222); static TEST_UNSIGNED: u128 = const_unsigned(200); diff --git a/src/test/run-fail/issue-29798.rs b/src/test/run-fail/issue-29798.rs index a77175975f941..30efe3b9ab2c4 100644 --- a/src/test/run-fail/issue-29798.rs +++ b/src/test/run-fail/issue-29798.rs @@ -10,7 +10,7 @@ // error-pattern:index out of bounds: the len is 5 but the index is 5 -#![feature(const_fn)] +#![feature(min_const_fn)] const fn test(x: usize) -> i32 { [42;5][x] } diff --git a/src/test/run-pass/auxiliary/const_fn_lib.rs b/src/test/run-pass/auxiliary/const_fn_lib.rs index be06e8dd5700b..6985a6527c874 100644 --- a/src/test/run-pass/auxiliary/const_fn_lib.rs +++ b/src/test/run-pass/auxiliary/const_fn_lib.rs @@ -11,6 +11,6 @@ // Crate that exports a const fn. Used for testing cross-crate. #![crate_type="rlib"] -#![feature(const_fn)] +#![feature(min_const_fn)] pub const fn foo() -> usize { 22 } diff --git a/src/test/run-pass/auxiliary/issue-36954.rs b/src/test/run-pass/auxiliary/issue-36954.rs index 832ee1d7c1b45..5351a40916b7d 100644 --- a/src/test/run-pass/auxiliary/issue-36954.rs +++ b/src/test/run-pass/auxiliary/issue-36954.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(const_fn)] +#![feature(min_const_fn)] #![crate_type = "lib"] const fn foo(i: i32) -> i32 { diff --git a/src/test/run-pass/const-fn-const-eval.rs b/src/test/run-pass/const-fn-const-eval.rs index 77c70fe7f6354..3fe27ca200cb0 100644 --- a/src/test/run-pass/const-fn-const-eval.rs +++ b/src/test/run-pass/const-fn-const-eval.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(const_fn)] +#![feature(min_const_fn)] const fn add(x: usize, y: usize) -> usize { x + y diff --git a/src/test/run-pass/const-fn-method.rs b/src/test/run-pass/const-fn-method.rs index 7d8d941439cf8..bed78f1e8978f 100644 --- a/src/test/run-pass/const-fn-method.rs +++ b/src/test/run-pass/const-fn-method.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(const_fn)] +#![feature(min_const_fn)] struct Foo { value: u32 } diff --git a/src/test/run-pass/const-fn-nested.rs b/src/test/run-pass/const-fn-nested.rs index 86f5dedc4d1b1..d5959a89e51a5 100644 --- a/src/test/run-pass/const-fn-nested.rs +++ b/src/test/run-pass/const-fn-nested.rs @@ -10,7 +10,7 @@ // Test a call whose argument is the result of another call. -#![feature(const_fn)] +#![feature(min_const_fn)] const fn sub(x: u32, y: u32) -> u32 { x - y diff --git a/src/test/run-pass/const-meth-pattern.rs b/src/test/run-pass/const-meth-pattern.rs index 3b27987f190cd..836716051d213 100644 --- a/src/test/run-pass/const-meth-pattern.rs +++ b/src/test/run-pass/const-meth-pattern.rs @@ -7,7 +7,7 @@ // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(const_fn)] +#![feature(min_const_fn)] struct A; diff --git a/src/test/run-pass/const-pattern-variant.rs b/src/test/run-pass/const-pattern-variant.rs index 104ab6e19db67..689ae19e7d4f4 100644 --- a/src/test/run-pass/const-pattern-variant.rs +++ b/src/test/run-pass/const-pattern-variant.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(const_fn)] +#![feature(min_const_fn)] #[derive(PartialEq, Eq)] enum Cake { diff --git a/src/test/run-pass/const-size_of-align_of.rs b/src/test/run-pass/const-size_of-align_of.rs index 06fbe9bf4f639..245dd673b512c 100644 --- a/src/test/run-pass/const-size_of-align_of.rs +++ b/src/test/run-pass/const-size_of-align_of.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(const_fn)] +#![feature(min_const_fn)] use std::mem; diff --git a/src/test/run-pass/const-unsafe-fn.rs b/src/test/run-pass/const-unsafe-fn.rs index 2511cfd042206..b267245b78969 100644 --- a/src/test/run-pass/const-unsafe-fn.rs +++ b/src/test/run-pass/const-unsafe-fn.rs @@ -10,7 +10,7 @@ // A quick test of 'unsafe const fn' functionality -#![feature(const_fn)] +#![feature(min_const_fn)] const unsafe fn dummy(v: u32) -> u32 { !v diff --git a/src/test/run-pass/consts-in-patterns.rs b/src/test/run-pass/consts-in-patterns.rs index eec4c940585c0..574fb29e82c7d 100644 --- a/src/test/run-pass/consts-in-patterns.rs +++ b/src/test/run-pass/consts-in-patterns.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(const_fn)] +#![feature(min_const_fn)] const FOO: isize = 10; const BAR: isize = 3; diff --git a/src/test/run-pass/ctfe/ice-48279.rs b/src/test/run-pass/ctfe/ice-48279.rs index c435e5fdaab4a..f59a6810e3a78 100644 --- a/src/test/run-pass/ctfe/ice-48279.rs +++ b/src/test/run-pass/ctfe/ice-48279.rs @@ -10,7 +10,7 @@ // https://github.com/rust-lang/rust/issues/48279 -#![feature(const_fn)] +#![feature(min_const_fn)] #[derive(PartialEq, Eq)] pub struct NonZeroU32 { diff --git a/src/test/run-pass/ctfe/match-const-fn-structs.rs b/src/test/run-pass/ctfe/match-const-fn-structs.rs index 0bb253d1a6455..352958f4c6a45 100644 --- a/src/test/run-pass/ctfe/match-const-fn-structs.rs +++ b/src/test/run-pass/ctfe/match-const-fn-structs.rs @@ -10,7 +10,7 @@ // https://github.com/rust-lang/rust/issues/46114 -#![feature(const_fn)] +#![feature(min_const_fn)] #[derive(Eq, PartialEq)] struct A { value: u32 } diff --git a/src/test/run-pass/ctfe/return-in-const-fn.rs b/src/test/run-pass/ctfe/return-in-const-fn.rs index d57d3bcb49aa8..87fdac4bfb4fe 100644 --- a/src/test/run-pass/ctfe/return-in-const-fn.rs +++ b/src/test/run-pass/ctfe/return-in-const-fn.rs @@ -10,7 +10,7 @@ // https://github.com/rust-lang/rust/issues/43754 -#![feature(const_fn)] +#![feature(min_const_fn)] const fn foo(x: usize) -> usize { return x; } diff --git a/src/test/run-pass/issue-28822.rs b/src/test/run-pass/issue-28822.rs index 5a010f2be7a34..10482139a978c 100644 --- a/src/test/run-pass/issue-28822.rs +++ b/src/test/run-pass/issue-28822.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(const_fn)] +#![feature(min_const_fn)] fn main() {} diff --git a/src/test/run-pass/issue-29927.rs b/src/test/run-pass/issue-29927.rs index 6d9adbcd57980..3079d9de3c238 100644 --- a/src/test/run-pass/issue-29927.rs +++ b/src/test/run-pass/issue-29927.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(const_fn)] +#![feature(min_const_fn)] struct A { field: usize, } diff --git a/src/test/run-pass/issue-33537.rs b/src/test/run-pass/issue-33537.rs index 24f4c9f590b11..7be79f3a45097 100644 --- a/src/test/run-pass/issue-33537.rs +++ b/src/test/run-pass/issue-33537.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(const_fn)] +#![feature(min_const_fn)] const fn foo() -> *const i8 { b"foo" as *const _ as *const i8 diff --git a/src/test/run-pass/issue-37991.rs b/src/test/run-pass/issue-37991.rs index 9bdde02d0061c..9b3289e67859a 100644 --- a/src/test/run-pass/issue-37991.rs +++ b/src/test/run-pass/issue-37991.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(const_fn)] +#![feature(min_const_fn)] const fn foo() -> i64 { 3 diff --git a/src/test/run-pass/issue29927-1.rs b/src/test/run-pass/issue29927-1.rs index 68271accb61a2..488bc6e6927a0 100644 --- a/src/test/run-pass/issue29927-1.rs +++ b/src/test/run-pass/issue29927-1.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(const_fn)] +#![feature(min_const_fn)] const fn f() -> usize { 5 } diff --git a/src/test/rustdoc/auxiliary/issue-27362.rs b/src/test/rustdoc/auxiliary/issue-27362.rs index 25de698cad10e..0c1eedc86ccfd 100644 --- a/src/test/rustdoc/auxiliary/issue-27362.rs +++ b/src/test/rustdoc/auxiliary/issue-27362.rs @@ -10,7 +10,7 @@ // compile-flags: -Cmetadata=aux -#![feature(const_fn)] +#![feature(min_const_fn)] pub const fn foo() {} pub const unsafe fn bar() {} diff --git a/src/test/rustdoc/const-fn.rs b/src/test/rustdoc/const-fn.rs index c323681f60b0a..dc7a2799b46a9 100644 --- a/src/test/rustdoc/const-fn.rs +++ b/src/test/rustdoc/const-fn.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(const_fn)] +#![feature(min_const_fn)] #![crate_name = "foo"] // @has foo/fn.bar.html diff --git a/src/test/rustdoc/const.rs b/src/test/rustdoc/const.rs index 380feb941d6fe..49694e3ae08d1 100644 --- a/src/test/rustdoc/const.rs +++ b/src/test/rustdoc/const.rs @@ -10,7 +10,7 @@ #![crate_type="lib"] -#![feature(const_fn)] +#![feature(min_const_fn)] pub struct Foo; diff --git a/src/test/ui/borrowck/move-in-static-initializer-issue-38520.rs b/src/test/ui/borrowck/move-in-static-initializer-issue-38520.rs index 508e09318ae11..d71c8462587d0 100644 --- a/src/test/ui/borrowck/move-in-static-initializer-issue-38520.rs +++ b/src/test/ui/borrowck/move-in-static-initializer-issue-38520.rs @@ -15,7 +15,7 @@ // permitted as `Foo` is not copy (even in a static/const // initializer). -#![feature(const_fn)] +#![feature(min_const_fn)] struct Foo(usize); diff --git a/src/test/ui/consts/auxiliary/const_fn_lib.rs b/src/test/ui/consts/auxiliary/const_fn_lib.rs index b0d5a6b12727b..499227e71a74c 100644 --- a/src/test/ui/consts/auxiliary/const_fn_lib.rs +++ b/src/test/ui/consts/auxiliary/const_fn_lib.rs @@ -11,6 +11,6 @@ // Crate that exports a const fn. Used for testing cross-crate. #![crate_type="rlib"] -#![feature(const_fn)] +#![feature(min_const_fn)] pub const fn foo() -> usize { 22 } //~ ERROR const fn is unstable diff --git a/src/test/ui/consts/const-eval/issue-43197.rs b/src/test/ui/consts/const-eval/issue-43197.rs index c0b45f0ba3041..200f423f6e39b 100644 --- a/src/test/ui/consts/const-eval/issue-43197.rs +++ b/src/test/ui/consts/const-eval/issue-43197.rs @@ -10,7 +10,7 @@ #![warn(const_err)] -#![feature(const_fn)] +#![feature(min_const_fn)] const fn foo(x: u32) -> u32 { x diff --git a/src/test/ui/consts/const-eval/issue-47971.rs b/src/test/ui/consts/const-eval/issue-47971.rs index f6a2db31d371a..2bc860e3ef94f 100644 --- a/src/test/ui/consts/const-eval/issue-47971.rs +++ b/src/test/ui/consts/const-eval/issue-47971.rs @@ -10,7 +10,7 @@ // compile-pass -#![feature(const_fn)] +#![feature(min_const_fn)] struct S(pub &'static u32, pub u32); diff --git a/src/test/ui/consts/const-pattern-not-const-evaluable.rs b/src/test/ui/consts/const-pattern-not-const-evaluable.rs index 87d5e13df6eb3..4f02b1eef3a0f 100644 --- a/src/test/ui/consts/const-pattern-not-const-evaluable.rs +++ b/src/test/ui/consts/const-pattern-not-const-evaluable.rs @@ -10,7 +10,7 @@ // compile-pass -#![feature(const_fn)] +#![feature(min_const_fn)] #[derive(PartialEq, Eq)] enum Cake { diff --git a/src/test/ui/consts/const-size_of-cycle.rs b/src/test/ui/consts/const-size_of-cycle.rs index fed8e1885de8a..04c054f8b6db2 100644 --- a/src/test/ui/consts/const-size_of-cycle.rs +++ b/src/test/ui/consts/const-size_of-cycle.rs @@ -10,8 +10,6 @@ // error-pattern: cycle detected -#![feature(const_fn)] - struct Foo { bytes: [u8; std::mem::size_of::()] } diff --git a/src/test/ui/infinite/infinite-recursion-const-fn.rs b/src/test/ui/infinite/infinite-recursion-const-fn.rs index 4f1f67214509e..63ae18cf9c2fa 100644 --- a/src/test/ui/infinite/infinite-recursion-const-fn.rs +++ b/src/test/ui/infinite/infinite-recursion-const-fn.rs @@ -10,7 +10,7 @@ //https://github.com/rust-lang/rust/issues/31364 -#![feature(const_fn)] +#![feature(min_const_fn)] const fn a() -> usize { b() } const fn b() -> usize { a() } const ARR: [i32; a()] = [5; 6]; //~ ERROR could not evaluate constant expression diff --git a/src/test/ui/issues/issue-44415.rs b/src/test/ui/issues/issue-44415.rs index 5d295510844ab..bd50f93945c51 100644 --- a/src/test/ui/issues/issue-44415.rs +++ b/src/test/ui/issues/issue-44415.rs @@ -10,7 +10,7 @@ //~^^^^^^^^^^ ERROR cycle detected when computing layout of -#![feature(const_fn)] + #![feature(core_intrinsics)] use std::intrinsics; diff --git a/src/test/ui/unsafe/unsafe-const-fn.rs b/src/test/ui/unsafe/unsafe-const-fn.rs index 765e2059a4b5e..fe0bb7533a86f 100644 --- a/src/test/ui/unsafe/unsafe-const-fn.rs +++ b/src/test/ui/unsafe/unsafe-const-fn.rs @@ -10,7 +10,7 @@ // A quick test of 'unsafe const fn' functionality -#![feature(const_fn)] +#![feature(min_const_fn)] const unsafe fn dummy(v: u32) -> u32 { !v From f3e1b968e3ac62cec168085ba0f9967fac9c4937 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Thu, 30 Aug 2018 10:39:41 +0200 Subject: [PATCH 19/36] Add test that min const fns can't call unstable min const fns even with the feature gate active --- .../min_const_fn/min_const_fn_libstd_stability.rs | 10 +++++++++- .../min_const_fn/min_const_fn_libstd_stability.stderr | 8 +++++++- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/src/test/ui/consts/min_const_fn/min_const_fn_libstd_stability.rs b/src/test/ui/consts/min_const_fn/min_const_fn_libstd_stability.rs index 4ce62ecc48533..9f5d0ad5df3e1 100644 --- a/src/test/ui/consts/min_const_fn/min_const_fn_libstd_stability.rs +++ b/src/test/ui/consts/min_const_fn/min_const_fn_libstd_stability.rs @@ -13,7 +13,7 @@ we're apparently really bad at it", issue = "0")] -#![feature(rustc_const_unstable, const_fn, foo)] +#![feature(rustc_const_unstable, const_fn, foo, foo2)] #![feature(staged_api)] #[stable(feature = "rust1", since = "1.0.0")] @@ -35,4 +35,12 @@ const fn bar2() -> u32 { foo2() } //~ ERROR can only call other `min_const_fn` // conformity is required, even with `const_fn` feature gate const fn bar3() -> u32 { (5f32 + 6f32) as u32 } //~ ERROR only int, `bool` and `char` operations +// check whether this function cannot be called even with the feature gate active +#[unstable(feature = "foo2", issue="0")] +const fn foo2_gated() -> u32 { 42 } + +#[stable(feature = "rust1", since = "1.0.0")] +// can't call non-min_const_fn +const fn bar2_gated() -> u32 { foo2_gated() } //~ ERROR can only call other `min_const_fn` + fn main() {} diff --git a/src/test/ui/consts/min_const_fn/min_const_fn_libstd_stability.stderr b/src/test/ui/consts/min_const_fn/min_const_fn_libstd_stability.stderr index 8e47090890db3..1ef7ffd3a916e 100644 --- a/src/test/ui/consts/min_const_fn/min_const_fn_libstd_stability.stderr +++ b/src/test/ui/consts/min_const_fn/min_const_fn_libstd_stability.stderr @@ -16,5 +16,11 @@ error: only int, `bool` and `char` operations are stable in const fn LL | const fn bar3() -> u32 { (5f32 + 6f32) as u32 } //~ ERROR only int, `bool` and `char` operations | ^^^^^^^^^^^^^ -error: aborting due to 3 previous errors +error: can only call other `min_const_fn` within a `min_const_fn` + --> $DIR/min_const_fn_libstd_stability.rs:44:32 + | +LL | const fn bar2_gated() -> u32 { foo2_gated() } //~ ERROR can only call other `min_const_fn` + | ^^^^^^^^^^^^ + +error: aborting due to 4 previous errors From b68bb636c7f238dbf94f1cbf301eafac0d308393 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Thu, 30 Aug 2018 10:45:05 +0200 Subject: [PATCH 20/36] Make `Condvar::new` and `RWLock::new` min const fn for cloudabi --- src/libstd/sys/cloudabi/condvar.rs | 8 +++++--- src/libstd/sys/cloudabi/rwlock.rs | 8 +++++--- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/src/libstd/sys/cloudabi/condvar.rs b/src/libstd/sys/cloudabi/condvar.rs index c05c837ade274..ccf848a9be420 100644 --- a/src/libstd/sys/cloudabi/condvar.rs +++ b/src/libstd/sys/cloudabi/condvar.rs @@ -28,11 +28,13 @@ pub struct Condvar { unsafe impl Send for Condvar {} unsafe impl Sync for Condvar {} +const NEW: Condvar = Condvar { + condvar: UnsafeCell::new(AtomicU32::new(abi::CONDVAR_HAS_NO_WAITERS.0)), +}; + impl Condvar { pub const fn new() -> Condvar { - Condvar { - condvar: UnsafeCell::new(AtomicU32::new(abi::CONDVAR_HAS_NO_WAITERS.0)), - } + NEW } pub unsafe fn init(&mut self) {} diff --git a/src/libstd/sys/cloudabi/rwlock.rs b/src/libstd/sys/cloudabi/rwlock.rs index 8539aec5e2c07..dc8624ec8a1b8 100644 --- a/src/libstd/sys/cloudabi/rwlock.rs +++ b/src/libstd/sys/cloudabi/rwlock.rs @@ -32,11 +32,13 @@ pub unsafe fn raw(r: &RWLock) -> *mut AtomicU32 { unsafe impl Send for RWLock {} unsafe impl Sync for RWLock {} +const NEW: RWLock = RWLock { + lock: UnsafeCell::new(AtomicU32::new(abi::LOCK_UNLOCKED.0)), +}; + impl RWLock { pub const fn new() -> RWLock { - RWLock { - lock: UnsafeCell::new(AtomicU32::new(abi::LOCK_UNLOCKED.0)), - } + NEW } pub unsafe fn try_read(&self) -> bool { From bf7e324e4e610b1f12971e601073ccfd6f197fff Mon Sep 17 00:00:00 2001 From: Otto Rask Date: Fri, 31 Aug 2018 11:21:01 +0300 Subject: [PATCH 21/36] Add clearer wording to Arc clone example code --- src/liballoc/sync.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/liballoc/sync.rs b/src/liballoc/sync.rs index 72a4740b15660..db7a4044b267f 100644 --- a/src/liballoc/sync.rs +++ b/src/liballoc/sync.rs @@ -108,7 +108,7 @@ const MAX_REFCOUNT: usize = (isize::MAX) as usize; /// // The two syntaxes below are equivalent. /// let a = foo.clone(); /// let b = Arc::clone(&foo); -/// // a and b both point to the same memory location as foo +/// // a, b, and foo are all Arcs that point to the same memory location /// ``` /// /// The [`Arc::clone(&from)`] syntax is the most idiomatic because it conveys more explicitly From 2839f4f0e8d58c295e146999961b78e2cc47354f Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Fri, 31 Aug 2018 11:47:45 +0200 Subject: [PATCH 22/36] Get rid of token passing --- .../transform/qualify_min_const_fn.rs | 90 ++++++++----------- 1 file changed, 35 insertions(+), 55 deletions(-) diff --git a/src/librustc_mir/transform/qualify_min_const_fn.rs b/src/librustc_mir/transform/qualify_min_const_fn.rs index 53ba4b03cb734..56e32ea5d1a23 100644 --- a/src/librustc_mir/transform/qualify_min_const_fn.rs +++ b/src/librustc_mir/transform/qualify_min_const_fn.rs @@ -5,17 +5,7 @@ use rustc::ty::{self, Predicate, TyCtxt}; use std::borrow::Cow; use syntax_pos::Span; -mod helper { - pub struct IsMinConstFn(()); - /// This should only ever be used *once* and then passed around as a token. - pub fn ensure_that_you_really_intended_to_create_an_instance_of_this() -> IsMinConstFn { - IsMinConstFn(()) - } -} - -use self::helper::*; - -type McfResult = Result)>; +type McfResult = Result<(), (Span, Cow<'static, str>)>; pub fn is_min_const_fn( tcx: TyCtxt<'a, 'tcx, 'tcx>, @@ -74,8 +64,6 @@ pub fn is_min_const_fn( } } - let mut token = ensure_that_you_really_intended_to_create_an_instance_of_this(); - for local in mir.vars_iter() { return Err(( mir.local_decls[local].source_info.span, @@ -83,30 +71,28 @@ pub fn is_min_const_fn( )); } for local in &mir.local_decls { - token = check_ty(tcx, local.ty, local.source_info.span, token)?; + check_ty(tcx, local.ty, local.source_info.span)?; } // impl trait is gone in MIR, so check the return type manually - token = check_ty( + check_ty( tcx, tcx.fn_sig(def_id).output().skip_binder(), mir.local_decls.iter().next().unwrap().source_info.span, - token, )?; for bb in mir.basic_blocks() { - token = check_terminator(tcx, mir, bb.terminator(), token)?; + check_terminator(tcx, mir, bb.terminator())?; for stmt in &bb.statements { - token = check_statement(tcx, mir, stmt, token)?; + check_statement(tcx, mir, stmt)?; } } - Ok(token) + Ok(()) } fn check_ty( tcx: TyCtxt<'a, 'tcx, 'tcx>, ty: ty::Ty<'tcx>, span: Span, - token: IsMinConstFn, ) -> McfResult { for ty in ty.walk() { match ty.sty { @@ -146,7 +132,7 @@ fn check_ty( _ => {} } } - Ok(token) + Ok(()) } fn check_rvalue( @@ -154,14 +140,13 @@ fn check_rvalue( mir: &'a Mir<'tcx>, rvalue: &Rvalue<'tcx>, span: Span, - token: IsMinConstFn, ) -> McfResult { match rvalue { Rvalue::Repeat(operand, _) | Rvalue::Use(operand) => { - check_operand(tcx, mir, operand, span, token) + check_operand(tcx, mir, operand, span) } Rvalue::Len(place) | Rvalue::Discriminant(place) | Rvalue::Ref(_, _, place) => { - check_place(tcx, mir, place, span, token, PlaceMode::Read) + check_place(tcx, mir, place, span, PlaceMode::Read) } Rvalue::Cast(_, operand, cast_ty) => { use rustc::ty::cast::CastTy; @@ -175,16 +160,16 @@ fn check_rvalue( (CastTy::RPtr(_), CastTy::Float) => bug!(), (CastTy::RPtr(_), CastTy::Int(_)) => bug!(), (CastTy::Ptr(_), CastTy::RPtr(_)) => bug!(), - _ => check_operand(tcx, mir, operand, span, token), + _ => check_operand(tcx, mir, operand, span), } } // binops are fine on integers Rvalue::BinaryOp(_, lhs, rhs) | Rvalue::CheckedBinaryOp(_, lhs, rhs) => { - let token = check_operand(tcx, mir, lhs, span, token)?; - let token = check_operand(tcx, mir, rhs, span, token)?; + check_operand(tcx, mir, lhs, span)?; + check_operand(tcx, mir, rhs, span)?; let ty = lhs.ty(mir, tcx); if ty.is_integral() || ty.is_bool() || ty.is_char() { - Ok(token) + Ok(()) } else { Err(( span, @@ -193,11 +178,11 @@ fn check_rvalue( } } // checked by regular const fn checks - Rvalue::NullaryOp(..) => Ok(token), + Rvalue::NullaryOp(..) => Ok(()), Rvalue::UnaryOp(_, operand) => { let ty = operand.ty(mir, tcx); if ty.is_integral() || ty.is_bool() { - check_operand(tcx, mir, operand, span, token) + check_operand(tcx, mir, operand, span) } else { Err(( span, @@ -206,11 +191,10 @@ fn check_rvalue( } } Rvalue::Aggregate(_, operands) => { - let mut token = token; for operand in operands { - token = check_operand(tcx, mir, operand, span, token)?; + check_operand(tcx, mir, operand, span)?; } - Ok(token) + Ok(()) } } } @@ -224,19 +208,18 @@ fn check_statement( tcx: TyCtxt<'a, 'tcx, 'tcx>, mir: &'a Mir<'tcx>, statement: &Statement<'tcx>, - token: IsMinConstFn, ) -> McfResult { let span = statement.source_info.span; match &statement.kind { StatementKind::Assign(place, rval) => { - let token = check_place(tcx, mir, place, span, token, PlaceMode::Assign)?; - check_rvalue(tcx, mir, rval, span, token) + check_place(tcx, mir, place, span, PlaceMode::Assign)?; + check_rvalue(tcx, mir, rval, span) } StatementKind::ReadForMatch(_) => Err((span, "match in const fn is unstable".into())), // just an assignment - StatementKind::SetDiscriminant { .. } => Ok(token), + StatementKind::SetDiscriminant { .. } => Ok(()), | StatementKind::InlineAsm { .. } => { Err((span, "cannot use inline assembly in const fn".into())) @@ -248,7 +231,7 @@ fn check_statement( | StatementKind::Validate(..) | StatementKind::EndRegion(_) | StatementKind::UserAssertTy(..) - | StatementKind::Nop => Ok(token), + | StatementKind::Nop => Ok(()), } } @@ -257,13 +240,12 @@ fn check_operand( mir: &'a Mir<'tcx>, operand: &Operand<'tcx>, span: Span, - token: IsMinConstFn, ) -> McfResult { match operand { Operand::Move(place) | Operand::Copy(place) => { - check_place(tcx, mir, place, span, token, PlaceMode::Read) + check_place(tcx, mir, place, span, PlaceMode::Read) } - Operand::Constant(_) => Ok(token), + Operand::Constant(_) => Ok(()), } } @@ -272,26 +254,25 @@ fn check_place( mir: &'a Mir<'tcx>, place: &Place<'tcx>, span: Span, - token: IsMinConstFn, mode: PlaceMode, ) -> McfResult { match place { Place::Local(l) => match mode { PlaceMode::Assign => match mir.local_kind(*l) { - LocalKind::Temp | LocalKind::ReturnPointer => Ok(token), + LocalKind::Temp | LocalKind::ReturnPointer => Ok(()), LocalKind::Arg | LocalKind::Var => { Err((span, "assignments in const fn are unstable".into())) } }, - PlaceMode::Read => Ok(token), + PlaceMode::Read => Ok(()), }, // promoteds are always fine, they are essentially constants - Place::Promoted(_) => Ok(token), + Place::Promoted(_) => Ok(()), Place::Static(_) => Err((span, "cannot access `static` items in const fn".into())), Place::Projection(proj) => { match proj.elem { | ProjectionElem::Deref | ProjectionElem::Field(..) | ProjectionElem::Index(_) => { - check_place(tcx, mir, &proj.base, span, token, mode) + check_place(tcx, mir, &proj.base, span, mode) } // slice patterns are unstable | ProjectionElem::ConstantIndex { .. } | ProjectionElem::Subslice { .. } => { @@ -309,20 +290,19 @@ fn check_terminator( tcx: TyCtxt<'a, 'tcx, 'tcx>, mir: &'a Mir<'tcx>, terminator: &Terminator<'tcx>, - token: IsMinConstFn, ) -> McfResult { let span = terminator.source_info.span; match &terminator.kind { | TerminatorKind::Goto { .. } | TerminatorKind::Return - | TerminatorKind::Resume => Ok(token), + | TerminatorKind::Resume => Ok(()), TerminatorKind::Drop { location, .. } => { - check_place(tcx, mir, location, span, token, PlaceMode::Read) + check_place(tcx, mir, location, span, PlaceMode::Read) } TerminatorKind::DropAndReplace { location, value, .. } => { - let token = check_place(tcx, mir, location, span, token, PlaceMode::Read)?; - check_operand(tcx, mir, value, span, token) + check_place(tcx, mir, location, span, PlaceMode::Read)?; + check_operand(tcx, mir, value, span) }, TerminatorKind::SwitchInt { .. } => Err(( span, @@ -344,12 +324,12 @@ fn check_terminator( let fn_ty = func.ty(mir, tcx); if let ty::FnDef(def_id, _) = fn_ty.sty { if tcx.is_min_const_fn(def_id) { - let mut token = check_operand(tcx, mir, func, span, token)?; + check_operand(tcx, mir, func, span)?; for arg in args { - token = check_operand(tcx, mir, arg, span, token)?; + check_operand(tcx, mir, arg, span)?; } - Ok(token) + Ok(()) } else { Err(( span, @@ -367,7 +347,7 @@ fn check_terminator( msg: _, target: _, cleanup: _, - } => check_operand(tcx, mir, cond, span, token), + } => check_operand(tcx, mir, cond, span), | TerminatorKind::FalseEdges { .. } | TerminatorKind::FalseUnwind { .. } => span_bug!( terminator.source_info.span, From 66d7216469faa5f22d0fe1deb9573e84d22142c5 Mon Sep 17 00:00:00 2001 From: csmoe <35686186+csmoe@users.noreply.github.com> Date: Fri, 31 Aug 2018 18:30:38 +0800 Subject: [PATCH 23/36] trip const_to_alloc query --- src/librustc/dep_graph/dep_node.rs | 3 +-- src/librustc/ty/query/config.rs | 6 ------ src/librustc/ty/query/mod.rs | 13 +------------ src/librustc/ty/query/plumbing.rs | 1 - src/librustc_mir/lib.rs | 1 - 5 files changed, 2 insertions(+), 22 deletions(-) diff --git a/src/librustc/dep_graph/dep_node.rs b/src/librustc/dep_graph/dep_node.rs index 90081d5b85ef9..dfe0a395ca140 100644 --- a/src/librustc/dep_graph/dep_node.rs +++ b/src/librustc/dep_graph/dep_node.rs @@ -75,7 +75,7 @@ use traits::query::{ CanonicalPredicateGoal, CanonicalTypeOpProvePredicateGoal, CanonicalTypeOpNormalizeGoal, }; use ty::{TyCtxt, FnSig, Instance, InstanceDef, - ParamEnv, ParamEnvAnd, Predicate, PolyFnSig, PolyTraitRef, Ty, self}; + ParamEnv, ParamEnvAnd, Predicate, PolyFnSig, PolyTraitRef, Ty}; use ty::subst::Substs; // erase!() just makes tokens go away. It's used to specify which macro argument @@ -632,7 +632,6 @@ define_dep_nodes!( <'tcx> // queries). Making them anonymous avoids hashing the result, which // may save a bit of time. [anon] EraseRegionsTy { ty: Ty<'tcx> }, - [anon] ConstToAllocation { val: &'tcx ty::Const<'tcx> }, [input] Freevars(DefId), [input] MaybeUnusedTraitImport(DefId), diff --git a/src/librustc/ty/query/config.rs b/src/librustc/ty/query/config.rs index b5093d0a1fc95..d32580181f8dc 100644 --- a/src/librustc/ty/query/config.rs +++ b/src/librustc/ty/query/config.rs @@ -198,12 +198,6 @@ impl<'tcx> QueryDescription<'tcx> for queries::super_predicates_of<'tcx> { } } -impl<'tcx> QueryDescription<'tcx> for queries::const_to_allocation<'tcx> { - fn describe(_tcx: TyCtxt, val: &'tcx ty::Const<'tcx>) -> String { - format!("converting constant `{:?}` to an allocation", val) - } -} - impl<'tcx> QueryDescription<'tcx> for queries::erase_regions_ty<'tcx> { fn describe(_tcx: TyCtxt, ty: Ty<'tcx>) -> String { format!("erasing regions from `{:?}`", ty) diff --git a/src/librustc/ty/query/mod.rs b/src/librustc/ty/query/mod.rs index 6f61583e49b8e..88f599971c7da 100644 --- a/src/librustc/ty/query/mod.rs +++ b/src/librustc/ty/query/mod.rs @@ -30,7 +30,7 @@ use middle::exported_symbols::{SymbolExportLevel, ExportedSymbol}; use mir::interpret::ConstEvalResult; use mir::mono::{CodegenUnit, Stats}; use mir; -use mir::interpret::{GlobalId, Allocation}; +use mir::interpret::GlobalId; use session::{CompileResult, CrateDisambiguator}; use session::config::OutputFilenames; use traits::{self, Vtable}; @@ -286,11 +286,6 @@ define_queries! { <'tcx> /// other items (such as enum variant explicit discriminants). [] fn const_eval: const_eval_dep_node(ty::ParamEnvAnd<'tcx, GlobalId<'tcx>>) -> ConstEvalResult<'tcx>, - - /// Converts a constant value to a constant allocation - [] fn const_to_allocation: const_to_allocation( - &'tcx ty::Const<'tcx> - ) -> &'tcx Allocation, }, TypeChecking { @@ -706,12 +701,6 @@ fn erase_regions_ty<'tcx>(ty: Ty<'tcx>) -> DepConstructor<'tcx> { DepConstructor::EraseRegionsTy { ty } } -fn const_to_allocation<'tcx>( - val: &'tcx ty::Const<'tcx>, -) -> DepConstructor<'tcx> { - DepConstructor::ConstToAllocation { val } -} - fn type_param_predicates<'tcx>((item_id, param_id): (DefId, DefId)) -> DepConstructor<'tcx> { DepConstructor::TypeParamPredicates { item_id, diff --git a/src/librustc/ty/query/plumbing.rs b/src/librustc/ty/query/plumbing.rs index 0edb1aa79e745..215fba54499b7 100644 --- a/src/librustc/ty/query/plumbing.rs +++ b/src/librustc/ty/query/plumbing.rs @@ -1062,7 +1062,6 @@ pub fn force_from_dep_node<'a, 'gcx, 'lcx>(tcx: TyCtxt<'a, 'gcx, 'lcx>, DepKind::FulfillObligation | DepKind::VtableMethods | DepKind::EraseRegionsTy | - DepKind::ConstToAllocation | DepKind::NormalizeProjectionTy | DepKind::NormalizeTyAfterErasingRegions | DepKind::ImpliedOutlivesBounds | diff --git a/src/librustc_mir/lib.rs b/src/librustc_mir/lib.rs index f91ff3642cd10..d5148b09c4ff5 100644 --- a/src/librustc_mir/lib.rs +++ b/src/librustc_mir/lib.rs @@ -93,7 +93,6 @@ pub fn provide(providers: &mut Providers) { shim::provide(providers); transform::provide(providers); providers.const_eval = interpret::const_eval_provider; - providers.const_to_allocation = interpret::const_to_allocation_provider; providers.check_match = hair::pattern::check_match; } From 72ba683457f3bb2b62754dec78ddd0c633982c65 Mon Sep 17 00:00:00 2001 From: csmoe <35686186+csmoe@users.noreply.github.com> Date: Fri, 31 Aug 2018 18:31:15 +0800 Subject: [PATCH 24/36] extract allocation info from byref --- src/librustc_mir/interpret/memory.rs | 11 +++++++---- src/librustc_typeck/check/mod.rs | 8 ++++++-- 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/src/librustc_mir/interpret/memory.rs b/src/librustc_mir/interpret/memory.rs index 91fc6453446a8..79e635a03b2ed 100644 --- a/src/librustc_mir/interpret/memory.rs +++ b/src/librustc_mir/interpret/memory.rs @@ -22,7 +22,7 @@ use std::ptr; use rustc::ty::{self, Instance, query::TyCtxtAt}; use rustc::ty::layout::{self, Align, TargetDataLayout, Size, HasDataLayout}; -use rustc::mir::interpret::{Pointer, AllocId, Allocation, ScalarMaybeUndef, GlobalId, +use rustc::mir::interpret::{Pointer, AllocId, Allocation, ConstValue, ScalarMaybeUndef, GlobalId, EvalResult, Scalar, EvalErrorKind, AllocType, PointerArithmetic, truncate}; pub use rustc::mir::interpret::{write_target_uint, read_target_uint}; @@ -340,9 +340,12 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> { // no need to report anything, the const_eval call takes care of that for statics assert!(tcx.is_static(def_id).is_some()); EvalErrorKind::ReferencedConstant(err).into() - }).map(|val| { - // FIXME We got our static (will be a ByRef), now we make a *copy*?!? - tcx.const_to_allocation(val) + }).map(|const_val| { + if let ConstValue::ByRef(_, allocation, _) = const_val.val { + allocation + } else { + panic!("Trying to get allocation info from non-byref const value") + } }) } diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index bbb45c04e4e98..2129cdf6f466b 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -94,7 +94,7 @@ use rustc::infer::{self, InferCtxt, InferOk, RegionVariableOrigin}; use rustc::infer::anon_types::AnonTypeDecl; use rustc::infer::type_variable::{TypeVariableOrigin}; use rustc::middle::region; -use rustc::mir::interpret::{GlobalId}; +use rustc::mir::interpret::{ConstValue, GlobalId}; use rustc::ty::subst::{CanonicalSubsts, UnpackedKind, Subst, Substs}; use rustc::traits::{self, ObligationCause, ObligationCauseCode, TraitEngine}; use rustc::ty::{self, Ty, TyCtxt, GenericParamDefKind, Visibility, ToPredicate, RegionKind}; @@ -1375,7 +1375,11 @@ fn maybe_check_static_with_link_section(tcx: TyCtxt, id: DefId, span: Span) { }; let param_env = ty::ParamEnv::reveal_all(); if let Ok(static_) = tcx.const_eval(param_env.and(cid)) { - let alloc = tcx.const_to_allocation(static_); + let alloc = if let ConstValue::ByRef(_, allocation, _) = static_.val { + allocation + } else { + panic!("Trying to get allocation info from non-byref const value") + }; if alloc.relocations.len() != 0 { let msg = "statics with a custom `#[link_section]` must be a \ simple list of bytes on the wasm target with no \ From c56adf64136aba153cac4600986787e8646c0811 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Thu, 23 Aug 2018 02:19:38 +0300 Subject: [PATCH 25/36] cleanup: Add main functions to some UI tests --- src/test/ui/enum/enum-discrim-autosizing.rs | 1 + src/test/ui/enum/enum-discrim-autosizing.stderr | 9 ++------- src/test/ui/gated-bad-feature.rs | 2 ++ src/test/ui/gated-bad-feature.stderr | 8 ++------ src/test/ui/hygiene/generate-mod.rs | 2 ++ src/test/ui/hygiene/generate-mod.stderr | 9 ++------- src/test/ui/hygiene/no_implicit_prelude.rs | 2 ++ src/test/ui/hygiene/no_implicit_prelude.stderr | 8 ++------ src/test/ui/imports/import-glob-circular.rs | 2 ++ src/test/ui/imports/import-glob-circular.stderr | 9 ++------- src/test/ui/imports/import-loop-2.rs | 2 ++ src/test/ui/imports/import-loop-2.stderr | 14 ++------------ src/test/ui/invalid_crate_type_syntax.rs | 2 ++ src/test/ui/invalid_crate_type_syntax.stderr | 7 +------ src/test/ui/issues/issue-38715.rs | 2 ++ src/test/ui/issues/issue-38715.stderr | 7 +------ src/test/ui/issues/issue-42755.rs | 2 ++ src/test/ui/issues/issue-42755.stderr | 7 +------ src/test/ui/issues/issue-43784-associated-type.rs | 2 ++ .../ui/issues/issue-43784-associated-type.stderr | 9 ++------- src/test/ui/issues/issue-43784-supertrait.rs | 2 ++ src/test/ui/issues/issue-43784-supertrait.stderr | 9 ++------- src/test/ui/macros/macro-use-bad-args-1.rs | 2 ++ src/test/ui/macros/macro-use-bad-args-1.stderr | 9 ++------- src/test/ui/macros/macro-use-bad-args-2.rs | 2 ++ src/test/ui/macros/macro-use-bad-args-2.stderr | 9 ++------- src/test/ui/nested-ty-params.rs | 2 ++ src/test/ui/nested-ty-params.stderr | 9 ++------- src/test/ui/repr/repr-transparent-other-items.rs | 2 ++ .../ui/repr/repr-transparent-other-items.stderr | 8 ++------ src/test/ui/repr/repr-transparent-other-reprs.rs | 2 ++ .../ui/repr/repr-transparent-other-reprs.stderr | 9 ++------- src/test/ui/repr/repr-transparent.rs | 2 ++ src/test/ui/repr/repr-transparent.stderr | 10 +++------- src/test/ui/resolve/resolve-unknown-trait.rs | 2 ++ src/test/ui/resolve/resolve-unknown-trait.stderr | 9 ++------- src/test/ui/resolve_self_super_hint.rs | 2 ++ src/test/ui/resolve_self_super_hint.stderr | 9 ++------- .../ui/specialization/defaultimpl/validation.rs | 2 ++ .../specialization/defaultimpl/validation.stderr | 9 ++------- src/test/ui/tuple/tuple-struct-fields/test.rs | 2 ++ src/test/ui/tuple/tuple-struct-fields/test.stderr | 9 ++------- src/test/ui/unresolved/unresolved-import.rs | 2 ++ src/test/ui/unresolved/unresolved-import.stderr | 9 ++------- src/test/ui/user-defined-macro-rules.rs | 2 ++ src/test/ui/user-defined-macro-rules.stderr | 7 +------ src/test/ui/wasm-custom-section-relocations.rs | 2 ++ src/test/ui/wasm-custom-section-relocations.stderr | 7 +------ 48 files changed, 91 insertions(+), 165 deletions(-) diff --git a/src/test/ui/enum/enum-discrim-autosizing.rs b/src/test/ui/enum/enum-discrim-autosizing.rs index 3a243330ad9b0..dab22de1b6e58 100644 --- a/src/test/ui/enum/enum-discrim-autosizing.rs +++ b/src/test/ui/enum/enum-discrim-autosizing.rs @@ -18,3 +18,4 @@ enum Eu64 { Bu64 = 0x8000_0000_0000_0000 //~ERROR already exists } +fn main() {} diff --git a/src/test/ui/enum/enum-discrim-autosizing.stderr b/src/test/ui/enum/enum-discrim-autosizing.stderr index 3b4ac436898e6..e4419d6285127 100644 --- a/src/test/ui/enum/enum-discrim-autosizing.stderr +++ b/src/test/ui/enum/enum-discrim-autosizing.stderr @@ -1,7 +1,3 @@ -error[E0601]: `main` function not found in crate `enum_discrim_autosizing` - | - = note: consider adding a `main` function to `$DIR/enum-discrim-autosizing.rs` - error[E0081]: discriminant value `0` already exists --> $DIR/enum-discrim-autosizing.rs:18:12 | @@ -10,7 +6,6 @@ LL | Au64 = 0, LL | Bu64 = 0x8000_0000_0000_0000 //~ERROR already exists | ^^^^^^^^^^^^^^^^^^^^^ enum already has `0` -error: aborting due to 2 previous errors +error: aborting due to previous error -Some errors occurred: E0081, E0601. -For more information about an error, try `rustc --explain E0081`. +For more information about this error, try `rustc --explain E0081`. diff --git a/src/test/ui/gated-bad-feature.rs b/src/test/ui/gated-bad-feature.rs index 5baafd4153159..0d74f9011c3ec 100644 --- a/src/test/ui/gated-bad-feature.rs +++ b/src/test/ui/gated-bad-feature.rs @@ -20,3 +20,5 @@ #![feature = "foo"] //~ ERROR: malformed feature #![feature(test_removed_feature)] //~ ERROR: feature has been removed + +fn main() {} diff --git a/src/test/ui/gated-bad-feature.stderr b/src/test/ui/gated-bad-feature.stderr index 2bed241d68cab..68be49a7277d2 100644 --- a/src/test/ui/gated-bad-feature.stderr +++ b/src/test/ui/gated-bad-feature.stderr @@ -28,11 +28,7 @@ error[E0557]: feature has been removed LL | #![feature(test_removed_feature)] //~ ERROR: feature has been removed | ^^^^^^^^^^^^^^^^^^^^ -error[E0601]: `main` function not found in crate `gated_bad_feature` - | - = note: consider adding a `main` function to `$DIR/gated-bad-feature.rs` - -error: aborting due to 6 previous errors +error: aborting due to 5 previous errors -Some errors occurred: E0555, E0556, E0557, E0601. +Some errors occurred: E0555, E0556, E0557. For more information about an error, try `rustc --explain E0555`. diff --git a/src/test/ui/hygiene/generate-mod.rs b/src/test/ui/hygiene/generate-mod.rs index 2b2108558a0f3..efb3696cf8513 100644 --- a/src/test/ui/hygiene/generate-mod.rs +++ b/src/test/ui/hygiene/generate-mod.rs @@ -55,3 +55,5 @@ fn check_legacy() { struct FromOutside; genmod_legacy!(); } + +fn main() {} diff --git a/src/test/ui/hygiene/generate-mod.stderr b/src/test/ui/hygiene/generate-mod.stderr index 0c5905c5acb4f..f86444bae77e8 100644 --- a/src/test/ui/hygiene/generate-mod.stderr +++ b/src/test/ui/hygiene/generate-mod.stderr @@ -46,11 +46,6 @@ LL | type Inner = Outer; //~ ERROR cannot find type `Outer` in this scop LL | genmod_legacy!(); | ----------------- in this macro invocation -error[E0601]: `main` function not found in crate `generate_mod` - | - = note: consider adding a `main` function to `$DIR/generate-mod.rs` - -error: aborting due to 7 previous errors +error: aborting due to 6 previous errors -Some errors occurred: E0412, E0601. -For more information about an error, try `rustc --explain E0412`. +For more information about this error, try `rustc --explain E0412`. diff --git a/src/test/ui/hygiene/no_implicit_prelude.rs b/src/test/ui/hygiene/no_implicit_prelude.rs index c90c7b3093c9f..bf07bc05491cc 100644 --- a/src/test/ui/hygiene/no_implicit_prelude.rs +++ b/src/test/ui/hygiene/no_implicit_prelude.rs @@ -23,3 +23,5 @@ mod bar { } fn f() { ::foo::m!(); } } + +fn main() {} diff --git a/src/test/ui/hygiene/no_implicit_prelude.stderr b/src/test/ui/hygiene/no_implicit_prelude.stderr index b3d82e9094ba7..463fdbf00ce54 100644 --- a/src/test/ui/hygiene/no_implicit_prelude.stderr +++ b/src/test/ui/hygiene/no_implicit_prelude.stderr @@ -7,10 +7,6 @@ LL | fn f() { ::bar::m!(); } LL | Vec::new(); //~ ERROR failed to resolve | ^^^ Use of undeclared type or module `Vec` -error[E0601]: `main` function not found in crate `no_implicit_prelude` - | - = note: consider adding a `main` function to `$DIR/no_implicit_prelude.rs` - error[E0599]: no method named `clone` found for type `()` in the current scope --> $DIR/no_implicit_prelude.rs:22:12 | @@ -24,7 +20,7 @@ LL | ().clone() //~ ERROR no method named `clone` found = note: the following trait is implemented but not in scope, perhaps add a `use` for it: `use std::clone::Clone;` -error: aborting due to 3 previous errors +error: aborting due to 2 previous errors -Some errors occurred: E0433, E0599, E0601. +Some errors occurred: E0433, E0599. For more information about an error, try `rustc --explain E0433`. diff --git a/src/test/ui/imports/import-glob-circular.rs b/src/test/ui/imports/import-glob-circular.rs index d9cc17791ed56..b2e92fe0e1bf9 100644 --- a/src/test/ui/imports/import-glob-circular.rs +++ b/src/test/ui/imports/import-glob-circular.rs @@ -25,3 +25,5 @@ mod test { fn test() { f1066(); } //~ ERROR cannot find function `f1066` in this scope } + +fn main() {} diff --git a/src/test/ui/imports/import-glob-circular.stderr b/src/test/ui/imports/import-glob-circular.stderr index 078a6a3937a47..fdff04cc24148 100644 --- a/src/test/ui/imports/import-glob-circular.stderr +++ b/src/test/ui/imports/import-glob-circular.stderr @@ -4,11 +4,6 @@ error[E0425]: cannot find function `f1066` in this scope LL | fn test() { f1066(); } //~ ERROR cannot find function `f1066` in this scope | ^^^^^ not found in this scope -error[E0601]: `main` function not found in crate `import_glob_circular` - | - = note: consider adding a `main` function to `$DIR/import-glob-circular.rs` - -error: aborting due to 2 previous errors +error: aborting due to previous error -Some errors occurred: E0425, E0601. -For more information about an error, try `rustc --explain E0425`. +For more information about this error, try `rustc --explain E0425`. diff --git a/src/test/ui/imports/import-loop-2.rs b/src/test/ui/imports/import-loop-2.rs index b7bbe11a4dc96..0bc968872db5b 100644 --- a/src/test/ui/imports/import-loop-2.rs +++ b/src/test/ui/imports/import-loop-2.rs @@ -19,3 +19,5 @@ mod b { fn main() { let y = x; } } + +fn main() {} diff --git a/src/test/ui/imports/import-loop-2.stderr b/src/test/ui/imports/import-loop-2.stderr index 717f74643ebb4..09c2e7918f376 100644 --- a/src/test/ui/imports/import-loop-2.stderr +++ b/src/test/ui/imports/import-loop-2.stderr @@ -4,16 +4,6 @@ error[E0432]: unresolved import `a::x` LL | pub use a::x; | ^^^^ no `x` in `a` -error[E0601]: `main` function not found in crate `import_loop_2` - | - = note: the main function must be defined at the crate level but you have one or more functions named 'main' that are not defined at the crate level. Either move the definition or attach the `#[main]` attribute to override this behavior. -note: here is a function named 'main' - --> $DIR/import-loop-2.rs:20:5 - | -LL | fn main() { let y = x; } - | ^^^^^^^^^^^^^^^^^^^^^^^^ - -error: aborting due to 2 previous errors +error: aborting due to previous error -Some errors occurred: E0432, E0601. -For more information about an error, try `rustc --explain E0432`. +For more information about this error, try `rustc --explain E0432`. diff --git a/src/test/ui/invalid_crate_type_syntax.rs b/src/test/ui/invalid_crate_type_syntax.rs index 6d42515704ea1..904a9acf9e530 100644 --- a/src/test/ui/invalid_crate_type_syntax.rs +++ b/src/test/ui/invalid_crate_type_syntax.rs @@ -12,3 +12,5 @@ #![crate_type(lib)] //~ ERROR `crate_type` requires a value fn my_lib_fn() {} + +fn main() {} diff --git a/src/test/ui/invalid_crate_type_syntax.stderr b/src/test/ui/invalid_crate_type_syntax.stderr index b609695b86ee5..6f02f96faca93 100644 --- a/src/test/ui/invalid_crate_type_syntax.stderr +++ b/src/test/ui/invalid_crate_type_syntax.stderr @@ -6,10 +6,5 @@ LL | #![crate_type(lib)] //~ ERROR `crate_type` requires a value | = note: for example: `#![crate_type="lib"]` -error[E0601]: `main` function not found in crate `invalid_crate_type_syntax` - | - = note: consider adding a `main` function to `$DIR/invalid_crate_type_syntax.rs` - -error: aborting due to 2 previous errors +error: aborting due to previous error -For more information about this error, try `rustc --explain E0601`. diff --git a/src/test/ui/issues/issue-38715.rs b/src/test/ui/issues/issue-38715.rs index 552653c21bad6..5c745d1fab3b5 100644 --- a/src/test/ui/issues/issue-38715.rs +++ b/src/test/ui/issues/issue-38715.rs @@ -14,3 +14,5 @@ macro_rules! foo { ($i:ident) => {} } #[macro_export] macro_rules! foo { () => {} } //~ ERROR a macro named `foo` has already been exported //~| WARN this was previously accepted + +fn main() {} diff --git a/src/test/ui/issues/issue-38715.stderr b/src/test/ui/issues/issue-38715.stderr index a0dbcbd18c673..67b27cc83cc89 100644 --- a/src/test/ui/issues/issue-38715.stderr +++ b/src/test/ui/issues/issue-38715.stderr @@ -13,10 +13,5 @@ note: previous macro export is now shadowed LL | macro_rules! foo { ($i:ident) => {} } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error[E0601]: `main` function not found in crate `issue_38715` - | - = note: consider adding a `main` function to `$DIR/issue-38715.rs` - -error: aborting due to 2 previous errors +error: aborting due to previous error -For more information about this error, try `rustc --explain E0601`. diff --git a/src/test/ui/issues/issue-42755.rs b/src/test/ui/issues/issue-42755.rs index dd53a1c71a5bc..46c8cb740ded7 100644 --- a/src/test/ui/issues/issue-42755.rs +++ b/src/test/ui/issues/issue-42755.rs @@ -15,3 +15,5 @@ macro_rules! foo { } foo!(a); + +fn main() {} diff --git a/src/test/ui/issues/issue-42755.stderr b/src/test/ui/issues/issue-42755.stderr index 9143906199616..fa736edc47f5b 100644 --- a/src/test/ui/issues/issue-42755.stderr +++ b/src/test/ui/issues/issue-42755.stderr @@ -4,10 +4,5 @@ error: repetition matches empty token tree LL | ($($p:vis)*) => {} //~ ERROR repetition matches empty token tree | ^^^^^^^^ -error[E0601]: `main` function not found in crate `issue_42755` - | - = note: consider adding a `main` function to `$DIR/issue-42755.rs` - -error: aborting due to 2 previous errors +error: aborting due to previous error -For more information about this error, try `rustc --explain E0601`. diff --git a/src/test/ui/issues/issue-43784-associated-type.rs b/src/test/ui/issues/issue-43784-associated-type.rs index 94b5c0034a76d..1ff1238ec54b8 100644 --- a/src/test/ui/issues/issue-43784-associated-type.rs +++ b/src/test/ui/issues/issue-43784-associated-type.rs @@ -23,3 +23,5 @@ impl Partial for T::Assoc where impl Complete for T { //~ ERROR the trait bound `T: std::marker::Copy` is not satisfied type Assoc = T; } + +fn main() {} diff --git a/src/test/ui/issues/issue-43784-associated-type.stderr b/src/test/ui/issues/issue-43784-associated-type.stderr index 798d8c6601668..18e97e24b733a 100644 --- a/src/test/ui/issues/issue-43784-associated-type.stderr +++ b/src/test/ui/issues/issue-43784-associated-type.stderr @@ -1,7 +1,3 @@ -error[E0601]: `main` function not found in crate `issue_43784_associated_type` - | - = note: consider adding a `main` function to `$DIR/issue-43784-associated-type.rs` - error[E0277]: the trait bound `T: std::marker::Copy` is not satisfied --> $DIR/issue-43784-associated-type.rs:23:9 | @@ -10,7 +6,6 @@ LL | impl Complete for T { //~ ERROR the trait bound `T: std::marker::Copy` i | = help: consider adding a `where T: std::marker::Copy` bound -error: aborting due to 2 previous errors +error: aborting due to previous error -Some errors occurred: E0277, E0601. -For more information about an error, try `rustc --explain E0277`. +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/issues/issue-43784-supertrait.rs b/src/test/ui/issues/issue-43784-supertrait.rs index e70df113da33c..30132c3be88a7 100644 --- a/src/test/ui/issues/issue-43784-supertrait.rs +++ b/src/test/ui/issues/issue-43784-supertrait.rs @@ -16,3 +16,5 @@ pub trait Complete: Partial { impl Partial for T where T: Complete {} impl Complete for T {} //~ ERROR the trait bound `T: std::marker::Copy` is not satisfied + +fn main() {} diff --git a/src/test/ui/issues/issue-43784-supertrait.stderr b/src/test/ui/issues/issue-43784-supertrait.stderr index 8646b315abdab..422075f62aa0d 100644 --- a/src/test/ui/issues/issue-43784-supertrait.stderr +++ b/src/test/ui/issues/issue-43784-supertrait.stderr @@ -1,7 +1,3 @@ -error[E0601]: `main` function not found in crate `issue_43784_supertrait` - | - = note: consider adding a `main` function to `$DIR/issue-43784-supertrait.rs` - error[E0277]: the trait bound `T: std::marker::Copy` is not satisfied --> $DIR/issue-43784-supertrait.rs:18:9 | @@ -10,7 +6,6 @@ LL | impl Complete for T {} //~ ERROR the trait bound `T: std::marker::Copy` | = help: consider adding a `where T: std::marker::Copy` bound -error: aborting due to 2 previous errors +error: aborting due to previous error -Some errors occurred: E0277, E0601. -For more information about an error, try `rustc --explain E0277`. +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/macros/macro-use-bad-args-1.rs b/src/test/ui/macros/macro-use-bad-args-1.rs index a07cc83441173..fefc6ff6ca615 100644 --- a/src/test/ui/macros/macro-use-bad-args-1.rs +++ b/src/test/ui/macros/macro-use-bad-args-1.rs @@ -13,3 +13,5 @@ #[allow(unused_extern_crates)] #[macro_use(foo(bar))] //~ ERROR bad macro import extern crate std; + +fn main() {} diff --git a/src/test/ui/macros/macro-use-bad-args-1.stderr b/src/test/ui/macros/macro-use-bad-args-1.stderr index 19a8c7c0382d1..308fb6c76e1b9 100644 --- a/src/test/ui/macros/macro-use-bad-args-1.stderr +++ b/src/test/ui/macros/macro-use-bad-args-1.stderr @@ -4,11 +4,6 @@ error[E0466]: bad macro import LL | #[macro_use(foo(bar))] //~ ERROR bad macro import | ^^^^^^^^ -error[E0601]: `main` function not found in crate `macro_use_bad_args_1` - | - = note: consider adding a `main` function to `$DIR/macro-use-bad-args-1.rs` - -error: aborting due to 2 previous errors +error: aborting due to previous error -Some errors occurred: E0466, E0601. -For more information about an error, try `rustc --explain E0466`. +For more information about this error, try `rustc --explain E0466`. diff --git a/src/test/ui/macros/macro-use-bad-args-2.rs b/src/test/ui/macros/macro-use-bad-args-2.rs index 89004f1689774..81352cf2e427d 100644 --- a/src/test/ui/macros/macro-use-bad-args-2.rs +++ b/src/test/ui/macros/macro-use-bad-args-2.rs @@ -13,3 +13,5 @@ #[allow(unused_extern_crates)] #[macro_use(foo="bar")] //~ ERROR bad macro import extern crate std; + +fn main() {} diff --git a/src/test/ui/macros/macro-use-bad-args-2.stderr b/src/test/ui/macros/macro-use-bad-args-2.stderr index 0ac18201d791e..62e3c22fab3ec 100644 --- a/src/test/ui/macros/macro-use-bad-args-2.stderr +++ b/src/test/ui/macros/macro-use-bad-args-2.stderr @@ -4,11 +4,6 @@ error[E0466]: bad macro import LL | #[macro_use(foo="bar")] //~ ERROR bad macro import | ^^^^^^^^^ -error[E0601]: `main` function not found in crate `macro_use_bad_args_2` - | - = note: consider adding a `main` function to `$DIR/macro-use-bad-args-2.rs` - -error: aborting due to 2 previous errors +error: aborting due to previous error -Some errors occurred: E0466, E0601. -For more information about an error, try `rustc --explain E0466`. +For more information about this error, try `rustc --explain E0466`. diff --git a/src/test/ui/nested-ty-params.rs b/src/test/ui/nested-ty-params.rs index aac37289bb749..2378cccf56f76 100644 --- a/src/test/ui/nested-ty-params.rs +++ b/src/test/ui/nested-ty-params.rs @@ -14,3 +14,5 @@ fn hd(v: Vec ) -> U { return hd1(v); } + +fn main() {} diff --git a/src/test/ui/nested-ty-params.stderr b/src/test/ui/nested-ty-params.stderr index 93b934f610f8c..58b6cd18989f2 100644 --- a/src/test/ui/nested-ty-params.stderr +++ b/src/test/ui/nested-ty-params.stderr @@ -18,11 +18,6 @@ LL | fn hd1(w: [U]) -> U { return w[0]; } | | | help: try using a local type parameter instead: `hd1` -error[E0601]: `main` function not found in crate `nested_ty_params` - | - = note: consider adding a `main` function to `$DIR/nested-ty-params.rs` - -error: aborting due to 3 previous errors +error: aborting due to 2 previous errors -Some errors occurred: E0401, E0601. -For more information about an error, try `rustc --explain E0401`. +For more information about this error, try `rustc --explain E0401`. diff --git a/src/test/ui/repr/repr-transparent-other-items.rs b/src/test/ui/repr/repr-transparent-other-items.rs index 685d62dc3a9c8..be6f3cf9eb205 100644 --- a/src/test/ui/repr/repr-transparent-other-items.rs +++ b/src/test/ui/repr/repr-transparent-other-items.rs @@ -36,3 +36,5 @@ fn cant_repr_this() {} #[repr(transparent)] //~ ERROR should be applied to struct static CANT_REPR_THIS: u32 = 0; + +fn main() {} diff --git a/src/test/ui/repr/repr-transparent-other-items.stderr b/src/test/ui/repr/repr-transparent-other-items.stderr index e5889cf53e58a..5a1978991480e 100644 --- a/src/test/ui/repr/repr-transparent-other-items.stderr +++ b/src/test/ui/repr/repr-transparent-other-items.stderr @@ -1,7 +1,3 @@ -error[E0601]: `main` function not found in crate `repr_transparent_other_items` - | - = note: consider adding a `main` function to `$DIR/repr-transparent-other-items.rs` - error[E0517]: attribute should be applied to struct --> $DIR/repr-transparent-other-items.rs:13:8 | @@ -67,7 +63,7 @@ LL | #[repr(transparent)] //~ ERROR unsupported representation for zero-variant LL | enum Void {} //~| ERROR should be applied to struct | ------------ zero-variant enum -error: aborting due to 8 previous errors +error: aborting due to 7 previous errors -Some errors occurred: E0084, E0517, E0601. +Some errors occurred: E0084, E0517. For more information about an error, try `rustc --explain E0084`. diff --git a/src/test/ui/repr/repr-transparent-other-reprs.rs b/src/test/ui/repr/repr-transparent-other-reprs.rs index fa5f1a2f7fb80..aed8a69f66ef8 100644 --- a/src/test/ui/repr/repr-transparent-other-reprs.rs +++ b/src/test/ui/repr/repr-transparent-other-reprs.rs @@ -26,3 +26,5 @@ struct TransparentPlusAlign(u8); #[repr(transparent)] //~ ERROR cannot have other repr #[repr(C)] struct SeparateAttributes(*mut u8); + +fn main() {} diff --git a/src/test/ui/repr/repr-transparent-other-reprs.stderr b/src/test/ui/repr/repr-transparent-other-reprs.stderr index 40f41c474dbda..c8f5dea3c1242 100644 --- a/src/test/ui/repr/repr-transparent-other-reprs.stderr +++ b/src/test/ui/repr/repr-transparent-other-reprs.stderr @@ -1,7 +1,3 @@ -error[E0601]: `main` function not found in crate `repr_transparent_other_reprs` - | - = note: consider adding a `main` function to `$DIR/repr-transparent-other-reprs.rs` - error[E0692]: transparent struct cannot have other repr hints --> $DIR/repr-transparent-other-reprs.rs:15:8 | @@ -28,7 +24,6 @@ LL | #[repr(transparent)] //~ ERROR cannot have other repr LL | #[repr(C)] | ^ -error: aborting due to 5 previous errors +error: aborting due to 4 previous errors -Some errors occurred: E0601, E0692. -For more information about an error, try `rustc --explain E0601`. +For more information about this error, try `rustc --explain E0692`. diff --git a/src/test/ui/repr/repr-transparent.rs b/src/test/ui/repr/repr-transparent.rs index 230573247316e..f5b99af156ee0 100644 --- a/src/test/ui/repr/repr-transparent.rs +++ b/src/test/ui/repr/repr-transparent.rs @@ -48,3 +48,5 @@ struct ZstAlign32(PhantomData); #[repr(transparent)] struct GenericAlign(ZstAlign32, u32); //~ ERROR alignment larger than 1 + +fn main() {} diff --git a/src/test/ui/repr/repr-transparent.stderr b/src/test/ui/repr/repr-transparent.stderr index 0f620880fa9d3..f7bfdbdc625bb 100644 --- a/src/test/ui/repr/repr-transparent.stderr +++ b/src/test/ui/repr/repr-transparent.stderr @@ -1,7 +1,3 @@ -error[E0601]: `main` function not found in crate `repr_transparent` - | - = note: consider adding a `main` function to `$DIR/repr-transparent.rs` - error[E0690]: transparent struct needs exactly one non-zero-sized field, but has 0 --> $DIR/repr-transparent.rs:21:1 | @@ -70,7 +66,7 @@ error[E0691]: zero-sized field in transparent struct has alignment larger than 1 LL | struct GenericAlign(ZstAlign32, u32); //~ ERROR alignment larger than 1 | ^^^^^^^^^^^^^ -error: aborting due to 9 previous errors +error: aborting due to 8 previous errors -Some errors occurred: E0601, E0690, E0691. -For more information about an error, try `rustc --explain E0601`. +Some errors occurred: E0690, E0691. +For more information about an error, try `rustc --explain E0690`. diff --git a/src/test/ui/resolve/resolve-unknown-trait.rs b/src/test/ui/resolve/resolve-unknown-trait.rs index 9432e727fa5b7..05bf4b928b725 100644 --- a/src/test/ui/resolve/resolve-unknown-trait.rs +++ b/src/test/ui/resolve/resolve-unknown-trait.rs @@ -17,3 +17,5 @@ impl SomeNonExistentTrait for isize {} fn f() {} //~^ ERROR cannot find trait `SomeNonExistentTrait` in this scope + +fn main() {} diff --git a/src/test/ui/resolve/resolve-unknown-trait.stderr b/src/test/ui/resolve/resolve-unknown-trait.stderr index 8a2d791654d2f..74b190f86845f 100644 --- a/src/test/ui/resolve/resolve-unknown-trait.stderr +++ b/src/test/ui/resolve/resolve-unknown-trait.stderr @@ -16,11 +16,6 @@ error[E0405]: cannot find trait `SomeNonExistentTrait` in this scope LL | fn f() {} | ^^^^^^^^^^^^^^^^^^^^ not found in this scope -error[E0601]: `main` function not found in crate `resolve_unknown_trait` - | - = note: consider adding a `main` function to `$DIR/resolve-unknown-trait.rs` - -error: aborting due to 4 previous errors +error: aborting due to 3 previous errors -Some errors occurred: E0405, E0601. -For more information about an error, try `rustc --explain E0405`. +For more information about this error, try `rustc --explain E0405`. diff --git a/src/test/ui/resolve_self_super_hint.rs b/src/test/ui/resolve_self_super_hint.rs index a89fd802baf0c..c5dd367c0ab88 100644 --- a/src/test/ui/resolve_self_super_hint.rs +++ b/src/test/ui/resolve_self_super_hint.rs @@ -32,3 +32,5 @@ mod a { } } } + +fn main() {} diff --git a/src/test/ui/resolve_self_super_hint.stderr b/src/test/ui/resolve_self_super_hint.stderr index 8538da06baf64..40b2a4bf96842 100644 --- a/src/test/ui/resolve_self_super_hint.stderr +++ b/src/test/ui/resolve_self_super_hint.stderr @@ -22,11 +22,6 @@ error[E0432]: unresolved import `alloc` LL | use alloc::HashMap; | ^^^^^ Did you mean `a::alloc`? -error[E0601]: `main` function not found in crate `resolve_self_super_hint` - | - = note: consider adding a `main` function to `$DIR/resolve_self_super_hint.rs` - -error: aborting due to 5 previous errors +error: aborting due to 4 previous errors -Some errors occurred: E0432, E0601. -For more information about an error, try `rustc --explain E0432`. +For more information about this error, try `rustc --explain E0432`. diff --git a/src/test/ui/specialization/defaultimpl/validation.rs b/src/test/ui/specialization/defaultimpl/validation.rs index 26b8b737f340d..068eb7a448556 100644 --- a/src/test/ui/specialization/defaultimpl/validation.rs +++ b/src/test/ui/specialization/defaultimpl/validation.rs @@ -21,3 +21,5 @@ default impl !Send for Z {} //~ ERROR impls of auto traits cannot be default trait Tr {} default impl !Tr for S {} //~ ERROR negative impls are only allowed for auto traits + +fn main() {} diff --git a/src/test/ui/specialization/defaultimpl/validation.stderr b/src/test/ui/specialization/defaultimpl/validation.stderr index 54b92da7b2192..c25c428eb4e94 100644 --- a/src/test/ui/specialization/defaultimpl/validation.stderr +++ b/src/test/ui/specialization/defaultimpl/validation.stderr @@ -6,10 +6,6 @@ LL | default impl S {} //~ ERROR inherent impls cannot be default | = note: only trait implementations may be annotated with default -error[E0601]: `main` function not found in crate `validation` - | - = note: consider adding a `main` function to `$DIR/validation.rs` - error: impls of auto traits cannot be default --> $DIR/validation.rs:19:1 | @@ -28,7 +24,6 @@ error[E0192]: negative impls are only allowed for auto traits (e.g., `Send` and LL | default impl !Tr for S {} //~ ERROR negative impls are only allowed for auto traits | ^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 5 previous errors +error: aborting due to 4 previous errors -Some errors occurred: E0192, E0601. -For more information about an error, try `rustc --explain E0192`. +For more information about this error, try `rustc --explain E0192`. diff --git a/src/test/ui/tuple/tuple-struct-fields/test.rs b/src/test/ui/tuple/tuple-struct-fields/test.rs index 22d54a3834073..c8b77bfabdb95 100644 --- a/src/test/ui/tuple/tuple-struct-fields/test.rs +++ b/src/test/ui/tuple/tuple-struct-fields/test.rs @@ -15,3 +15,5 @@ mod foo { //~^ ERROR expected one of `)` or `,`, found `(` //~| ERROR cannot find type `foo` in this scope } + +fn main() {} diff --git a/src/test/ui/tuple/tuple-struct-fields/test.stderr b/src/test/ui/tuple/tuple-struct-fields/test.stderr index 59228ea8c14d2..f83e9dd5458fb 100644 --- a/src/test/ui/tuple/tuple-struct-fields/test.stderr +++ b/src/test/ui/tuple/tuple-struct-fields/test.stderr @@ -10,11 +10,6 @@ error[E0412]: cannot find type `foo` in this scope LL | struct S2(pub((foo)) ()); | ^^^ not found in this scope -error[E0601]: `main` function not found in crate `test` - | - = note: consider adding a `main` function to `$DIR/test.rs` - -error: aborting due to 3 previous errors +error: aborting due to 2 previous errors -Some errors occurred: E0412, E0601. -For more information about an error, try `rustc --explain E0412`. +For more information about this error, try `rustc --explain E0412`. diff --git a/src/test/ui/unresolved/unresolved-import.rs b/src/test/ui/unresolved/unresolved-import.rs index a3eeb6de96bda..efa7494647691 100644 --- a/src/test/ui/unresolved/unresolved-import.rs +++ b/src/test/ui/unresolved/unresolved-import.rs @@ -55,3 +55,5 @@ mod items { fn item() {} } + +fn main() {} diff --git a/src/test/ui/unresolved/unresolved-import.stderr b/src/test/ui/unresolved/unresolved-import.stderr index 1e663cde48a65..9bcebb0011a75 100644 --- a/src/test/ui/unresolved/unresolved-import.stderr +++ b/src/test/ui/unresolved/unresolved-import.stderr @@ -34,11 +34,6 @@ error[E0432]: unresolved import `Enum` LL | use Enum::*; //~ ERROR unresolved import `Enum` [E0432] | ^^^^ Did you mean `self::Enum`? -error[E0601]: `main` function not found in crate `unresolved_import` - | - = note: consider adding a `main` function to `$DIR/unresolved-import.rs` - -error: aborting due to 7 previous errors +error: aborting due to 6 previous errors -Some errors occurred: E0432, E0601. -For more information about an error, try `rustc --explain E0432`. +For more information about this error, try `rustc --explain E0432`. diff --git a/src/test/ui/user-defined-macro-rules.rs b/src/test/ui/user-defined-macro-rules.rs index 02e1a585fa89d..fe76d58f1ef76 100644 --- a/src/test/ui/user-defined-macro-rules.rs +++ b/src/test/ui/user-defined-macro-rules.rs @@ -11,3 +11,5 @@ #![allow(unused_macros)] macro_rules! macro_rules { () => {} } //~ ERROR user-defined macros may not be named `macro_rules` + +fn main() {} diff --git a/src/test/ui/user-defined-macro-rules.stderr b/src/test/ui/user-defined-macro-rules.stderr index 3359aa4bcd720..1f8b18166c9c9 100644 --- a/src/test/ui/user-defined-macro-rules.stderr +++ b/src/test/ui/user-defined-macro-rules.stderr @@ -4,10 +4,5 @@ error: user-defined macros may not be named `macro_rules` LL | macro_rules! macro_rules { () => {} } //~ ERROR user-defined macros may not be named `macro_rules` | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error[E0601]: `main` function not found in crate `user_defined_macro_rules` - | - = note: consider adding a `main` function to `$DIR/user-defined-macro-rules.rs` - -error: aborting due to 2 previous errors +error: aborting due to previous error -For more information about this error, try `rustc --explain E0601`. diff --git a/src/test/ui/wasm-custom-section-relocations.rs b/src/test/ui/wasm-custom-section-relocations.rs index 5631a70192afd..9f431e7806139 100644 --- a/src/test/ui/wasm-custom-section-relocations.rs +++ b/src/test/ui/wasm-custom-section-relocations.rs @@ -21,3 +21,5 @@ pub static C: usize = 3; #[link_section = "test"] pub static D: &usize = &C; //~ ERROR: no extra levels of indirection + +fn main() {} diff --git a/src/test/ui/wasm-custom-section-relocations.stderr b/src/test/ui/wasm-custom-section-relocations.stderr index 9b96b99e02ae4..cea6e5c41923a 100644 --- a/src/test/ui/wasm-custom-section-relocations.stderr +++ b/src/test/ui/wasm-custom-section-relocations.stderr @@ -1,7 +1,3 @@ -error[E0601]: `main` function not found in crate `wasm_custom_section_relocations` - | - = note: consider adding a `main` function to `$DIR/wasm-custom-section-relocations.rs` - error: statics with a custom `#[link_section]` must be a simple list of bytes on the wasm target with no extra levels of indirection such as references --> $DIR/wasm-custom-section-relocations.rs:14:1 | @@ -14,6 +10,5 @@ error: statics with a custom `#[link_section]` must be a simple list of bytes on LL | pub static D: &usize = &C; //~ ERROR: no extra levels of indirection | ^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 3 previous errors +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0601`. From 1a3bb2795b3c06e56d0c172b59178c72a171f1fc Mon Sep 17 00:00:00 2001 From: QuietMisdreavus Date: Sat, 4 Aug 2018 18:12:38 -0500 Subject: [PATCH 26/36] feature(doc_cfg): set cfg(rustdoc) when rustdoc is running --- src/librustdoc/lib.rs | 6 ++++-- src/libsyntax/feature_gate.rs | 1 + src/test/ui/feature-gate-doc_cfg-cfg-rustdoc.rs | 14 ++++++++++++++ .../ui/feature-gate-doc_cfg-cfg-rustdoc.stderr | 11 +++++++++++ 4 files changed, 30 insertions(+), 2 deletions(-) create mode 100644 src/test/ui/feature-gate-doc_cfg-cfg-rustdoc.rs create mode 100644 src/test/ui/feature-gate-doc_cfg-cfg-rustdoc.stderr diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index 279151eb26def..feae724b55d09 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -466,7 +466,8 @@ fn main_args(args: &[String]) -> isize { let output = matches.opt_str("o").map(|s| PathBuf::from(&s)); let css_file_extension = matches.opt_str("e").map(|s| PathBuf::from(&s)); - let cfgs = matches.opt_strs("cfg"); + let mut cfgs = matches.opt_strs("cfg"); + cfgs.push("rustdoc".to_string()); if let Some(ref p) = css_file_extension { if !p.is_file() { @@ -643,7 +644,8 @@ where R: 'static + Send, for s in &matches.opt_strs("L") { paths.add_path(s, ErrorOutputType::default()); } - let cfgs = matches.opt_strs("cfg"); + let mut cfgs = matches.opt_strs("cfg"); + cfgs.push("rustdoc".to_string()); let triple = matches.opt_str("target").map(|target| { if target.ends_with(".json") { TargetTriple::TargetPath(PathBuf::from(target)) diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index 6dd788bf6e2ac..7f051ac3ebcc0 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -1148,6 +1148,7 @@ const GATED_CFGS: &[(&str, &str, fn(&Features) -> bool)] = &[ ("target_vendor", "cfg_target_vendor", cfg_fn!(cfg_target_vendor)), ("target_thread_local", "cfg_target_thread_local", cfg_fn!(cfg_target_thread_local)), ("target_has_atomic", "cfg_target_has_atomic", cfg_fn!(cfg_target_has_atomic)), + ("rustdoc", "doc_cfg", cfg_fn!(doc_cfg)), ]; #[derive(Debug)] diff --git a/src/test/ui/feature-gate-doc_cfg-cfg-rustdoc.rs b/src/test/ui/feature-gate-doc_cfg-cfg-rustdoc.rs new file mode 100644 index 0000000000000..6207d99dc36aa --- /dev/null +++ b/src/test/ui/feature-gate-doc_cfg-cfg-rustdoc.rs @@ -0,0 +1,14 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#[cfg(rustdoc)] //~ ERROR: `cfg(rustdoc)` is experimental and subject to change +pub struct SomeStruct; + +fn main() {} diff --git a/src/test/ui/feature-gate-doc_cfg-cfg-rustdoc.stderr b/src/test/ui/feature-gate-doc_cfg-cfg-rustdoc.stderr new file mode 100644 index 0000000000000..be2c263af042d --- /dev/null +++ b/src/test/ui/feature-gate-doc_cfg-cfg-rustdoc.stderr @@ -0,0 +1,11 @@ +error[E0658]: `cfg(rustdoc)` is experimental and subject to change (see issue #43781) + --> $DIR/feature-gate-doc_cfg-cfg-rustdoc.rs:11:7 + | +LL | #[cfg(rustdoc)] //~ ERROR: `cfg(rustdoc)` is experimental and subject to change + | ^^^^^^^ + | + = help: add #![feature(doc_cfg)] to the crate attributes to enable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0658`. From d7e496f4424cc0fef686abdc738a8421825c9c50 Mon Sep 17 00:00:00 2001 From: QuietMisdreavus Date: Sat, 4 Aug 2018 18:28:36 -0500 Subject: [PATCH 27/36] feature(doc_cfg): add docs for cfg(rustdoc) --- src/doc/rustdoc/src/unstable-features.md | 20 +++++++++---------- .../src/language-features/doc-cfg.md | 8 ++++++-- 2 files changed, 15 insertions(+), 13 deletions(-) diff --git a/src/doc/rustdoc/src/unstable-features.md b/src/doc/rustdoc/src/unstable-features.md index a91c2cd71cde3..876a773b30ab0 100644 --- a/src/doc/rustdoc/src/unstable-features.md +++ b/src/doc/rustdoc/src/unstable-features.md @@ -106,27 +106,25 @@ The `#[doc(cfg(...))]` attribute has another effect: When Rustdoc renders docume item, it will be accompanied by a banner explaining that the item is only available on certain platforms. -As mentioned earlier, getting the items to Rustdoc requires some extra preparation. The standard -library adds a `--cfg dox` flag to every Rustdoc command, but the same thing can be accomplished by -adding a feature to your Cargo.toml and adding `--feature dox` (or whatever you choose to name the -feature) to your `cargo doc` calls. +For Rustdoc to document an item, it needs to see it, regardless of what platform it's currently +running on. To aid this, Rustdoc sets the flag `#[cfg(rustdoc)]` when running on your crate. +Combining this with the target platform of a given item allows it to appear when building your crate +normally on that platform, as well as when building documentation anywhere. -Either way, once you create an environment for the documentation, you can start to augment your -`#[cfg]` attributes to allow both the target platform *and* the documentation configuration to leave -the item in. For example, `#[cfg(any(windows, feature = "dox"))]` will preserve the item either on -Windows or during the documentation process. Then, adding a new attribute `#[doc(cfg(windows))]` -will tell Rustdoc that the item is supposed to be used on Windows. For example: +For example, `#[cfg(any(windows, rustdoc))]` will preserve the item either on Windows or during the +documentation process. Then, adding a new attribute `#[doc(cfg(windows))]` will tell Rustdoc that +the item is supposed to be used on Windows. For example: ```rust #![feature(doc_cfg)] /// Token struct that can only be used on Windows. -#[cfg(any(windows, feature = "dox"))] +#[cfg(any(windows, rustdoc))] #[doc(cfg(windows))] pub struct WindowsToken; /// Token struct that can only be used on Unix. -#[cfg(any(unix, feature = "dox"))] +#[cfg(any(unix, rustdoc))] #[doc(cfg(unix))] pub struct UnixToken; ``` diff --git a/src/doc/unstable-book/src/language-features/doc-cfg.md b/src/doc/unstable-book/src/language-features/doc-cfg.md index ddc538e12144a..96c66a1515ed5 100644 --- a/src/doc/unstable-book/src/language-features/doc-cfg.md +++ b/src/doc/unstable-book/src/language-features/doc-cfg.md @@ -12,13 +12,17 @@ This attribute has two effects: 2. The item's doc-tests will only run on the specific platform. +In addition to allowing the use of the `#[doc(cfg)]` attribute, this feature enables the use of a +special conditional compilation flag, `#[cfg(rustdoc)]`, set whenever building documentation on your +crate. + This feature was introduced as part of PR [#43348] to allow the platform-specific parts of the standard library be documented. ```rust #![feature(doc_cfg)] -#[cfg(any(windows, feature = "documentation"))] +#[cfg(any(windows, rustdoc))] #[doc(cfg(windows))] /// The application's icon in the notification area (a.k.a. system tray). /// @@ -39,4 +43,4 @@ pub struct Icon { ``` [#43781]: https://github.com/rust-lang/rust/issues/43781 -[#43348]: https://github.com/rust-lang/rust/issues/43348 \ No newline at end of file +[#43348]: https://github.com/rust-lang/rust/issues/43348 From ad2169c095b190afd76a5e32865410502a8bcfdd Mon Sep 17 00:00:00 2001 From: QuietMisdreavus Date: Sat, 4 Aug 2018 18:29:47 -0500 Subject: [PATCH 28/36] use cfg(rustdoc) instead of cfg(dox) in std and friends --- src/bootstrap/bin/rustdoc.rs | 2 ++ src/libcore/macros.rs | 2 +- src/libstd/macros.rs | 2 +- src/libstd/os/mod.rs | 2 +- src/libstd/sys/mod.rs | 4 ++-- src/libstd/sys/unix/mod.rs | 32 ++++++++++++++++---------------- src/libstd/sys/windows/c.rs | 2 +- 7 files changed, 24 insertions(+), 22 deletions(-) diff --git a/src/bootstrap/bin/rustdoc.rs b/src/bootstrap/bin/rustdoc.rs index a54e58665cceb..bb5a21e3e405f 100644 --- a/src/bootstrap/bin/rustdoc.rs +++ b/src/bootstrap/bin/rustdoc.rs @@ -37,6 +37,8 @@ fn main() { let mut dylib_path = bootstrap::util::dylib_path(); dylib_path.insert(0, PathBuf::from(libdir.clone())); + //FIXME(misdreavus): once stdsimd uses cfg(rustdoc) instead of cfg(dox), remove the `--cfg dox` + //arguments here let mut cmd = Command::new(rustdoc); cmd.args(&args) .arg("--cfg") diff --git a/src/libcore/macros.rs b/src/libcore/macros.rs index 5b3b2d1635688..0032bedc7ed1d 100644 --- a/src/libcore/macros.rs +++ b/src/libcore/macros.rs @@ -541,7 +541,7 @@ macro_rules! unimplemented { /// into libsyntax itself. /// /// For more information, see documentation for `std`'s macros. -#[cfg(dox)] +#[cfg(rustdoc)] mod builtin { /// Unconditionally causes compilation to fail with the given error message when encountered. diff --git a/src/libstd/macros.rs b/src/libstd/macros.rs index 6945a41a5e73b..b649ec2340e93 100644 --- a/src/libstd/macros.rs +++ b/src/libstd/macros.rs @@ -309,7 +309,7 @@ macro_rules! assert_approx_eq { /// These macros do not have any corresponding definition with a `macro_rules!` /// macro, but are documented here. Their implementations can be found hardcoded /// into libsyntax itself. -#[cfg(dox)] +#[cfg(rustdoc)] mod builtin { /// Unconditionally causes compilation to fail with the given error message when encountered. diff --git a/src/libstd/os/mod.rs b/src/libstd/os/mod.rs index c384ec9168ac4..6bc186e796666 100644 --- a/src/libstd/os/mod.rs +++ b/src/libstd/os/mod.rs @@ -14,7 +14,7 @@ #![allow(missing_docs, bad_style, missing_debug_implementations)] cfg_if! { - if #[cfg(dox)] { + if #[cfg(rustdoc)] { // When documenting libstd we want to show unix/windows/linux modules as // these are the "main modules" that are used across platforms. This diff --git a/src/libstd/sys/mod.rs b/src/libstd/sys/mod.rs index c44db3b107224..61e4ce66eec0f 100644 --- a/src/libstd/sys/mod.rs +++ b/src/libstd/sys/mod.rs @@ -57,7 +57,7 @@ cfg_if! { // then later used in the `std::os` module when documenting, for example, // Windows when we're compiling for Linux. -#[cfg(dox)] +#[cfg(rustdoc)] cfg_if! { if #[cfg(any(unix, target_os = "redox"))] { // On unix we'll document what's already available @@ -77,7 +77,7 @@ cfg_if! { } } -#[cfg(dox)] +#[cfg(rustdoc)] cfg_if! { if #[cfg(windows)] { // On windows we'll just be documenting what's already available diff --git a/src/libstd/sys/unix/mod.rs b/src/libstd/sys/unix/mod.rs index c738003caf1d9..a631ef5ec5cbd 100644 --- a/src/libstd/sys/unix/mod.rs +++ b/src/libstd/sys/unix/mod.rs @@ -13,22 +13,22 @@ use io::{self, ErrorKind}; use libc; -#[cfg(any(dox, target_os = "linux"))] pub use os::linux as platform; - -#[cfg(all(not(dox), target_os = "android"))] pub use os::android as platform; -#[cfg(all(not(dox), target_os = "bitrig"))] pub use os::bitrig as platform; -#[cfg(all(not(dox), target_os = "dragonfly"))] pub use os::dragonfly as platform; -#[cfg(all(not(dox), target_os = "freebsd"))] pub use os::freebsd as platform; -#[cfg(all(not(dox), target_os = "haiku"))] pub use os::haiku as platform; -#[cfg(all(not(dox), target_os = "ios"))] pub use os::ios as platform; -#[cfg(all(not(dox), target_os = "macos"))] pub use os::macos as platform; -#[cfg(all(not(dox), target_os = "netbsd"))] pub use os::netbsd as platform; -#[cfg(all(not(dox), target_os = "openbsd"))] pub use os::openbsd as platform; -#[cfg(all(not(dox), target_os = "solaris"))] pub use os::solaris as platform; -#[cfg(all(not(dox), target_os = "emscripten"))] pub use os::emscripten as platform; -#[cfg(all(not(dox), target_os = "fuchsia"))] pub use os::fuchsia as platform; -#[cfg(all(not(dox), target_os = "l4re"))] pub use os::linux as platform; -#[cfg(all(not(dox), target_os = "hermit"))] pub use os::hermit as platform; +#[cfg(any(rustdoc, target_os = "linux"))] pub use os::linux as platform; + +#[cfg(all(not(rustdoc), target_os = "android"))] pub use os::android as platform; +#[cfg(all(not(rustdoc), target_os = "bitrig"))] pub use os::bitrig as platform; +#[cfg(all(not(rustdoc), target_os = "dragonfly"))] pub use os::dragonfly as platform; +#[cfg(all(not(rustdoc), target_os = "freebsd"))] pub use os::freebsd as platform; +#[cfg(all(not(rustdoc), target_os = "haiku"))] pub use os::haiku as platform; +#[cfg(all(not(rustdoc), target_os = "ios"))] pub use os::ios as platform; +#[cfg(all(not(rustdoc), target_os = "macos"))] pub use os::macos as platform; +#[cfg(all(not(rustdoc), target_os = "netbsd"))] pub use os::netbsd as platform; +#[cfg(all(not(rustdoc), target_os = "openbsd"))] pub use os::openbsd as platform; +#[cfg(all(not(rustdoc), target_os = "solaris"))] pub use os::solaris as platform; +#[cfg(all(not(rustdoc), target_os = "emscripten"))] pub use os::emscripten as platform; +#[cfg(all(not(rustdoc), target_os = "fuchsia"))] pub use os::fuchsia as platform; +#[cfg(all(not(rustdoc), target_os = "l4re"))] pub use os::linux as platform; +#[cfg(all(not(rustdoc), target_os = "hermit"))] pub use os::hermit as platform; pub use self::rand::hashmap_random_keys; pub use libc::strlen; diff --git a/src/libstd/sys/windows/c.rs b/src/libstd/sys/windows/c.rs index e514a56dcc436..10f48c3c308a7 100644 --- a/src/libstd/sys/windows/c.rs +++ b/src/libstd/sys/windows/c.rs @@ -794,7 +794,7 @@ pub struct FLOATING_SAVE_AREA { // will not appear in the final documentation. This should be also defined for // other architectures supported by Windows such as ARM, and for historical // interest, maybe MIPS and PowerPC as well. -#[cfg(all(dox, not(any(target_arch = "x86_64", target_arch = "x86", target_arch = "aarch64"))))] +#[cfg(all(rustdoc, not(any(target_arch = "x86_64", target_arch = "x86", target_arch = "aarch64"))))] pub enum CONTEXT {} #[cfg(target_arch = "aarch64")] From a18a2900f3c4be97d661c2ab5ae5812106ed2833 Mon Sep 17 00:00:00 2001 From: csmoe <35686186+csmoe@users.noreply.github.com> Date: Sat, 1 Sep 2018 09:49:24 +0800 Subject: [PATCH 29/36] improve panic message --- src/librustc_mir/interpret/memory.rs | 2 +- src/librustc_typeck/check/mod.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/librustc_mir/interpret/memory.rs b/src/librustc_mir/interpret/memory.rs index 79e635a03b2ed..d2edfdec90658 100644 --- a/src/librustc_mir/interpret/memory.rs +++ b/src/librustc_mir/interpret/memory.rs @@ -344,7 +344,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> { if let ConstValue::ByRef(_, allocation, _) = const_val.val { allocation } else { - panic!("Trying to get allocation info from non-byref const value") + panic!("Matching on non-ByRef static") } }) } diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 2129cdf6f466b..b0e8f1c8ca3f5 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -1378,7 +1378,7 @@ fn maybe_check_static_with_link_section(tcx: TyCtxt, id: DefId, span: Span) { let alloc = if let ConstValue::ByRef(_, allocation, _) = static_.val { allocation } else { - panic!("Trying to get allocation info from non-byref const value") + panic!("Matching on non-ByRef static") }; if alloc.relocations.len() != 0 { let msg = "statics with a custom `#[link_section]` must be a \ From db7da0e476b943cf9248e2f49329a300ffbb132e Mon Sep 17 00:00:00 2001 From: csmoe <35686186+csmoe@users.noreply.github.com> Date: Sat, 1 Sep 2018 18:13:28 +0800 Subject: [PATCH 30/36] bug! instead of panic! --- src/librustc_mir/interpret/memory.rs | 2 +- src/librustc_typeck/check/mod.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/librustc_mir/interpret/memory.rs b/src/librustc_mir/interpret/memory.rs index d2edfdec90658..59bebbb87a775 100644 --- a/src/librustc_mir/interpret/memory.rs +++ b/src/librustc_mir/interpret/memory.rs @@ -344,7 +344,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> { if let ConstValue::ByRef(_, allocation, _) = const_val.val { allocation } else { - panic!("Matching on non-ByRef static") + bug!("Matching on non-ByRef static") } }) } diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index b0e8f1c8ca3f5..7a13d8bdd4bac 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -1378,7 +1378,7 @@ fn maybe_check_static_with_link_section(tcx: TyCtxt, id: DefId, span: Span) { let alloc = if let ConstValue::ByRef(_, allocation, _) = static_.val { allocation } else { - panic!("Matching on non-ByRef static") + bug!("Matching on non-ByRef static") }; if alloc.relocations.len() != 0 { let msg = "statics with a custom `#[link_section]` must be a \ From 798a20740ea0435727ae784a62f1632d45628dce Mon Sep 17 00:00:00 2001 From: flip1995 <9744647+flip1995@users.noreply.github.com> Date: Sat, 1 Sep 2018 17:43:14 +0200 Subject: [PATCH 31/36] Fix of bug introduced by #53762 --- src/librustc/lint/context.rs | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/librustc/lint/context.rs b/src/librustc/lint/context.rs index d5247b4ce9de8..ddd74813621a8 100644 --- a/src/librustc/lint/context.rs +++ b/src/librustc/lint/context.rs @@ -319,7 +319,15 @@ impl LintStore { CheckLintNameResult::NoLint => { Some(struct_err!(sess, E0602, "unknown lint: `{}`", lint_name)) } - CheckLintNameResult::Tool(_) => unreachable!(), + CheckLintNameResult::Tool(result) => match result { + Err((Some(_), new_name)) => Some(sess.struct_warn(&format!( + "lint name `{}` is deprcated \ + and does not have an effect anymore. \ + Use: {}", + lint_name, new_name + ))), + _ => None, + }, }; if let Some(mut db) = db { From 6a317be5c89febbdef799155e8cf667a93fa88d5 Mon Sep 17 00:00:00 2001 From: flip1995 <9744647+flip1995@users.noreply.github.com> Date: Sat, 1 Sep 2018 18:06:36 +0200 Subject: [PATCH 32/36] Add tests for cmdline tool lints --- .../ui-fulldeps/lint_tool_cmdline_allow.rs | 23 +++++++++++++++++ .../lint_tool_cmdline_allow.stderr | 25 +++++++++++++++++++ 2 files changed, 48 insertions(+) create mode 100644 src/test/ui-fulldeps/lint_tool_cmdline_allow.rs create mode 100644 src/test/ui-fulldeps/lint_tool_cmdline_allow.stderr diff --git a/src/test/ui-fulldeps/lint_tool_cmdline_allow.rs b/src/test/ui-fulldeps/lint_tool_cmdline_allow.rs new file mode 100644 index 0000000000000..74888d3e14004 --- /dev/null +++ b/src/test/ui-fulldeps/lint_tool_cmdline_allow.rs @@ -0,0 +1,23 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// run-pass +// aux-build:lint_tool_test.rs +// ignore-stage1 +// compile-flags: -A test-lint + +#![feature(plugin)] +#![warn(unused)] +#![plugin(lint_tool_test)] + +fn lintme() { } + +pub fn main() { +} diff --git a/src/test/ui-fulldeps/lint_tool_cmdline_allow.stderr b/src/test/ui-fulldeps/lint_tool_cmdline_allow.stderr new file mode 100644 index 0000000000000..fbf28a68bd0cc --- /dev/null +++ b/src/test/ui-fulldeps/lint_tool_cmdline_allow.stderr @@ -0,0 +1,25 @@ +warning: lint name `test_lint` is deprcated and does not have an effect anymore. Use: clippy::test_lint + | + = note: requested on the command line with `-A test_lint` + +warning: item is named 'lintme' + --> $DIR/lint_tool_cmdline_allow.rs:20:1 + | +LL | fn lintme() { } + | ^^^^^^^^^^^^^^^ + | + = note: #[warn(clippy::test_lint)] on by default + +warning: function is never used: `lintme` + --> $DIR/lint_tool_cmdline_allow.rs:20:1 + | +LL | fn lintme() { } + | ^^^^^^^^^^^ + | +note: lint level defined here + --> $DIR/lint_tool_cmdline_allow.rs:17:9 + | +LL | #![warn(unused)] + | ^^^^^^ + = note: #[warn(dead_code)] implied by #[warn(unused)] + From daa43643b06bf89a183ee9a41d8e50fa80f62c23 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Sat, 1 Sep 2018 21:45:44 +0530 Subject: [PATCH 33/36] deprcated -> deprecated --- src/librustc/lint/context.rs | 2 +- src/test/ui-fulldeps/lint_tool_cmdline_allow.stderr | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/librustc/lint/context.rs b/src/librustc/lint/context.rs index ddd74813621a8..b823545aa9114 100644 --- a/src/librustc/lint/context.rs +++ b/src/librustc/lint/context.rs @@ -321,7 +321,7 @@ impl LintStore { } CheckLintNameResult::Tool(result) => match result { Err((Some(_), new_name)) => Some(sess.struct_warn(&format!( - "lint name `{}` is deprcated \ + "lint name `{}` is deprecated \ and does not have an effect anymore. \ Use: {}", lint_name, new_name diff --git a/src/test/ui-fulldeps/lint_tool_cmdline_allow.stderr b/src/test/ui-fulldeps/lint_tool_cmdline_allow.stderr index fbf28a68bd0cc..c1a9d81874671 100644 --- a/src/test/ui-fulldeps/lint_tool_cmdline_allow.stderr +++ b/src/test/ui-fulldeps/lint_tool_cmdline_allow.stderr @@ -1,4 +1,4 @@ -warning: lint name `test_lint` is deprcated and does not have an effect anymore. Use: clippy::test_lint +warning: lint name `test_lint` is deprecated and does not have an effect anymore. Use: clippy::test_lint | = note: requested on the command line with `-A test_lint` From c436d9a9396c7302b985f170a8bbc65a8c586700 Mon Sep 17 00:00:00 2001 From: Jake Goulding Date: Fri, 6 May 2016 09:32:10 -0400 Subject: [PATCH 34/36] [AVR] Add AVR platform support --- config.toml.example | 2 +- src/bootstrap/config.rs | 2 +- src/librustc/ich/impls_syntax.rs | 2 + src/librustc_codegen_llvm/abi.rs | 4 ++ src/librustc_codegen_llvm/llvm/ffi.rs | 2 + src/librustc_llvm/build.rs | 2 +- src/librustc_llvm/lib.rs | 6 +++ src/librustc_target/abi/call/avr.rs | 43 +++++++++++++++++++ src/librustc_target/abi/call/mod.rs | 4 ++ src/librustc_target/spec/abi.rs | 4 ++ .../spec/avr_unknown_unknown.rs | 31 +++++++++++++ src/librustc_target/spec/mod.rs | 5 ++- src/librustc_target/spec/none_base.rs | 37 ++++++++++++++++ src/libstd/env.rs | 6 +++ src/libsyntax/feature_gate.rs | 7 +++ src/rustllvm/PassWrapper.cpp | 7 +++ src/tools/compiletest/src/util.rs | 2 + 17 files changed, 162 insertions(+), 4 deletions(-) create mode 100644 src/librustc_target/abi/call/avr.rs create mode 100644 src/librustc_target/spec/avr_unknown_unknown.rs create mode 100644 src/librustc_target/spec/none_base.rs diff --git a/config.toml.example b/config.toml.example index 35f69cd05b607..0410770291663 100644 --- a/config.toml.example +++ b/config.toml.example @@ -68,7 +68,7 @@ # not built by default and the experimental Rust compilation targets that depend # on them will not work unless the user opts in to building them. By default the # `WebAssembly` and `RISCV` targets are enabled when compiling LLVM from scratch. -#experimental-targets = "WebAssembly;RISCV" +#experimental-targets = "AVR;WebAssembly;RISCV" # Cap the number of parallel linker invocations when compiling LLVM. # This can be useful when building LLVM with debug info, which significantly diff --git a/src/bootstrap/config.rs b/src/bootstrap/config.rs index bf4d39c4947e5..6da2f2db2c52d 100644 --- a/src/bootstrap/config.rs +++ b/src/bootstrap/config.rs @@ -514,7 +514,7 @@ impl Config { set(&mut config.llvm_link_shared, llvm.link_shared); config.llvm_targets = llvm.targets.clone(); config.llvm_experimental_targets = llvm.experimental_targets.clone() - .unwrap_or("WebAssembly;RISCV".to_string()); + .unwrap_or("AVR;WebAssembly;RISCV".to_string()); config.llvm_link_jobs = llvm.link_jobs; config.llvm_clang_cl = llvm.clang_cl.clone(); } diff --git a/src/librustc/ich/impls_syntax.rs b/src/librustc/ich/impls_syntax.rs index a15411c7d8369..d0513740a5766 100644 --- a/src/librustc/ich/impls_syntax.rs +++ b/src/librustc/ich/impls_syntax.rs @@ -116,6 +116,8 @@ impl_stable_hash_for!(enum ::rustc_target::spec::abi::Abi { Msp430Interrupt, X86Interrupt, AmdGpuKernel, + AvrInterrupt, + AvrNonBlockingInterrupt, Rust, C, System, diff --git a/src/librustc_codegen_llvm/abi.rs b/src/librustc_codegen_llvm/abi.rs index 684f2b358858f..26de0eafe8b43 100644 --- a/src/librustc_codegen_llvm/abi.rs +++ b/src/librustc_codegen_llvm/abi.rs @@ -354,6 +354,8 @@ impl<'tcx> FnTypeExt<'tcx> for FnType<'tcx, Ty<'tcx>> { Msp430Interrupt => Conv::Msp430Intr, X86Interrupt => Conv::X86Intr, AmdGpuKernel => Conv::AmdGpuKernel, + AvrInterrupt => Conv::AvrInterrupt, + AvrNonBlockingInterrupt => Conv::AvrNonBlockingInterrupt, // These API constants ought to be more specific... Cdecl => Conv::C, @@ -633,6 +635,8 @@ impl<'tcx> FnTypeExt<'tcx> for FnType<'tcx, Ty<'tcx>> { match self.conv { Conv::C => llvm::CCallConv, Conv::AmdGpuKernel => llvm::AmdGpuKernel, + Conv::AvrInterrupt => llvm::AvrInterrupt, + Conv::AvrNonBlockingInterrupt => llvm::AvrNonBlockingInterrupt, Conv::ArmAapcs => llvm::ArmAapcsCallConv, Conv::Msp430Intr => llvm::Msp430Intr, Conv::PtxKernel => llvm::PtxKernel, diff --git a/src/librustc_codegen_llvm/llvm/ffi.rs b/src/librustc_codegen_llvm/llvm/ffi.rs index 51b0299e63f46..490f659ddb104 100644 --- a/src/librustc_codegen_llvm/llvm/ffi.rs +++ b/src/librustc_codegen_llvm/llvm/ffi.rs @@ -59,6 +59,8 @@ pub enum CallConv { X86_64_Win64 = 79, X86_VectorCall = 80, X86_Intr = 83, + AvrNonBlockingInterrupt = 84, + AvrInterrupt = 85, AmdGpuKernel = 91, } diff --git a/src/librustc_llvm/build.rs b/src/librustc_llvm/build.rs index 4e24a26983d48..583a92e052158 100644 --- a/src/librustc_llvm/build.rs +++ b/src/librustc_llvm/build.rs @@ -81,7 +81,7 @@ fn main() { let is_crossed = target != host; let mut optional_components = - vec!["x86", "arm", "aarch64", "mips", "powerpc", + vec!["x86", "arm", "aarch64", "avr", "mips", "powerpc", "systemz", "jsbackend", "webassembly", "msp430", "sparc", "nvptx"]; let mut version_cmd = Command::new(&llvm_config); diff --git a/src/librustc_llvm/lib.rs b/src/librustc_llvm/lib.rs index 13605e993a59c..0be8351ebc0f7 100644 --- a/src/librustc_llvm/lib.rs +++ b/src/librustc_llvm/lib.rs @@ -53,6 +53,12 @@ pub fn initialize_available_targets() { LLVMInitializeARMTargetMC, LLVMInitializeARMAsmPrinter, LLVMInitializeARMAsmParser); + init_target!(llvm_component = "avr", + LLVMInitializeAVRTargetInfo, + LLVMInitializeAVRTarget, + LLVMInitializeAVRTargetMC, + LLVMInitializeAVRAsmPrinter, + LLVMInitializeAVRAsmParser); init_target!(llvm_component = "aarch64", LLVMInitializeAArch64TargetInfo, LLVMInitializeAArch64Target, diff --git a/src/librustc_target/abi/call/avr.rs b/src/librustc_target/abi/call/avr.rs new file mode 100644 index 0000000000000..318495d93f2b1 --- /dev/null +++ b/src/librustc_target/abi/call/avr.rs @@ -0,0 +1,43 @@ +// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![allow(non_upper_case_globals)] + +use abi::call::{FnType, ArgType}; + +fn classify_ret_ty(ret: &mut ArgType) { + if ret.layout.is_aggregate() { + ret.make_indirect(); + } else { + ret.extend_integer_width_to(8); // Is 8 correct? + } +} + +fn classify_arg_ty(arg: &mut ArgType) { + if arg.layout.is_aggregate() { + arg.make_indirect(); + } else { + arg.extend_integer_width_to(8); + } +} + +pub fn compute_abi_info(fty: &mut FnType) { + if !fty.ret.is_ignore() { + classify_ret_ty(&mut fty.ret); + } + + for arg in &mut fty.args { + if arg.is_ignore() { + continue; + } + + classify_arg_ty(arg); + } +} diff --git a/src/librustc_target/abi/call/mod.rs b/src/librustc_target/abi/call/mod.rs index 78ed4b2d615a4..c5fefdda54ee6 100644 --- a/src/librustc_target/abi/call/mod.rs +++ b/src/librustc_target/abi/call/mod.rs @@ -15,6 +15,7 @@ use spec::HasTargetSpec; mod aarch64; mod arm; mod asmjs; +mod avr; mod hexagon; mod mips; mod mips64; @@ -461,6 +462,8 @@ pub enum Conv { X86_64Win64, AmdGpuKernel, + AvrInterrupt, + AvrNonBlockingInterrupt, } /// Metadata describing how the arguments to a native function @@ -517,6 +520,7 @@ impl<'a, Ty> FnType<'a, Ty> { wasm32::compute_abi_info(self) } } + "avr" => avr::compute_abi_info(self), "msp430" => msp430::compute_abi_info(self), "sparc" => sparc::compute_abi_info(cx, self), "sparc64" => sparc64::compute_abi_info(cx, self), diff --git a/src/librustc_target/spec/abi.rs b/src/librustc_target/spec/abi.rs index 6d8c8eb19f057..831f880212b04 100644 --- a/src/librustc_target/spec/abi.rs +++ b/src/librustc_target/spec/abi.rs @@ -28,6 +28,8 @@ pub enum Abi { Msp430Interrupt, X86Interrupt, AmdGpuKernel, + AvrInterrupt, + AvrNonBlockingInterrupt, // Multiplatform / generic ABIs Rust, @@ -65,6 +67,8 @@ const AbiDatas: &[AbiData] = &[ AbiData {abi: Abi::Msp430Interrupt, name: "msp430-interrupt", generic: false }, AbiData {abi: Abi::X86Interrupt, name: "x86-interrupt", generic: false }, AbiData {abi: Abi::AmdGpuKernel, name: "amdgpu-kernel", generic: false }, + AbiData {abi: Abi::AvrInterrupt, name: "avr-interrupt", generic: false }, + AbiData {abi: Abi::AvrNonBlockingInterrupt, name: "avr-non-blocking-interrupt", generic: false }, // Cross-platform ABIs AbiData {abi: Abi::Rust, name: "Rust", generic: true }, diff --git a/src/librustc_target/spec/avr_unknown_unknown.rs b/src/librustc_target/spec/avr_unknown_unknown.rs new file mode 100644 index 0000000000000..1c6debc1ae56d --- /dev/null +++ b/src/librustc_target/spec/avr_unknown_unknown.rs @@ -0,0 +1,31 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use spec::{LinkerFlavor, Target, TargetOptions, TargetResult}; + +pub fn target() -> TargetResult { + Ok(Target { + llvm_target: "avr-unknown-unknown".to_string(), + target_endian: "little".to_string(), + target_pointer_width: "16".to_string(), + data_layout: "e-P1-p:16:8-i8:8-i16:8-i32:8-i64:8-f32:8-f64:8-n8-a:8".to_string(), + arch: "avr".to_string(), + linker_flavor: LinkerFlavor::Gcc, + target_os: "unknown".to_string(), + target_env: "".to_string(), + target_vendor: "unknown".to_string(), + target_c_int_width: 16.to_string(), + options: TargetOptions { + // jemalloc is not supported on 16-bit targets. + exe_allocation_crate: Some("alloc_system".to_string()), + .. super::none_base::opts() + }, + }) +} diff --git a/src/librustc_target/spec/mod.rs b/src/librustc_target/spec/mod.rs index 2514909ba75f3..69ced159d755b 100644 --- a/src/librustc_target/spec/mod.rs +++ b/src/librustc_target/spec/mod.rs @@ -65,6 +65,7 @@ mod haiku_base; mod hermit_base; mod linux_base; mod linux_musl_base; +mod none_base; mod openbsd_base; mod netbsd_base; mod solaris_base; @@ -361,6 +362,8 @@ supported_targets! { ("aarch64-fuchsia", aarch64_fuchsia), ("x86_64-fuchsia", x86_64_fuchsia), + ("avr-unknown-unknown", avr_unknown_unknown), + ("x86_64-unknown-l4re-uclibc", x86_64_unknown_l4re_uclibc), ("x86_64-unknown-redox", x86_64_unknown_redox), @@ -433,7 +436,7 @@ pub struct Target { /// Vendor name to use for conditional compilation. pub target_vendor: String, /// Architecture to use for ABI considerations. Valid options: "x86", - /// "x86_64", "arm", "aarch64", "mips", "powerpc", and "powerpc64". + /// "x86_64", "arm", "aarch64", "avr", "mips", "powerpc", and "powerpc64". pub arch: String, /// [Data layout](http://llvm.org/docs/LangRef.html#data-layout) to pass to LLVM. pub data_layout: String, diff --git a/src/librustc_target/spec/none_base.rs b/src/librustc_target/spec/none_base.rs new file mode 100644 index 0000000000000..6afdcb6ecf1c5 --- /dev/null +++ b/src/librustc_target/spec/none_base.rs @@ -0,0 +1,37 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use std::default::Default; +use spec::{LinkerFlavor, LinkArgs, TargetOptions}; + +pub fn opts() -> TargetOptions { + let mut args = LinkArgs::new(); + + args.insert(LinkerFlavor::Gcc, vec![ + // We want to be able to strip as much executable code as possible + // from the linker command line, and this flag indicates to the + // linker that it can avoid linking in dynamic libraries that don't + // actually satisfy any symbols up to that point (as with many other + // resolutions the linker does). This option only applies to all + // following libraries so we're sure to pass it as one of the first + // arguments. + "-Wl,--as-needed".to_string(), + ]); + + TargetOptions { + dynamic_linking: false, + executables: true, + linker_is_gnu: true, + has_rpath: false, + pre_link_args: args, + position_independent_executables: true, + .. Default::default() + } +} diff --git a/src/libstd/env.rs b/src/libstd/env.rs index 9066c0b769479..d14a4bb8c494d 100644 --- a/src/libstd/env.rs +++ b/src/libstd/env.rs @@ -821,6 +821,7 @@ pub mod consts { /// - x86_64 /// - arm /// - aarch64 + /// - avr /// - mips /// - mips64 /// - powerpc @@ -933,6 +934,11 @@ mod arch { pub const ARCH: &'static str = "aarch64"; } +#[cfg(target_arch = "avr")] +mod arch { + pub const ARCH: &'static str = "avr"; +} + #[cfg(target_arch = "mips")] mod arch { pub const ARCH: &'static str = "mips"; diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index 14781dd8e24d3..aeb454f1016b7 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -346,6 +346,9 @@ declare_features! ( // `extern "x86-interrupt" fn()` (active, abi_x86_interrupt, "1.17.0", Some(40180), None), + // `extern "avr-interrupt" fn()` + (active, abi_avr_interrupt, "1.18.0", Some(000), None), + // Allows the `try {...}` expression (active, try_blocks, "1.29.0", Some(31436), None), @@ -1464,6 +1467,10 @@ impl<'a> PostExpansionVisitor<'a> { Abi::X86Interrupt => { gate_feature_post!(&self, abi_x86_interrupt, span, "x86-interrupt ABI is experimental and subject to change"); + } + Abi::AvrInterrupt | Abi::AvrNonBlockingInterrupt => { + gate_feature_post!(&self, abi_avr_interrupt, span, + "avr-interrupt and avr-non-blocking-interrupt ABIs are experimental and subject to change"); }, Abi::AmdGpuKernel => { gate_feature_post!(&self, abi_amdgpu_kernel, span, diff --git a/src/rustllvm/PassWrapper.cpp b/src/rustllvm/PassWrapper.cpp index 09befdaae37c5..5f5291b0a1b22 100644 --- a/src/rustllvm/PassWrapper.cpp +++ b/src/rustllvm/PassWrapper.cpp @@ -147,6 +147,12 @@ bool LLVMRustPassManagerBuilderPopulateThinLTOPassManager( #define SUBTARGET_AARCH64 #endif +#ifdef LLVM_COMPONENT_AVR +#define SUBTARGET_AVR SUBTARGET(AVR) +#else +#define SUBTARGET_AVR +#endif + #ifdef LLVM_COMPONENT_MIPS #define SUBTARGET_MIPS SUBTARGET(Mips) #else @@ -193,6 +199,7 @@ bool LLVMRustPassManagerBuilderPopulateThinLTOPassManager( SUBTARGET_X86 \ SUBTARGET_ARM \ SUBTARGET_AARCH64 \ + SUBTARGET_AVR \ SUBTARGET_MIPS \ SUBTARGET_PPC \ SUBTARGET_SYSTEMZ \ diff --git a/src/tools/compiletest/src/util.rs b/src/tools/compiletest/src/util.rs index 2a716970ca7b9..9c77627954118 100644 --- a/src/tools/compiletest/src/util.rs +++ b/src/tools/compiletest/src/util.rs @@ -31,6 +31,7 @@ const OS_TABLE: &'static [(&'static str, &'static str)] = &[ ("linux", "linux"), ("mingw32", "windows"), ("netbsd", "netbsd"), + ("none", "none"), ("openbsd", "openbsd"), ("redox", "redox"), ("solaris", "solaris"), @@ -48,6 +49,7 @@ const ARCH_TABLE: &'static [(&'static str, &'static str)] = &[ ("armv7", "arm"), ("armv7s", "arm"), ("asmjs", "asmjs"), + ("avr", "avr"), ("hexagon", "hexagon"), ("i386", "x86"), ("i586", "x86"), From 34e01a223e312eea50a18300c353f635a15c661a Mon Sep 17 00:00:00 2001 From: Tim Neumann Date: Sun, 28 Oct 2018 12:23:45 +0100 Subject: [PATCH 35/36] [AVR] Rustc: support instruction address space cc rust-lang/rust#54993 --- src/librustc_codegen_llvm/abi.rs | 10 +++++++++- src/librustc_codegen_llvm/meth.rs | 2 +- src/librustc_codegen_llvm/type_.rs | 2 ++ src/librustc_codegen_llvm/type_of.rs | 2 +- src/librustc_target/abi/mod.rs | 15 +++++++++++++-- 5 files changed, 26 insertions(+), 5 deletions(-) diff --git a/src/librustc_codegen_llvm/abi.rs b/src/librustc_codegen_llvm/abi.rs index 26de0eafe8b43..dcd1b68c5149f 100644 --- a/src/librustc_codegen_llvm/abi.rs +++ b/src/librustc_codegen_llvm/abi.rs @@ -19,7 +19,7 @@ use type_::Type; use type_of::{LayoutLlvmExt, PointerKind}; use value::Value; -use rustc_target::abi::{LayoutOf, Size, TyLayout}; +use rustc_target::abi::{HasDataLayout, LayoutOf, Size, TyLayout}; use rustc::ty::{self, Ty}; use rustc::ty::layout; @@ -277,6 +277,7 @@ pub trait FnTypeExt<'tcx> { cx: &CodegenCx<'ll, 'tcx>, abi: Abi); fn llvm_type(&self, cx: &CodegenCx<'ll, 'tcx>) -> &'ll Type; + fn ptr_to_llvm_type(&self, cx: &CodegenCx<'ll, 'tcx>) -> &'ll Type; fn llvm_cconv(&self) -> llvm::CallConv; fn apply_attrs_llfn(&self, llfn: &'ll Value); fn apply_attrs_callsite(&self, bx: &Builder<'a, 'll, 'tcx>, callsite: &'ll Value); @@ -631,6 +632,13 @@ impl<'tcx> FnTypeExt<'tcx> for FnType<'tcx, Ty<'tcx>> { } } + fn ptr_to_llvm_type(&self, cx: &CodegenCx<'ll, 'tcx>) -> &'ll Type { + unsafe { + llvm::LLVMPointerType(self.llvm_type(cx), + cx.data_layout().instruction_address_space as c_uint) + } + } + fn llvm_cconv(&self) -> llvm::CallConv { match self.conv { Conv::C => llvm::CCallConv, diff --git a/src/librustc_codegen_llvm/meth.rs b/src/librustc_codegen_llvm/meth.rs index 8a1159bc4773c..0164bcf9566e8 100644 --- a/src/librustc_codegen_llvm/meth.rs +++ b/src/librustc_codegen_llvm/meth.rs @@ -39,7 +39,7 @@ impl<'a, 'tcx> VirtualIndex { // Load the data pointer from the object. debug!("get_fn({:?}, {:?})", llvtable, self); - let llvtable = bx.pointercast(llvtable, fn_ty.llvm_type(bx.cx).ptr_to().ptr_to()); + let llvtable = bx.pointercast(llvtable, fn_ty.ptr_to_llvm_type(bx.cx).ptr_to()); let ptr_align = bx.tcx().data_layout.pointer_align; let ptr = bx.load(bx.inbounds_gep(llvtable, &[C_usize(bx.cx, self.0)]), ptr_align); bx.nonnull_metadata(ptr); diff --git a/src/librustc_codegen_llvm/type_.rs b/src/librustc_codegen_llvm/type_.rs index 51a233d791625..6fb78fe4aa5a4 100644 --- a/src/librustc_codegen_llvm/type_.rs +++ b/src/librustc_codegen_llvm/type_.rs @@ -234,6 +234,8 @@ impl Type { } pub fn ptr_to(&self) -> &Type { + assert_ne!(self.kind(), TypeKind::Function, + "don't call ptr_to on function types, use ptr_to_llvm_type on FnType instead"); unsafe { llvm::LLVMPointerType(self, 0) } diff --git a/src/librustc_codegen_llvm/type_of.rs b/src/librustc_codegen_llvm/type_of.rs index e6907030ae635..5fa97dbb1bdd2 100644 --- a/src/librustc_codegen_llvm/type_of.rs +++ b/src/librustc_codegen_llvm/type_of.rs @@ -264,7 +264,7 @@ impl<'tcx> LayoutLlvmExt<'tcx> for TyLayout<'tcx> { ty::ParamEnv::reveal_all(), &sig, ); - FnType::new(cx, sig, &[]).llvm_type(cx).ptr_to() + FnType::new(cx, sig, &[]).ptr_to_llvm_type(cx) } _ => self.scalar_llvm_type_at(cx, scalar, Size::ZERO) }; diff --git a/src/librustc_target/abi/mod.rs b/src/librustc_target/abi/mod.rs index 16b5241b29aa5..ca08e3fe909a0 100644 --- a/src/librustc_target/abi/mod.rs +++ b/src/librustc_target/abi/mod.rs @@ -35,7 +35,8 @@ pub struct TargetDataLayout { pub aggregate_align: Align, /// Alignments for vector types. - pub vector_align: Vec<(Size, Align)> + pub vector_align: Vec<(Size, Align)>, + pub instruction_address_space: u32, } impl Default for TargetDataLayout { @@ -57,13 +58,22 @@ impl Default for TargetDataLayout { vector_align: vec![ (Size::from_bits(64), Align::from_bits(64, 64).unwrap()), (Size::from_bits(128), Align::from_bits(128, 128).unwrap()) - ] + ], + instruction_address_space: 0, } } } impl TargetDataLayout { pub fn parse(target: &Target) -> Result { + // Parse an address space index from a string. + let parse_address_space = |s: &str, cause: &str| { + s.parse::().map_err(|err| { + format!("invalid address space `{}` for `{}` in \"data-layout\": {}", + s, cause, err) + }) + }; + // Parse a bit count from a string. let parse_bits = |s: &str, kind: &str, cause: &str| { s.parse::().map_err(|err| { @@ -96,6 +106,7 @@ impl TargetDataLayout { match spec.split(':').collect::>()[..] { ["e"] => dl.endian = Endian::Little, ["E"] => dl.endian = Endian::Big, + [p] if p.starts_with("P") => dl.instruction_address_space = parse_address_space(&p[1..], "P")?, ["a", ref a..] => dl.aggregate_align = align(a, "a")?, ["f32", ref a..] => dl.f32_align = align(a, "f32")?, ["f64", ref a..] => dl.f64_align = align(a, "f64")?, From 5379bf437151ceb602d56f396d8a6e7e7f326606 Mon Sep 17 00:00:00 2001 From: Tim Neumann Date: Sun, 28 Oct 2018 12:59:58 +0100 Subject: [PATCH 36/36] [AVR] Patch LLVM --- src/llvm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/llvm b/src/llvm index 2a1cdeadd3ea8..ddf3253b49b0d 160000 --- a/src/llvm +++ b/src/llvm @@ -1 +1 @@ -Subproject commit 2a1cdeadd3ea8e1eba9cc681037b83f07332763b +Subproject commit ddf3253b49b0ded85e030e21ff21dad3e2266413