Auto merge of #54969 - Manishearth:rollup, r=Manishearth
Rollup of 9 pull requests Successful merges: - #54747 (codegen_llvm: verify that inline assembly operands are scalars) - #54848 (Better Diagnostic for Trait Object Capture) - #54850 (Fix #54707 - parse_trait_item_ now handles interpolated blocks as function body decls) - #54858 (second round of refactorings for universes) - #54862 (Implement RFC 2539: cfg_attr with multiple attributes) - #54869 (Fix mobile docs) - #54870 (Stabilize tool lints) - #54893 (Fix internal compiler error on malformed match arm pattern.) - #54904 (Stabilize the `Option::replace` method) Failed merges: - #54909 ( Add chalk rules related to associated type defs) r? @ghost
This commit is contained in:
commit
cb6eeddd4d
71 changed files with 599 additions and 242 deletions
|
|
@ -270,7 +270,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
|
||||
[[package]]
|
||||
name = "chalk-engine"
|
||||
version = "0.7.0"
|
||||
version = "0.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"chalk-macros 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
|
@ -1898,7 +1898,7 @@ dependencies = [
|
|||
"backtrace 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"byteorder 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"chalk-engine 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"chalk-engine 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"flate2 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"fmt_macros 0.0.0",
|
||||
"graphviz 0.0.0",
|
||||
|
|
@ -2434,7 +2434,7 @@ name = "rustc_traits"
|
|||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"chalk-engine 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"chalk-engine 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"graphviz 0.0.0",
|
||||
"log 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rustc 0.0.0",
|
||||
|
|
@ -3195,7 +3195,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
"checksum cargo_metadata 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2d6809b327f87369e6f3651efd2c5a96c49847a3ed2559477ecba79014751ee1"
|
||||
"checksum cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)" = "f159dfd43363c4d08055a07703eb7a3406b0dac4d0584d96965a3262db3c9d16"
|
||||
"checksum cfg-if 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "0c4e7bb64a8ebb0d856483e1e682ea3422f883c5f5615a90d51a2c82fe87fdd3"
|
||||
"checksum chalk-engine 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "25ce2f28f55ed544a2a3756b7acf41dd7d6f27acffb2086439950925506af7d0"
|
||||
"checksum chalk-engine 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6749eb72e7d4355d944a99f15fbaea701b978c18c5e184a025fcde942b0c9779"
|
||||
"checksum chalk-macros 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "295635afd6853aa9f20baeb7f0204862440c0fe994c5a253d5f479dac41d047e"
|
||||
"checksum chrono 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "6962c635d530328acc53ac6a955e83093fedc91c5809dfac1fa60fa470830a37"
|
||||
"checksum clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b957d88f4b6a63b9d70d5f454ac8011819c6efa7727858f458ab71c756ce2d3e"
|
||||
|
|
|
|||
|
|
@ -0,0 +1,20 @@
|
|||
# `cfg_attr_multi`
|
||||
|
||||
The tracking issue for this feature is: [#54881]
|
||||
The RFC for this feature is: [#2539]
|
||||
|
||||
[#54881]: https://github.com/rust-lang/rust/issues/54881
|
||||
[#2539]: https://github.com/rust-lang/rfcs/pull/2539
|
||||
|
||||
------------------------
|
||||
|
||||
This feature flag lets you put multiple attributes into a `cfg_attr` attribute.
|
||||
|
||||
Example:
|
||||
|
||||
```rust,ignore
|
||||
#[cfg_attr(all(), must_use, optimize)]
|
||||
```
|
||||
|
||||
Because `cfg_attr` resolves before procedural macros, this does not affect
|
||||
macro resolution at all.
|
||||
|
|
@ -1,35 +0,0 @@
|
|||
# `tool_lints`
|
||||
|
||||
The tracking issue for this feature is: [#44690]
|
||||
|
||||
[#44690]: https://github.com/rust-lang/rust/issues/44690
|
||||
|
||||
------------------------
|
||||
|
||||
Tool lints let you use scoped lints, to `allow`, `warn`, `deny` or `forbid` lints of
|
||||
certain tools.
|
||||
|
||||
Currently `clippy` is the only available lint tool.
|
||||
|
||||
It is recommended for lint tools to implement the scoped lints like this:
|
||||
|
||||
- `#[_(TOOL_NAME::lintname)]`: for lint names
|
||||
- `#[_(TOOL_NAME::lintgroup)]`: for groups of lints
|
||||
- `#[_(TOOL_NAME::all)]`: for (almost[^1]) all lints
|
||||
|
||||
## An example
|
||||
|
||||
```rust
|
||||
#![feature(tool_lints)]
|
||||
|
||||
#![warn(clippy::pedantic)]
|
||||
|
||||
#[allow(clippy::filter_map)]
|
||||
fn main() {
|
||||
let v = vec![0; 10];
|
||||
let _ = v.into_iter().filter(|&x| x < 1).map(|x| x + 1).collect::<Vec<_>>();
|
||||
println!("No filter_map()!");
|
||||
}
|
||||
```
|
||||
|
||||
[^1]: Some defined lint groups can be excluded here.
|
||||
|
|
@ -867,8 +867,6 @@ impl<T> Option<T> {
|
|||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(option_replace)]
|
||||
///
|
||||
/// let mut x = Some(2);
|
||||
/// let old = x.replace(5);
|
||||
/// assert_eq!(x, Some(5));
|
||||
|
|
@ -880,7 +878,7 @@ impl<T> Option<T> {
|
|||
/// assert_eq!(old, None);
|
||||
/// ```
|
||||
#[inline]
|
||||
#[unstable(feature = "option_replace", issue = "51998")]
|
||||
#[stable(feature = "option_replace", since = "1.31.0")]
|
||||
pub fn replace(&mut self, value: T) -> Option<T> {
|
||||
mem::replace(self, Some(value))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -39,7 +39,6 @@
|
|||
#![feature(reverse_bits)]
|
||||
#![feature(inner_deref)]
|
||||
#![feature(slice_internals)]
|
||||
#![feature(option_replace)]
|
||||
#![feature(slice_partition_dedup)]
|
||||
#![feature(copy_within)]
|
||||
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@ syntax_pos = { path = "../libsyntax_pos" }
|
|||
backtrace = "0.3.3"
|
||||
parking_lot = "0.6"
|
||||
byteorder = { version = "1.1", features = ["i128"]}
|
||||
chalk-engine = { version = "0.7.0", default-features=false }
|
||||
chalk-engine = { version = "0.8.0", default-features=false }
|
||||
rustc_fs_util = { path = "../librustc_fs_util" }
|
||||
smallvec = { version = "0.6.5", features = ["union"] }
|
||||
|
||||
|
|
|
|||
|
|
@ -1370,7 +1370,7 @@ impl<'a, 'tcx> HashStable<StableHashingContext<'a>> for traits::Goal<'tcx> {
|
|||
fn hash_stable<W: StableHasherResult>(&self,
|
||||
hcx: &mut StableHashingContext<'a>,
|
||||
hasher: &mut StableHasher<W>) {
|
||||
use traits::Goal::*;
|
||||
use traits::GoalKind::*;
|
||||
|
||||
mem::discriminant(self).hash_stable(hcx, hasher);
|
||||
match self {
|
||||
|
|
|
|||
|
|
@ -18,11 +18,10 @@ use lint::context::CheckLintNameResult;
|
|||
use lint::{self, Lint, LintId, Level, LintSource};
|
||||
use rustc_data_structures::stable_hasher::{HashStable, ToStableHashKey,
|
||||
StableHasher, StableHasherResult};
|
||||
use session::{config::nightly_options, Session};
|
||||
use session::Session;
|
||||
use syntax::ast;
|
||||
use syntax::attr;
|
||||
use syntax::source_map::MultiSpan;
|
||||
use syntax::feature_gate;
|
||||
use syntax::symbol::Symbol;
|
||||
use util::nodemap::FxHashMap;
|
||||
|
||||
|
|
@ -228,18 +227,7 @@ impl<'a> LintLevelsBuilder<'a> {
|
|||
}
|
||||
};
|
||||
let tool_name = if let Some(lint_tool) = word.is_scoped() {
|
||||
let gate_feature = !self.sess.features_untracked().tool_lints;
|
||||
let known_tool = attr::is_known_lint_tool(lint_tool);
|
||||
if gate_feature {
|
||||
feature_gate::emit_feature_err(
|
||||
&sess.parse_sess,
|
||||
"tool_lints",
|
||||
word.span,
|
||||
feature_gate::GateIssue::Language,
|
||||
&format!("scoped lint `{}` is experimental", word.ident),
|
||||
);
|
||||
}
|
||||
if !known_tool {
|
||||
if !attr::is_known_lint_tool(lint_tool) {
|
||||
span_err!(
|
||||
sess,
|
||||
lint_tool.span,
|
||||
|
|
@ -247,9 +235,6 @@ impl<'a> LintLevelsBuilder<'a> {
|
|||
"an unknown tool name found in scoped lint: `{}`",
|
||||
word.ident
|
||||
);
|
||||
}
|
||||
|
||||
if gate_feature || !known_tool {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
@ -299,13 +284,7 @@ impl<'a> LintLevelsBuilder<'a> {
|
|||
"change it to",
|
||||
new_lint_name.to_string(),
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
|
||||
if nightly_options::is_nightly_build() {
|
||||
err.emit();
|
||||
} else {
|
||||
err.cancel();
|
||||
}
|
||||
).emit();
|
||||
|
||||
let src = LintSource::Node(Symbol::intern(&new_lint_name), li.span);
|
||||
for id in ids {
|
||||
|
|
|
|||
|
|
@ -318,31 +318,33 @@ pub enum QuantifierKind {
|
|||
}
|
||||
|
||||
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
|
||||
pub enum Goal<'tcx> {
|
||||
Implies(Clauses<'tcx>, &'tcx Goal<'tcx>),
|
||||
And(&'tcx Goal<'tcx>, &'tcx Goal<'tcx>),
|
||||
Not(&'tcx Goal<'tcx>),
|
||||
pub enum GoalKind<'tcx> {
|
||||
Implies(Clauses<'tcx>, Goal<'tcx>),
|
||||
And(Goal<'tcx>, Goal<'tcx>),
|
||||
Not(Goal<'tcx>),
|
||||
DomainGoal(DomainGoal<'tcx>),
|
||||
Quantified(QuantifierKind, ty::Binder<&'tcx Goal<'tcx>>),
|
||||
Quantified(QuantifierKind, ty::Binder<Goal<'tcx>>),
|
||||
CannotProve,
|
||||
}
|
||||
|
||||
pub type Goal<'tcx> = &'tcx GoalKind<'tcx>;
|
||||
|
||||
pub type Goals<'tcx> = &'tcx List<Goal<'tcx>>;
|
||||
|
||||
impl<'tcx> DomainGoal<'tcx> {
|
||||
pub fn into_goal(self) -> Goal<'tcx> {
|
||||
Goal::DomainGoal(self)
|
||||
pub fn into_goal(self) -> GoalKind<'tcx> {
|
||||
GoalKind::DomainGoal(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Goal<'tcx> {
|
||||
impl<'tcx> GoalKind<'tcx> {
|
||||
pub fn from_poly_domain_goal<'a>(
|
||||
domain_goal: PolyDomainGoal<'tcx>,
|
||||
tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
) -> Goal<'tcx> {
|
||||
) -> GoalKind<'tcx> {
|
||||
match domain_goal.no_late_bound_regions() {
|
||||
Some(p) => p.into_goal(),
|
||||
None => Goal::Quantified(
|
||||
None => GoalKind::Quantified(
|
||||
QuantifierKind::Universal,
|
||||
domain_goal.map_bound(|p| tcx.mk_goal(p.into_goal()))
|
||||
),
|
||||
|
|
|
|||
|
|
@ -469,7 +469,7 @@ impl fmt::Display for traits::QuantifierKind {
|
|||
|
||||
impl<'tcx> fmt::Display for traits::Goal<'tcx> {
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
use traits::Goal::*;
|
||||
use traits::GoalKind::*;
|
||||
|
||||
match self {
|
||||
Implies(hypotheses, goal) => {
|
||||
|
|
@ -598,25 +598,25 @@ CloneTypeFoldableAndLiftImpls! {
|
|||
}
|
||||
|
||||
EnumTypeFoldableImpl! {
|
||||
impl<'tcx> TypeFoldable<'tcx> for traits::Goal<'tcx> {
|
||||
(traits::Goal::Implies)(hypotheses, goal),
|
||||
(traits::Goal::And)(goal1, goal2),
|
||||
(traits::Goal::Not)(goal),
|
||||
(traits::Goal::DomainGoal)(domain_goal),
|
||||
(traits::Goal::Quantified)(qkind, goal),
|
||||
(traits::Goal::CannotProve),
|
||||
impl<'tcx> TypeFoldable<'tcx> for traits::GoalKind<'tcx> {
|
||||
(traits::GoalKind::Implies)(hypotheses, goal),
|
||||
(traits::GoalKind::And)(goal1, goal2),
|
||||
(traits::GoalKind::Not)(goal),
|
||||
(traits::GoalKind::DomainGoal)(domain_goal),
|
||||
(traits::GoalKind::Quantified)(qkind, goal),
|
||||
(traits::GoalKind::CannotProve),
|
||||
}
|
||||
}
|
||||
|
||||
EnumLiftImpl! {
|
||||
impl<'a, 'tcx> Lift<'tcx> for traits::Goal<'a> {
|
||||
type Lifted = traits::Goal<'tcx>;
|
||||
(traits::Goal::Implies)(hypotheses, goal),
|
||||
(traits::Goal::And)(goal1, goal2),
|
||||
(traits::Goal::Not)(goal),
|
||||
(traits::Goal::DomainGoal)(domain_goal),
|
||||
(traits::Goal::Quantified)(kind, goal),
|
||||
(traits::Goal::CannotProve),
|
||||
impl<'a, 'tcx> Lift<'tcx> for traits::GoalKind<'a> {
|
||||
type Lifted = traits::GoalKind<'tcx>;
|
||||
(traits::GoalKind::Implies)(hypotheses, goal),
|
||||
(traits::GoalKind::And)(goal1, goal2),
|
||||
(traits::GoalKind::Not)(goal),
|
||||
(traits::GoalKind::DomainGoal)(domain_goal),
|
||||
(traits::GoalKind::Quantified)(kind, goal),
|
||||
(traits::GoalKind::CannotProve),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -633,7 +633,7 @@ impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::List<traits::Goal<'tcx>> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'tcx> TypeFoldable<'tcx> for &'tcx traits::Goal<'tcx> {
|
||||
impl<'tcx> TypeFoldable<'tcx> for traits::Goal<'tcx> {
|
||||
fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self {
|
||||
let v = (**self).fold_with(folder);
|
||||
folder.tcx().mk_goal(v)
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@ use mir::interpret::Allocation;
|
|||
use ty::subst::{CanonicalSubsts, Kind, Substs, Subst};
|
||||
use ty::ReprOptions;
|
||||
use traits;
|
||||
use traits::{Clause, Clauses, Goal, Goals};
|
||||
use traits::{Clause, Clauses, GoalKind, Goal, Goals};
|
||||
use ty::{self, Ty, TypeAndMut};
|
||||
use ty::{TyS, TyKind, List};
|
||||
use ty::{AdtKind, AdtDef, ClosureSubsts, GeneratorSubsts, Region, Const};
|
||||
|
|
@ -143,7 +143,8 @@ pub struct CtxtInterners<'tcx> {
|
|||
predicates: InternedSet<'tcx, List<Predicate<'tcx>>>,
|
||||
const_: InternedSet<'tcx, Const<'tcx>>,
|
||||
clauses: InternedSet<'tcx, List<Clause<'tcx>>>,
|
||||
goals: InternedSet<'tcx, List<Goal<'tcx>>>,
|
||||
goal: InternedSet<'tcx, GoalKind<'tcx>>,
|
||||
goal_list: InternedSet<'tcx, List<Goal<'tcx>>>,
|
||||
}
|
||||
|
||||
impl<'gcx: 'tcx, 'tcx> CtxtInterners<'tcx> {
|
||||
|
|
@ -159,7 +160,8 @@ impl<'gcx: 'tcx, 'tcx> CtxtInterners<'tcx> {
|
|||
predicates: Default::default(),
|
||||
const_: Default::default(),
|
||||
clauses: Default::default(),
|
||||
goals: Default::default(),
|
||||
goal: Default::default(),
|
||||
goal_list: Default::default(),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1731,9 +1733,9 @@ impl<'a, 'tcx> Lift<'tcx> for Region<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> Lift<'tcx> for &'a Goal<'a> {
|
||||
type Lifted = &'tcx Goal<'tcx>;
|
||||
fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option<&'tcx Goal<'tcx>> {
|
||||
impl<'a, 'tcx> Lift<'tcx> for Goal<'a> {
|
||||
type Lifted = Goal<'tcx>;
|
||||
fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option<Goal<'tcx>> {
|
||||
if tcx.interners.arena.in_arena(*self as *const _) {
|
||||
return Some(unsafe { mem::transmute(*self) });
|
||||
}
|
||||
|
|
@ -2304,6 +2306,12 @@ impl<'tcx> Borrow<RegionKind> for Interned<'tcx, RegionKind> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'tcx: 'lcx, 'lcx> Borrow<GoalKind<'lcx>> for Interned<'tcx, GoalKind<'tcx>> {
|
||||
fn borrow<'a>(&'a self) -> &'a GoalKind<'lcx> {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx: 'lcx, 'lcx> Borrow<[ExistentialPredicate<'lcx>]>
|
||||
for Interned<'tcx, List<ExistentialPredicate<'tcx>>> {
|
||||
fn borrow<'a>(&'a self) -> &'a [ExistentialPredicate<'lcx>] {
|
||||
|
|
@ -2419,7 +2427,8 @@ pub fn keep_local<'tcx, T: ty::TypeFoldable<'tcx>>(x: &T) -> bool {
|
|||
|
||||
direct_interners!('tcx,
|
||||
region: mk_region(|r: &RegionKind| r.keep_in_local_tcx()) -> RegionKind,
|
||||
const_: mk_const(|c: &Const<'_>| keep_local(&c.ty) || keep_local(&c.val)) -> Const<'tcx>
|
||||
const_: mk_const(|c: &Const<'_>| keep_local(&c.ty) || keep_local(&c.val)) -> Const<'tcx>,
|
||||
goal: mk_goal(|c: &GoalKind<'_>| keep_local(c)) -> GoalKind<'tcx>
|
||||
);
|
||||
|
||||
macro_rules! slice_interners {
|
||||
|
|
@ -2438,7 +2447,7 @@ slice_interners!(
|
|||
type_list: _intern_type_list(Ty),
|
||||
substs: _intern_substs(Kind),
|
||||
clauses: _intern_clauses(Clause),
|
||||
goals: _intern_goals(Goal)
|
||||
goal_list: _intern_goals(Goal)
|
||||
);
|
||||
|
||||
// This isn't a perfect fit: CanonicalVarInfo slices are always
|
||||
|
|
@ -2818,10 +2827,6 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
|
|||
iter.intern_with(|xs| self.intern_goals(xs))
|
||||
}
|
||||
|
||||
pub fn mk_goal(self, goal: Goal<'tcx>) -> &'tcx Goal<'_> {
|
||||
&self.intern_goals(&[goal])[0]
|
||||
}
|
||||
|
||||
pub fn lint_hir<S: Into<MultiSpan>>(self,
|
||||
lint: &'static Lint,
|
||||
hir_id: HirId,
|
||||
|
|
|
|||
|
|
@ -148,7 +148,10 @@ impl FlagComputation {
|
|||
self.add_projection_ty(data);
|
||||
}
|
||||
|
||||
&ty::UnnormalizedProjection(..) => bug!("only used with chalk-engine"),
|
||||
&ty::UnnormalizedProjection(ref data) => {
|
||||
self.add_flags(TypeFlags::HAS_PROJECTION);
|
||||
self.add_projection_ty(data);
|
||||
},
|
||||
|
||||
&ty::Opaque(_, substs) => {
|
||||
self.add_flags(TypeFlags::HAS_PROJECTION);
|
||||
|
|
|
|||
|
|
@ -21,7 +21,6 @@
|
|||
#![feature(box_syntax)]
|
||||
#![cfg_attr(unix, feature(libc))]
|
||||
#![feature(nll)]
|
||||
#![feature(option_replace)]
|
||||
#![feature(quote)]
|
||||
#![feature(rustc_diagnostic_macros)]
|
||||
#![feature(slice_sort_by_cached_key)]
|
||||
|
|
|
|||
|
|
@ -16,5 +16,5 @@ rustc = { path = "../librustc" }
|
|||
rustc_data_structures = { path = "../librustc_data_structures" }
|
||||
syntax = { path = "../libsyntax" }
|
||||
syntax_pos = { path = "../libsyntax_pos" }
|
||||
chalk-engine = { version = "0.7.0", default-features=false }
|
||||
chalk-engine = { version = "0.8.0", default-features=false }
|
||||
smallvec = { version = "0.6.5", features = ["union"] }
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@ use rustc::traits::{
|
|||
ExClauseFold,
|
||||
ExClauseLift,
|
||||
Goal,
|
||||
GoalKind,
|
||||
ProgramClause,
|
||||
QuantifierKind
|
||||
};
|
||||
|
|
@ -92,7 +93,7 @@ impl context::Context for ChalkArenas<'tcx> {
|
|||
|
||||
type DomainGoal = DomainGoal<'tcx>;
|
||||
|
||||
type BindersGoal = ty::Binder<&'tcx Goal<'tcx>>;
|
||||
type BindersGoal = ty::Binder<Goal<'tcx>>;
|
||||
|
||||
type Parameter = Kind<'tcx>;
|
||||
|
||||
|
|
@ -102,14 +103,6 @@ impl context::Context for ChalkArenas<'tcx> {
|
|||
|
||||
type UnificationResult = InferOk<'tcx, ()>;
|
||||
|
||||
fn into_goal(domain_goal: DomainGoal<'tcx>) -> Goal<'tcx> {
|
||||
Goal::DomainGoal(domain_goal)
|
||||
}
|
||||
|
||||
fn cannot_prove() -> Goal<'tcx> {
|
||||
Goal::CannotProve
|
||||
}
|
||||
|
||||
fn goal_in_environment(
|
||||
env: &ty::ParamEnv<'tcx>,
|
||||
goal: Goal<'tcx>,
|
||||
|
|
@ -251,15 +244,23 @@ impl context::ContextOps<ChalkArenas<'gcx>> for ChalkContext<'cx, 'gcx> {
|
|||
impl context::InferenceTable<ChalkArenas<'gcx>, ChalkArenas<'tcx>>
|
||||
for ChalkInferenceContext<'cx, 'gcx, 'tcx>
|
||||
{
|
||||
fn into_goal(&self, domain_goal: DomainGoal<'tcx>) -> Goal<'tcx> {
|
||||
self.infcx.tcx.mk_goal(GoalKind::DomainGoal(domain_goal))
|
||||
}
|
||||
|
||||
fn cannot_prove(&self) -> Goal<'tcx> {
|
||||
self.infcx.tcx.mk_goal(GoalKind::CannotProve)
|
||||
}
|
||||
|
||||
fn into_hh_goal(&mut self, goal: Goal<'tcx>) -> ChalkHhGoal<'tcx> {
|
||||
match goal {
|
||||
Goal::Implies(..) => panic!("FIXME rust-lang-nursery/chalk#94"),
|
||||
Goal::And(left, right) => HhGoal::And(*left, *right),
|
||||
Goal::Not(subgoal) => HhGoal::Not(*subgoal),
|
||||
Goal::DomainGoal(d) => HhGoal::DomainGoal(d),
|
||||
Goal::Quantified(QuantifierKind::Universal, binder) => HhGoal::ForAll(binder),
|
||||
Goal::Quantified(QuantifierKind::Existential, binder) => HhGoal::Exists(binder),
|
||||
Goal::CannotProve => HhGoal::CannotProve,
|
||||
match *goal {
|
||||
GoalKind::Implies(..) => panic!("FIXME rust-lang-nursery/chalk#94"),
|
||||
GoalKind::And(left, right) => HhGoal::And(left, right),
|
||||
GoalKind::Not(subgoal) => HhGoal::Not(subgoal),
|
||||
GoalKind::DomainGoal(d) => HhGoal::DomainGoal(d),
|
||||
GoalKind::Quantified(QuantifierKind::Universal, binder) => HhGoal::ForAll(binder),
|
||||
GoalKind::Quantified(QuantifierKind::Existential, binder) => HhGoal::Exists(binder),
|
||||
GoalKind::CannotProve => HhGoal::CannotProve,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -363,21 +364,21 @@ impl context::UnificationOps<ChalkArenas<'gcx>, ChalkArenas<'tcx>>
|
|||
|
||||
fn instantiate_binders_universally(
|
||||
&mut self,
|
||||
_arg: &ty::Binder<&'tcx Goal<'tcx>>,
|
||||
_arg: &ty::Binder<Goal<'tcx>>,
|
||||
) -> Goal<'tcx> {
|
||||
panic!("FIXME -- universal instantiation needs sgrif's branch")
|
||||
}
|
||||
|
||||
fn instantiate_binders_existentially(
|
||||
&mut self,
|
||||
arg: &ty::Binder<&'tcx Goal<'tcx>>,
|
||||
arg: &ty::Binder<Goal<'tcx>>,
|
||||
) -> Goal<'tcx> {
|
||||
let (value, _map) = self.infcx.replace_late_bound_regions_with_fresh_var(
|
||||
DUMMY_SP,
|
||||
LateBoundRegionConversionTime::HigherRankedType,
|
||||
arg,
|
||||
);
|
||||
*value
|
||||
value
|
||||
}
|
||||
|
||||
fn debug_ex_clause(&mut self, value: &'v ChalkExClause<'tcx>) -> Box<dyn Debug + 'v> {
|
||||
|
|
|
|||
|
|
@ -13,7 +13,14 @@ use rustc::hir::intravisit::{self, NestedVisitorMap, Visitor};
|
|||
use rustc::hir::map::definitions::DefPathData;
|
||||
use rustc::hir::{self, ImplPolarity};
|
||||
use rustc::traits::{
|
||||
Clause, Clauses, DomainGoal, FromEnv, Goal, PolyDomainGoal, ProgramClause, WellFormed,
|
||||
Clause,
|
||||
Clauses,
|
||||
DomainGoal,
|
||||
FromEnv,
|
||||
GoalKind,
|
||||
PolyDomainGoal,
|
||||
ProgramClause,
|
||||
WellFormed,
|
||||
WhereClause,
|
||||
};
|
||||
use rustc::ty::query::Providers;
|
||||
|
|
@ -249,7 +256,7 @@ fn program_clauses_for_trait<'a, 'tcx>(
|
|||
let impl_trait: DomainGoal = trait_pred.lower();
|
||||
|
||||
// `FromEnv(Self: Trait<P1..Pn>)`
|
||||
let from_env_goal = impl_trait.into_from_env_goal().into_goal();
|
||||
let from_env_goal = tcx.mk_goal(impl_trait.into_from_env_goal().into_goal());
|
||||
let hypotheses = tcx.intern_goals(&[from_env_goal]);
|
||||
|
||||
// `Implemented(Self: Trait<P1..Pn>) :- FromEnv(Self: Trait<P1..Pn>)`
|
||||
|
|
@ -308,7 +315,7 @@ fn program_clauses_for_trait<'a, 'tcx>(
|
|||
let wf_clause = ProgramClause {
|
||||
goal: DomainGoal::WellFormed(WellFormed::Trait(trait_pred)),
|
||||
hypotheses: tcx.mk_goals(
|
||||
wf_conditions.map(|wc| Goal::from_poly_domain_goal(wc, tcx)),
|
||||
wf_conditions.map(|wc| tcx.mk_goal(GoalKind::from_poly_domain_goal(wc, tcx))),
|
||||
),
|
||||
};
|
||||
let wf_clause = iter::once(Clause::ForAll(ty::Binder::dummy(wf_clause)));
|
||||
|
|
@ -352,10 +359,10 @@ fn program_clauses_for_impl<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId
|
|||
hypotheses: tcx.mk_goals(
|
||||
where_clauses
|
||||
.into_iter()
|
||||
.map(|wc| Goal::from_poly_domain_goal(wc, tcx)),
|
||||
.map(|wc| tcx.mk_goal(GoalKind::from_poly_domain_goal(wc, tcx))),
|
||||
),
|
||||
};
|
||||
tcx.intern_clauses(&[Clause::ForAll(ty::Binder::dummy(clause))])
|
||||
tcx.mk_clauses(iter::once(Clause::ForAll(ty::Binder::dummy(clause))))
|
||||
}
|
||||
|
||||
pub fn program_clauses_for_type_def<'a, 'tcx>(
|
||||
|
|
@ -388,7 +395,7 @@ pub fn program_clauses_for_type_def<'a, 'tcx>(
|
|||
where_clauses
|
||||
.iter()
|
||||
.cloned()
|
||||
.map(|wc| Goal::from_poly_domain_goal(wc, tcx)),
|
||||
.map(|wc| tcx.mk_goal(GoalKind::from_poly_domain_goal(wc, tcx))),
|
||||
),
|
||||
};
|
||||
|
||||
|
|
@ -404,7 +411,7 @@ pub fn program_clauses_for_type_def<'a, 'tcx>(
|
|||
// ```
|
||||
|
||||
// `FromEnv(Ty<...>)`
|
||||
let from_env_goal = DomainGoal::FromEnv(FromEnv::Ty(ty)).into_goal();
|
||||
let from_env_goal = tcx.mk_goal(DomainGoal::FromEnv(FromEnv::Ty(ty)).into_goal());
|
||||
let hypotheses = tcx.intern_goals(&[from_env_goal]);
|
||||
|
||||
// For each where clause `WC`:
|
||||
|
|
@ -423,10 +430,86 @@ pub fn program_clauses_for_type_def<'a, 'tcx>(
|
|||
}
|
||||
|
||||
pub fn program_clauses_for_associated_type_def<'a, 'tcx>(
|
||||
_tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
_item_id: DefId,
|
||||
tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
item_id: DefId,
|
||||
) -> Clauses<'tcx> {
|
||||
unimplemented!()
|
||||
// Rule ProjectionEq-Skolemize
|
||||
//
|
||||
// ```
|
||||
// trait Trait<P1..Pn> {
|
||||
// type AssocType<Pn+1..Pm>;
|
||||
// }
|
||||
// ```
|
||||
//
|
||||
// `ProjectionEq` can succeed by skolemizing, see "associated type"
|
||||
// chapter for more:
|
||||
// ```
|
||||
// forall<Self, P1..Pn, Pn+1..Pm> {
|
||||
// ProjectionEq(
|
||||
// <Self as Trait<P1..Pn>>::AssocType<Pn+1..Pm> =
|
||||
// (Trait::AssocType)<Self, P1..Pn, Pn+1..Pm>
|
||||
// )
|
||||
// }
|
||||
// ```
|
||||
|
||||
let item = tcx.associated_item(item_id);
|
||||
debug_assert_eq!(item.kind, ty::AssociatedKind::Type);
|
||||
let trait_id = match item.container {
|
||||
ty::AssociatedItemContainer::TraitContainer(trait_id) => trait_id,
|
||||
_ => bug!("not an trait container"),
|
||||
};
|
||||
let trait_ref = ty::TraitRef::identity(tcx, trait_id);
|
||||
|
||||
let projection_ty = ty::ProjectionTy::from_ref_and_name(tcx, trait_ref, item.ident);
|
||||
let placeholder_ty = tcx.mk_ty(ty::UnnormalizedProjection(projection_ty));
|
||||
let projection_eq = WhereClause::ProjectionEq(ty::ProjectionPredicate {
|
||||
projection_ty,
|
||||
ty: placeholder_ty,
|
||||
});
|
||||
|
||||
let projection_eq_clause = ProgramClause {
|
||||
goal: DomainGoal::Holds(projection_eq),
|
||||
hypotheses: &ty::List::empty(),
|
||||
};
|
||||
|
||||
// Rule WellFormed-AssocTy
|
||||
// ```
|
||||
// forall<Self, P1..Pn, Pn+1..Pm> {
|
||||
// WellFormed((Trait::AssocType)<Self, P1..Pn, Pn+1..Pm>)
|
||||
// :- Implemented(Self: Trait<P1..Pn>)
|
||||
// }
|
||||
// ```
|
||||
|
||||
let trait_predicate = ty::TraitPredicate { trait_ref };
|
||||
let hypothesis = tcx.mk_goal(
|
||||
DomainGoal::Holds(WhereClause::Implemented(trait_predicate)).into_goal()
|
||||
);
|
||||
let wf_clause = ProgramClause {
|
||||
goal: DomainGoal::WellFormed(WellFormed::Ty(placeholder_ty)),
|
||||
hypotheses: tcx.mk_goals(iter::once(hypothesis)),
|
||||
};
|
||||
|
||||
// Rule Implied-Trait-From-AssocTy
|
||||
// ```
|
||||
// forall<Self, P1..Pn, Pn+1..Pm> {
|
||||
// FromEnv(Self: Trait<P1..Pn>)
|
||||
// :- FromEnv((Trait::AssocType)<Self, P1..Pn, Pn+1..Pm>)
|
||||
// }
|
||||
// ```
|
||||
|
||||
let hypothesis = tcx.mk_goal(
|
||||
DomainGoal::FromEnv(FromEnv::Ty(placeholder_ty)).into_goal()
|
||||
);
|
||||
let from_env_clause = ProgramClause {
|
||||
goal: DomainGoal::FromEnv(FromEnv::Trait(trait_predicate)),
|
||||
hypotheses: tcx.mk_goals(iter::once(hypothesis)),
|
||||
};
|
||||
|
||||
let clauses = iter::once(projection_eq_clause)
|
||||
.chain(iter::once(wf_clause))
|
||||
.chain(iter::once(from_env_clause));
|
||||
let clauses = clauses.map(|clause| Clause::ForAll(ty::Binder::dummy(clause)));
|
||||
tcx.mk_clauses(clauses)
|
||||
}
|
||||
|
||||
pub fn program_clauses_for_associated_type_value<'a, 'tcx>(
|
||||
|
|
@ -435,10 +518,11 @@ pub fn program_clauses_for_associated_type_value<'a, 'tcx>(
|
|||
) -> Clauses<'tcx> {
|
||||
// Rule Normalize-From-Impl (see rustc guide)
|
||||
//
|
||||
// ```impl<P0..Pn> Trait<A1..An> for A0
|
||||
// {
|
||||
// ```
|
||||
// impl<P0..Pn> Trait<A1..An> for A0 {
|
||||
// type AssocType<Pn+1..Pm> = T;
|
||||
// }```
|
||||
// }
|
||||
// ```
|
||||
//
|
||||
// FIXME: For the moment, we don't account for where clauses written on the associated
|
||||
// ty definition (i.e. in the trait def, as in `type AssocType<T> where T: Sized`).
|
||||
|
|
@ -482,10 +566,10 @@ pub fn program_clauses_for_associated_type_value<'a, 'tcx>(
|
|||
hypotheses: tcx.mk_goals(
|
||||
hypotheses
|
||||
.into_iter()
|
||||
.map(|wc| Goal::from_poly_domain_goal(wc, tcx)),
|
||||
.map(|wc| tcx.mk_goal(GoalKind::from_poly_domain_goal(wc, tcx))),
|
||||
),
|
||||
};
|
||||
tcx.intern_clauses(&[Clause::ForAll(ty::Binder::dummy(clause))])
|
||||
tcx.mk_clauses(iter::once(Clause::ForAll(ty::Binder::dummy(clause))))
|
||||
}
|
||||
|
||||
pub fn dump_program_clauses<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
|
||||
|
|
|
|||
|
|
@ -9,7 +9,14 @@
|
|||
// except according to those terms.
|
||||
|
||||
use attr::HasAttrs;
|
||||
use feature_gate::{feature_err, EXPLAIN_STMT_ATTR_SYNTAX, Features, get_features, GateIssue};
|
||||
use feature_gate::{
|
||||
feature_err,
|
||||
EXPLAIN_STMT_ATTR_SYNTAX,
|
||||
Features,
|
||||
get_features,
|
||||
GateIssue,
|
||||
emit_feature_err,
|
||||
};
|
||||
use {fold, attr};
|
||||
use ast;
|
||||
use source_map::Spanned;
|
||||
|
|
@ -73,49 +80,103 @@ impl<'a> StripUnconfigured<'a> {
|
|||
if self.in_cfg(node.attrs()) { Some(node) } else { None }
|
||||
}
|
||||
|
||||
/// Parse and expand all `cfg_attr` attributes into a list of attributes
|
||||
/// that are within each `cfg_attr` that has a true configuration predicate.
|
||||
///
|
||||
/// Gives compiler warnigns if any `cfg_attr` does not contain any
|
||||
/// attributes and is in the original source code. Gives compiler errors if
|
||||
/// the syntax of any `cfg_attr` is incorrect.
|
||||
pub fn process_cfg_attrs<T: HasAttrs>(&mut self, node: T) -> T {
|
||||
node.map_attrs(|attrs| {
|
||||
attrs.into_iter().filter_map(|attr| self.process_cfg_attr(attr)).collect()
|
||||
attrs.into_iter().flat_map(|attr| self.process_cfg_attr(attr)).collect()
|
||||
})
|
||||
}
|
||||
|
||||
fn process_cfg_attr(&mut self, attr: ast::Attribute) -> Option<ast::Attribute> {
|
||||
/// Parse and expand a single `cfg_attr` attribute into a list of attributes
|
||||
/// when the configuration predicate is true, or otherwise expand into an
|
||||
/// empty list of attributes.
|
||||
///
|
||||
/// Gives a compiler warning when the `cfg_attr` contains no attribtes and
|
||||
/// is in the original source file. Gives a compiler error if the syntax of
|
||||
/// the attribute is incorrect
|
||||
fn process_cfg_attr(&mut self, attr: ast::Attribute) -> Vec<ast::Attribute> {
|
||||
if !attr.check_name("cfg_attr") {
|
||||
return Some(attr);
|
||||
return vec![attr];
|
||||
}
|
||||
|
||||
let (cfg, path, tokens, span) = match attr.parse(self.sess, |parser| {
|
||||
let gate_cfg_attr_multi = if let Some(ref features) = self.features {
|
||||
!features.cfg_attr_multi
|
||||
} else {
|
||||
false
|
||||
};
|
||||
let cfg_attr_span = attr.span;
|
||||
|
||||
let (cfg_predicate, expanded_attrs) = match attr.parse(self.sess, |parser| {
|
||||
parser.expect(&token::OpenDelim(token::Paren))?;
|
||||
let cfg = parser.parse_meta_item()?;
|
||||
|
||||
let cfg_predicate = parser.parse_meta_item()?;
|
||||
parser.expect(&token::Comma)?;
|
||||
let lo = parser.span.lo();
|
||||
let (path, tokens) = parser.parse_meta_item_unrestricted()?;
|
||||
parser.eat(&token::Comma); // Optional trailing comma
|
||||
|
||||
// Presumably, the majority of the time there will only be one attr.
|
||||
let mut expanded_attrs = Vec::with_capacity(1);
|
||||
|
||||
while !parser.check(&token::CloseDelim(token::Paren)) {
|
||||
let lo = parser.span.lo();
|
||||
let (path, tokens) = parser.parse_meta_item_unrestricted()?;
|
||||
expanded_attrs.push((path, tokens, parser.prev_span.with_lo(lo)));
|
||||
parser.expect_one_of(&[token::Comma], &[token::CloseDelim(token::Paren)])?;
|
||||
}
|
||||
|
||||
parser.expect(&token::CloseDelim(token::Paren))?;
|
||||
Ok((cfg, path, tokens, parser.prev_span.with_lo(lo)))
|
||||
Ok((cfg_predicate, expanded_attrs))
|
||||
}) {
|
||||
Ok(result) => result,
|
||||
Err(mut e) => {
|
||||
e.emit();
|
||||
return None;
|
||||
return Vec::new();
|
||||
}
|
||||
};
|
||||
|
||||
if attr::cfg_matches(&cfg, self.sess, self.features) {
|
||||
self.process_cfg_attr(ast::Attribute {
|
||||
// Check feature gate and lint on zero attributes in source. Even if the feature is gated,
|
||||
// we still compute as if it wasn't, since the emitted error will stop compilation futher
|
||||
// along the compilation.
|
||||
match (expanded_attrs.len(), gate_cfg_attr_multi) {
|
||||
(0, false) => {
|
||||
// FIXME: Emit unused attribute lint here.
|
||||
},
|
||||
(1, _) => {},
|
||||
(_, true) => {
|
||||
emit_feature_err(
|
||||
self.sess,
|
||||
"cfg_attr_multi",
|
||||
cfg_attr_span,
|
||||
GateIssue::Language,
|
||||
"cfg_attr with zero or more than one attributes is experimental",
|
||||
);
|
||||
},
|
||||
(_, false) => {}
|
||||
}
|
||||
|
||||
if attr::cfg_matches(&cfg_predicate, self.sess, self.features) {
|
||||
// We call `process_cfg_attr` recursively in case there's a
|
||||
// `cfg_attr` inside of another `cfg_attr`. E.g.
|
||||
// `#[cfg_attr(false, cfg_attr(true, some_attr))]`.
|
||||
expanded_attrs.into_iter()
|
||||
.flat_map(|(path, tokens, span)| self.process_cfg_attr(ast::Attribute {
|
||||
id: attr::mk_attr_id(),
|
||||
style: attr.style,
|
||||
path,
|
||||
tokens,
|
||||
is_sugared_doc: false,
|
||||
span,
|
||||
})
|
||||
}))
|
||||
.collect()
|
||||
} else {
|
||||
None
|
||||
Vec::new()
|
||||
}
|
||||
}
|
||||
|
||||
// Determine if a node with the given attributes should be included in this configuration.
|
||||
/// Determine if a node with the given attributes should be included in this configuration.
|
||||
pub fn in_cfg(&mut self, attrs: &[ast::Attribute]) -> bool {
|
||||
attrs.iter().all(|attr| {
|
||||
if !is_cfg(attr) {
|
||||
|
|
@ -165,7 +226,7 @@ impl<'a> StripUnconfigured<'a> {
|
|||
})
|
||||
}
|
||||
|
||||
// Visit attributes on expression and statements (but not attributes on items in blocks).
|
||||
/// Visit attributes on expression and statements (but not attributes on items in blocks).
|
||||
fn visit_expr_attrs(&mut self, attrs: &[ast::Attribute]) {
|
||||
// flag the offending attributes
|
||||
for attr in attrs.iter() {
|
||||
|
|
|
|||
|
|
@ -433,9 +433,6 @@ declare_features! (
|
|||
// #[doc(alias = "...")]
|
||||
(active, doc_alias, "1.27.0", Some(50146), None),
|
||||
|
||||
// Scoped lints
|
||||
(active, tool_lints, "1.28.0", Some(44690), None),
|
||||
|
||||
// Allows irrefutable patterns in if-let and while-let statements (RFC 2086)
|
||||
(active, irrefutable_let_patterns, "1.27.0", Some(44495), None),
|
||||
|
||||
|
|
@ -499,6 +496,9 @@ declare_features! (
|
|||
|
||||
// Allows `impl Trait` in bindings (`let`, `const`, `static`)
|
||||
(active, impl_trait_in_bindings, "1.30.0", Some(34511), None),
|
||||
|
||||
// #[cfg_attr(predicate, multiple, attributes, here)]
|
||||
(active, cfg_attr_multi, "1.31.0", Some(54881), None),
|
||||
);
|
||||
|
||||
declare_features! (
|
||||
|
|
@ -679,6 +679,8 @@ declare_features! (
|
|||
(accepted, pattern_parentheses, "1.31.0", Some(51087), None),
|
||||
// Allows the definition of `const fn` functions.
|
||||
(accepted, min_const_fn, "1.31.0", Some(53555), None),
|
||||
// Scoped lints
|
||||
(accepted, tool_lints, "1.31.0", Some(44690), None),
|
||||
);
|
||||
|
||||
// If you change this, please modify src/doc/unstable-book as well. You must
|
||||
|
|
|
|||
|
|
@ -678,7 +678,7 @@ impl<'a> Parser<'a> {
|
|||
/// Expect next token to be edible or inedible token. If edible,
|
||||
/// then consume it; if inedible, then return without consuming
|
||||
/// anything. Signal a fatal error if next token is unexpected.
|
||||
fn expect_one_of(&mut self,
|
||||
pub fn expect_one_of(&mut self,
|
||||
edible: &[token::Token],
|
||||
inedible: &[token::Token]) -> PResult<'a, ()>{
|
||||
fn tokens_to_string(tokens: &[TokenType]) -> String {
|
||||
|
|
@ -3866,6 +3866,9 @@ impl<'a> Parser<'a> {
|
|||
// check that a comma comes after every field
|
||||
if !ate_comma {
|
||||
let err = self.struct_span_err(self.prev_span, "expected `,`");
|
||||
if let Some(mut delayed) = delayed_err {
|
||||
delayed.emit();
|
||||
}
|
||||
return Err(err);
|
||||
}
|
||||
ate_comma = false;
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@
|
|||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
#![feature(tool_lints)]
|
||||
|
||||
#![deny(unknown_lints)]
|
||||
|
||||
#[allow(clippy::almost_swapped)]
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@
|
|||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
#![feature(tool_lints)]
|
||||
|
||||
#![feature(rust_2018_preview)]
|
||||
#![deny(unknown_lints)]
|
||||
|
||||
|
|
|
|||
|
|
@ -11,8 +11,8 @@
|
|||
// aux-build:lint_tool_test.rs
|
||||
// ignore-stage1
|
||||
// compile-flags: --cfg foo
|
||||
|
||||
#![feature(plugin)]
|
||||
#![feature(tool_lints)]
|
||||
#![plugin(lint_tool_test)]
|
||||
#![allow(dead_code)]
|
||||
#![cfg_attr(foo, warn(test_lint))]
|
||||
|
|
|
|||
|
|
@ -1,13 +0,0 @@
|
|||
// compile-flags: --cfg TRUE
|
||||
|
||||
#[cfg_attr(TRUE, inline,)] // OK
|
||||
fn f() {}
|
||||
|
||||
#[cfg_attr(FALSE, inline,)] // OK
|
||||
fn g() {}
|
||||
|
||||
#[cfg_attr(TRUE, inline,,)] //~ ERROR expected `)`, found `,`
|
||||
fn h() {}
|
||||
|
||||
#[cfg_attr(FALSE, inline,,)] //~ ERROR expected `)`, found `,`
|
||||
fn i() {}
|
||||
|
|
@ -1,14 +0,0 @@
|
|||
error: expected `)`, found `,`
|
||||
--> $DIR/cfg-attr-trailing-comma.rs:9:25
|
||||
|
|
||||
LL | #[cfg_attr(TRUE, inline,,)] //~ ERROR expected `)`, found `,`
|
||||
| ^ expected `)`
|
||||
|
||||
error: expected `)`, found `,`
|
||||
--> $DIR/cfg-attr-trailing-comma.rs:12:26
|
||||
|
|
||||
LL | #[cfg_attr(FALSE, inline,,)] //~ ERROR expected `)`, found `,`
|
||||
| ^ expected `)`
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
|
|
@ -10,11 +10,12 @@
|
|||
|
||||
#![feature(rustc_attrs)]
|
||||
|
||||
trait Bar { }
|
||||
|
||||
#[rustc_dump_program_clauses] //~ ERROR program clause dump
|
||||
trait Foo<S, T, U> {
|
||||
fn s(_: S) -> S;
|
||||
fn t(_: T) -> T;
|
||||
fn u(_: U) -> U;
|
||||
trait Foo<S, T: ?Sized> {
|
||||
#[rustc_dump_program_clauses] //~ ERROR program clause dump
|
||||
type Assoc: Bar + ?Sized;
|
||||
}
|
||||
|
||||
fn main() {
|
||||
|
|
|
|||
|
|
@ -1,14 +1,23 @@
|
|||
error: program clause dump
|
||||
--> $DIR/lower_trait.rs:13:1
|
||||
--> $DIR/lower_trait.rs:15:1
|
||||
|
|
||||
LL | #[rustc_dump_program_clauses] //~ ERROR program clause dump
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: FromEnv(S: std::marker::Sized) :- FromEnv(Self: Foo<S, T, U>).
|
||||
= note: FromEnv(T: std::marker::Sized) :- FromEnv(Self: Foo<S, T, U>).
|
||||
= note: FromEnv(U: std::marker::Sized) :- FromEnv(Self: Foo<S, T, U>).
|
||||
= note: Implemented(Self: Foo<S, T, U>) :- FromEnv(Self: Foo<S, T, U>).
|
||||
= note: WellFormed(Self: Foo<S, T, U>) :- Implemented(Self: Foo<S, T, U>), WellFormed(S: std::marker::Sized), WellFormed(T: std::marker::Sized), WellFormed(U: std::marker::Sized).
|
||||
= note: FromEnv(<Self as Foo<S, T>>::Assoc: Bar) :- FromEnv(Self: Foo<S, T>).
|
||||
= note: FromEnv(S: std::marker::Sized) :- FromEnv(Self: Foo<S, T>).
|
||||
= note: Implemented(Self: Foo<S, T>) :- FromEnv(Self: Foo<S, T>).
|
||||
= note: WellFormed(Self: Foo<S, T>) :- Implemented(Self: Foo<S, T>), WellFormed(S: std::marker::Sized), WellFormed(<Self as Foo<S, T>>::Assoc: Bar).
|
||||
|
||||
error: aborting due to previous error
|
||||
error: program clause dump
|
||||
--> $DIR/lower_trait.rs:17:5
|
||||
|
|
||||
LL | #[rustc_dump_program_clauses] //~ ERROR program clause dump
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: FromEnv(Self: Foo<S, T>) :- FromEnv(Unnormalized(<Self as Foo<S, T>>::Assoc)).
|
||||
= note: ProjectionEq(<Self as Foo<S, T>>::Assoc == Unnormalized(<Self as Foo<S, T>>::Assoc)).
|
||||
= note: WellFormed(Unnormalized(<Self as Foo<S, T>>::Assoc)) :- Implemented(Self: Foo<S, T>).
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ error[E0658]: no_core is experimental (see issue #29639)
|
|||
--> $DIR/cfg-attr-crate-2.rs:15:21
|
||||
|
|
||||
LL | #![cfg_attr(broken, no_core)] //~ ERROR no_core is experimental
|
||||
| ^^^^^^^^
|
||||
| ^^^^^^^
|
||||
|
|
||||
= help: add #![feature(no_core)] to the crate attributes to enable
|
||||
|
||||
20
src/test/ui/conditional-compilation/cfg-attr-multi-false.rs
Normal file
20
src/test/ui/conditional-compilation/cfg-attr-multi-false.rs
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
// Test that cfg_attr doesn't emit any attributes when the
|
||||
// configuation variable is false. This mirrors `cfg-attr-multi-true.rs`
|
||||
|
||||
// compile-pass
|
||||
|
||||
#![warn(unused_must_use)]
|
||||
#![feature(cfg_attr_multi)]
|
||||
|
||||
#[cfg_attr(any(), deprecated, must_use)]
|
||||
struct Struct {}
|
||||
|
||||
impl Struct {
|
||||
fn new() -> Struct {
|
||||
Struct {}
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
Struct::new();
|
||||
}
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
|
||||
// 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.
|
||||
//
|
||||
|
|
@ -7,6 +7,10 @@
|
|||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
//
|
||||
// compile-flags: --cfg broken
|
||||
|
||||
#[warn(clippy::assign_ops)] //~ ERROR scoped lint `clippy::assign_ops` is experimental
|
||||
fn main() {}
|
||||
#![feature(cfg_attr_multi)]
|
||||
#![cfg_attr(broken, no_core, no_std)] //~ ERROR no_core is experimental
|
||||
|
||||
fn main() { }
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
error[E0658]: no_core is experimental (see issue #29639)
|
||||
--> $DIR/cfg-attr-multi-invalid-1.rs:14:21
|
||||
|
|
||||
LL | #![cfg_attr(broken, no_core, no_std)] //~ ERROR no_core is experimental
|
||||
| ^^^^^^^
|
||||
|
|
||||
= help: add #![feature(no_core)] to the crate attributes to enable
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0658`.
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
// 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 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
//
|
||||
// compile-flags: --cfg broken
|
||||
|
||||
#![feature(cfg_attr_multi)]
|
||||
#![cfg_attr(broken, no_std, no_core)] //~ ERROR no_core is experimental
|
||||
|
||||
fn main() { }
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
error[E0658]: no_core is experimental (see issue #29639)
|
||||
--> $DIR/cfg-attr-multi-invalid-2.rs:14:29
|
||||
|
|
||||
LL | #![cfg_attr(broken, no_std, no_core)] //~ ERROR no_core is experimental
|
||||
| ^^^^^^^
|
||||
|
|
||||
= help: add #![feature(no_core)] to the crate attributes to enable
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0658`.
|
||||
22
src/test/ui/conditional-compilation/cfg-attr-multi-true.rs
Normal file
22
src/test/ui/conditional-compilation/cfg-attr-multi-true.rs
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
// Test that cfg_attr with multiple attributes actually emits both attributes.
|
||||
// This is done by emitting two attributes that cause new warnings, and then
|
||||
// triggering those warnings.
|
||||
|
||||
// compile-pass
|
||||
|
||||
#![warn(unused_must_use)]
|
||||
#![feature(cfg_attr_multi)]
|
||||
|
||||
#[cfg_attr(all(), deprecated, must_use)]
|
||||
struct MustUseDeprecated {}
|
||||
|
||||
impl MustUseDeprecated { //~ warning: use of deprecated item
|
||||
fn new() -> MustUseDeprecated { //~ warning: use of deprecated item
|
||||
MustUseDeprecated {} //~ warning: use of deprecated item
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
MustUseDeprecated::new(); //~ warning: use of deprecated item
|
||||
//| warning: unused `MustUseDeprecated` which must be used
|
||||
}
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
warning: use of deprecated item 'MustUseDeprecated'
|
||||
--> $DIR/cfg-attr-multi-true.rs:13:6
|
||||
|
|
||||
LL | impl MustUseDeprecated { //~ warning: use of deprecated item
|
||||
| ^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: #[warn(deprecated)] on by default
|
||||
|
||||
warning: use of deprecated item 'MustUseDeprecated'
|
||||
--> $DIR/cfg-attr-multi-true.rs:20:5
|
||||
|
|
||||
LL | MustUseDeprecated::new(); //~ warning: use of deprecated item
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
warning: use of deprecated item 'MustUseDeprecated'
|
||||
--> $DIR/cfg-attr-multi-true.rs:14:17
|
||||
|
|
||||
LL | fn new() -> MustUseDeprecated { //~ warning: use of deprecated item
|
||||
| ^^^^^^^^^^^^^^^^^
|
||||
|
||||
warning: use of deprecated item 'MustUseDeprecated'
|
||||
--> $DIR/cfg-attr-multi-true.rs:15:9
|
||||
|
|
||||
LL | MustUseDeprecated {} //~ warning: use of deprecated item
|
||||
| ^^^^^^^^^^^^^^^^^
|
||||
|
||||
warning: unused `MustUseDeprecated` which must be used
|
||||
--> $DIR/cfg-attr-multi-true.rs:20:5
|
||||
|
|
||||
LL | MustUseDeprecated::new(); //~ warning: use of deprecated item
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
note: lint level defined here
|
||||
--> $DIR/cfg-attr-multi-true.rs:7:9
|
||||
|
|
||||
LL | #![warn(unused_must_use)]
|
||||
| ^^^^^^^^^^^^^^^
|
||||
|
||||
45
src/test/ui/conditional-compilation/cfg-attr-parse.rs
Normal file
45
src/test/ui/conditional-compilation/cfg-attr-parse.rs
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
// Parse `cfg_attr` with varying numbers of attributes and trailing commas
|
||||
|
||||
#![feature(cfg_attr_multi)]
|
||||
|
||||
// Completely empty `cfg_attr` input
|
||||
#[cfg_attr()] //~ error: expected identifier, found `)`
|
||||
struct NoConfigurationPredicate;
|
||||
|
||||
// Zero attributes, zero trailing comma (comma manatory here)
|
||||
#[cfg_attr(all())] //~ error: expected `,`, found `)`
|
||||
struct A0C0;
|
||||
|
||||
// Zero attributes, one trailing comma
|
||||
#[cfg_attr(all(),)] // Ok
|
||||
struct A0C1;
|
||||
|
||||
// Zero attributes, two trailing commas
|
||||
#[cfg_attr(all(),,)] //~ ERROR expected identifier
|
||||
struct A0C2;
|
||||
|
||||
// One attribute, no trailing comma
|
||||
#[cfg_attr(all(), must_use)] // Ok
|
||||
struct A1C0;
|
||||
|
||||
// One attribute, one trailing comma
|
||||
#[cfg_attr(all(), must_use,)] // Ok
|
||||
struct A1C1;
|
||||
|
||||
// One attribute, two trailing commas
|
||||
#[cfg_attr(all(), must_use,,)] //~ ERROR expected identifier
|
||||
struct A1C2;
|
||||
|
||||
// Two attributes, no trailing comma
|
||||
#[cfg_attr(all(), must_use, deprecated)] // Ok
|
||||
struct A2C0;
|
||||
|
||||
// Two attributes, one trailing comma
|
||||
#[cfg_attr(all(), must_use, deprecated,)] // Ok
|
||||
struct A2C1;
|
||||
|
||||
// Two attributes, two trailing commas
|
||||
#[cfg_attr(all(), must_use, deprecated,,)] //~ ERROR expected identifier
|
||||
struct A2C2;
|
||||
|
||||
fn main() {}
|
||||
32
src/test/ui/conditional-compilation/cfg-attr-parse.stderr
Normal file
32
src/test/ui/conditional-compilation/cfg-attr-parse.stderr
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
error: expected identifier, found `)`
|
||||
--> $DIR/cfg-attr-parse.rs:6:12
|
||||
|
|
||||
LL | #[cfg_attr()] //~ error: expected identifier, found `)`
|
||||
| ^ expected identifier
|
||||
|
||||
error: expected `,`, found `)`
|
||||
--> $DIR/cfg-attr-parse.rs:10:17
|
||||
|
|
||||
LL | #[cfg_attr(all())] //~ error: expected `,`, found `)`
|
||||
| ^ expected `,`
|
||||
|
||||
error: expected identifier, found `,`
|
||||
--> $DIR/cfg-attr-parse.rs:18:18
|
||||
|
|
||||
LL | #[cfg_attr(all(),,)] //~ ERROR expected identifier
|
||||
| ^ expected identifier
|
||||
|
||||
error: expected identifier, found `,`
|
||||
--> $DIR/cfg-attr-parse.rs:30:28
|
||||
|
|
||||
LL | #[cfg_attr(all(), must_use,,)] //~ ERROR expected identifier
|
||||
| ^ expected identifier
|
||||
|
||||
error: expected identifier, found `,`
|
||||
--> $DIR/cfg-attr-parse.rs:42:40
|
||||
|
|
||||
LL | #[cfg_attr(all(), must_use, deprecated,,)] //~ ERROR expected identifier
|
||||
| ^ expected identifier
|
||||
|
||||
error: aborting due to 5 previous errors
|
||||
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
// gate-test-cfg_attr_multi
|
||||
|
||||
#![cfg_attr(all(), warn(nonstandard_style), allow(unused_attributes))]
|
||||
//~^ ERROR cfg_attr with zero or more than one attributes is experimental
|
||||
fn main() {}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
error[E0658]: cfg_attr with zero or more than one attributes is experimental (see issue #54881)
|
||||
--> $DIR/feature-gate-cfg-attr-multi-1.rs:3:1
|
||||
|
|
||||
LL | #![cfg_attr(all(), warn(nonstandard_style), allow(unused_attributes))]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= help: add #![feature(cfg_attr_multi)] to the crate attributes to enable
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0658`.
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
#![cfg_attr(all(),)]
|
||||
//~^ ERROR cfg_attr with zero or more than one attributes is experimental
|
||||
fn main() {}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
error[E0658]: cfg_attr with zero or more than one attributes is experimental (see issue #54881)
|
||||
--> $DIR/feature-gate-cfg-attr-multi-2.rs:1:1
|
||||
|
|
||||
LL | #![cfg_attr(all(),)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= help: add #![feature(cfg_attr_multi)] to the crate attributes to enable
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0658`.
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
// Test that settingt the featute gate while using its functionality doesn't error.
|
||||
|
||||
// compile-pass
|
||||
|
||||
#![cfg_attr(all(), feature(cfg_attr_multi), crate_type="bin")]
|
||||
|
||||
fn main() {}
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
// Test that settingt the featute gate while using its functionality doesn't error.
|
||||
// Specifically, if there's a cfg-attr *before* the feature gate.
|
||||
|
||||
// compile-pass
|
||||
|
||||
#![cfg_attr(all(),)]
|
||||
#![cfg_attr(all(), feature(cfg_attr_multi), crate_type="bin")]
|
||||
|
||||
fn main() {}
|
||||
|
|
@ -1,11 +0,0 @@
|
|||
error[E0658]: scoped lint `clippy::assign_ops` is experimental (see issue #44690)
|
||||
--> $DIR/feature-gate-tool_lints-fail.rs:11:8
|
||||
|
|
||||
LL | #[warn(clippy::assign_ops)] //~ ERROR scoped lint `clippy::assign_ops` is experimental
|
||||
| ^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= help: add #![feature(tool_lints)] to the crate attributes to enable
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0658`.
|
||||
|
|
@ -1,11 +0,0 @@
|
|||
error[E0658]: scoped lint `clippy::decimal_literal_representation` is experimental (see issue #44690)
|
||||
--> $DIR/feature-gate-tool_lints.rs:11:8
|
||||
|
|
||||
LL | #[warn(clippy::decimal_literal_representation)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= help: add #![feature(tool_lints)] to the crate attributes to enable
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0658`.
|
||||
|
|
@ -7,9 +7,15 @@
|
|||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
#[warn(clippy::decimal_literal_representation)]
|
||||
//~^ ERROR scoped lint `clippy::decimal_literal_representation` is experimental
|
||||
fn main() {
|
||||
let a = 65_535;
|
||||
struct MyStruct {
|
||||
pub s1: Option<String>,
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let thing = MyStruct { s1: None };
|
||||
|
||||
match thing {
|
||||
MyStruct { .., Some(_) } => {},
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
24
src/test/ui/resolve/issue-54379.stderr
Normal file
24
src/test/ui/resolve/issue-54379.stderr
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
error: expected `}`, found `,`
|
||||
--> $DIR/issue-54379.rs:18:22
|
||||
|
|
||||
LL | MyStruct { .., Some(_) } => {},
|
||||
| --^
|
||||
| | |
|
||||
| | expected `}`
|
||||
| `..` must be at the end and cannot have a trailing comma
|
||||
|
||||
error: expected `,`
|
||||
--> $DIR/issue-54379.rs:18:24
|
||||
|
|
||||
LL | MyStruct { .., Some(_) } => {},
|
||||
| ^^^^
|
||||
|
||||
error[E0027]: pattern does not mention field `s1`
|
||||
--> $DIR/issue-54379.rs:18:9
|
||||
|
|
||||
LL | MyStruct { .., Some(_) } => {},
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^ missing field `s1`
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0027`.
|
||||
|
|
@ -10,7 +10,7 @@
|
|||
|
||||
// Don't allow tool_lints, which aren't scoped
|
||||
|
||||
#![feature(tool_lints)]
|
||||
|
||||
#![deny(unknown_lints)]
|
||||
|
||||
#![deny(clippy)] //~ ERROR: unknown lint: `clippy`
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@
|
|||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
#![feature(tool_lints)]
|
||||
|
||||
|
||||
#[warn(foo::bar)]
|
||||
//~^ ERROR an unknown tool name found in scoped lint: `foo::bar`
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@
|
|||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
#![feature(tool_lints)]
|
||||
|
||||
|
||||
#![deny(foo::bar)] //~ ERROR an unknown tool name found in scoped lint: `foo::bar`
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue