Constness -> enum Const { Yes(Span), No }

Same idea for `Unsafety` & use new span for better diagnostics.
This commit is contained in:
Mazdak Farrokhzad 2020-01-30 02:42:33 +01:00
parent 2e6eaceede
commit e839b2ec84
40 changed files with 238 additions and 212 deletions

View File

@ -9,7 +9,6 @@ use crate::ty::fold::TypeFolder;
use crate::ty::{Region, RegionVid};
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use syntax::ast;
use std::collections::hash_map::Entry;
use std::collections::VecDeque;
@ -350,7 +349,7 @@ impl AutoTraitFinder<'tcx> {
already_visited.remove(&pred);
self.add_user_pred(
&mut user_computed_preds,
ty::Predicate::Trait(pred, ast::Constness::NotConst),
ty::Predicate::Trait(pred, hir::Constness::NotConst),
);
predicates.push_back(pred);
} else {

View File

@ -695,7 +695,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
let unit_obligation = Obligation {
predicate: ty::Predicate::Trait(
predicate,
ast::Constness::NotConst,
hir::Constness::NotConst,
),
..obligation.clone()
};

View File

@ -40,19 +40,19 @@ use crate::ty::fast_reject;
use crate::ty::relate::TypeRelation;
use crate::ty::subst::{Subst, SubstsRef};
use crate::ty::{self, ToPolyTraitRef, ToPredicate, Ty, TyCtxt, TypeFoldable, WithConstness};
use rustc_hir::def_id::DefId;
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_hir as hir;
use rustc_hir::def_id::DefId;
use rustc_index::bit_set::GrowableBitSet;
use rustc_span::symbol::sym;
use rustc_target::spec::abi::Abi;
use syntax::attr;
use std::cell::{Cell, RefCell};
use std::cmp;
use std::fmt::{self, Display};
use std::iter;
use std::rc::Rc;
use syntax::{ast, attr};
pub use rustc::traits::types::select::*;
@ -677,7 +677,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
// if the regions match exactly.
let cycle = stack.iter().skip(1).take_while(|s| s.depth >= cycle_depth);
let cycle = cycle.map(|stack| {
ty::Predicate::Trait(stack.obligation.predicate, ast::Constness::NotConst)
ty::Predicate::Trait(stack.obligation.predicate, hir::Constness::NotConst)
});
if self.coinductive_match(cycle) {
debug!("evaluate_stack({:?}) --> recursive, coinductive", stack.fresh_trait_ref);

View File

@ -32,6 +32,7 @@
//! looking for, and does not need to visit anything else.
use crate::ty::{self, flags::FlagComputation, Binder, Ty, TyCtxt, TypeFlags};
use rustc_hir as hir;
use rustc_hir::def_id::DefId;
use rustc_data_structures::fx::FxHashSet;
@ -150,7 +151,7 @@ pub trait TypeFoldable<'tcx>: fmt::Debug + Clone {
}
}
impl TypeFoldable<'tcx> for syntax::ast::Constness {
impl TypeFoldable<'tcx> for hir::Constness {
fn super_fold_with<F: TypeFolder<'tcx>>(&self, _: &mut F) -> Self {
*self
}

View File

@ -35,7 +35,7 @@ use rustc_data_structures::sync::{self, par_iter, Lrc, ParallelIterator};
use rustc_hir as hir;
use rustc_hir::def::{CtorKind, CtorOf, DefKind, Res};
use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, LocalDefId, CRATE_DEF_INDEX, LOCAL_CRATE};
use rustc_hir::{GlobMap, Node, TraitMap};
use rustc_hir::{Constness, GlobMap, Node, TraitMap};
use rustc_index::vec::{Idx, IndexVec};
use rustc_macros::HashStable;
use rustc_serialize::{self, Encodable, Encoder};
@ -43,7 +43,7 @@ use rustc_span::hygiene::ExpnId;
use rustc_span::symbol::{kw, sym, Symbol};
use rustc_span::Span;
use rustc_target::abi::Align;
use syntax::ast::{self, Constness, Ident, Name};
use syntax::ast::{self, Ident, Name};
use syntax::node_id::{NodeId, NodeMap, NodeSet};
use std::cell::RefCell;

View File

@ -1818,7 +1818,7 @@ define_print_and_forward_display! {
ty::Predicate<'tcx> {
match *self {
ty::Predicate::Trait(ref data, constness) => {
if let ast::Constness::Const = constness {
if let hir::Constness::Const = constness {
p!(write("const "));
}
p!(print(data))

View File

@ -7,6 +7,7 @@ use crate::mir::ProjectionKind;
use crate::ty::fold::{TypeFoldable, TypeFolder, TypeVisitor};
use crate::ty::print::{FmtPrinter, Printer};
use crate::ty::{self, InferConst, Lift, Ty, TyCtxt};
use rustc_hir as hir;
use rustc_hir::def::Namespace;
use rustc_hir::def_id::CRATE_DEF_INDEX;
use rustc_index::vec::{Idx, IndexVec};
@ -15,7 +16,6 @@ use smallvec::SmallVec;
use std::fmt;
use std::rc::Rc;
use std::sync::Arc;
use syntax::ast;
impl fmt::Debug for ty::GenericParamDef {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
@ -236,7 +236,7 @@ impl fmt::Debug for ty::Predicate<'tcx> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match *self {
ty::Predicate::Trait(ref a, constness) => {
if let ast::Constness::Const = constness {
if let hir::Constness::Const = constness {
write!(f, "const ")?;
}
a.fmt(f)

View File

@ -67,10 +67,12 @@ impl<'a> Visitor<'a> for ItemLowerer<'a, '_, '_> {
self.lctx.with_parent_item_lifetime_defs(hir_id, |this| {
let this = &mut ItemLowerer { lctx: this };
if let ItemKind::Impl { constness, ref of_trait, .. } = item.kind {
if constness == Constness::Const {
if let Const::Yes(span) = constness {
this.lctx
.diagnostic()
.span_err(item.span, "const trait impls are not yet implemented");
.struct_span_err(item.span, "const trait impls are not yet implemented")
.span_label(span, "const because of this")
.emit();
}
this.with_trait_impl_ref(of_trait, |this| visit::walk_item(this, item));
@ -413,10 +415,10 @@ impl<'hir> LoweringContext<'_, 'hir> {
});
hir::ItemKind::Impl {
unsafety,
unsafety: self.lower_unsafety(unsafety),
polarity,
defaultness: self.lower_defaultness(defaultness, true /* [1] */),
constness,
constness: self.lower_constness(constness),
generics,
of_trait: trait_ref,
self_ty: lowered_ty,
@ -430,7 +432,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
.alloc_from_iter(items.iter().map(|item| self.lower_trait_item_ref(item)));
hir::ItemKind::Trait(
is_auto,
unsafety,
self.lower_unsafety(unsafety),
self.lower_generics(generics, ImplTraitContext::disallowed()),
bounds,
items,
@ -1245,9 +1247,9 @@ impl<'hir> LoweringContext<'_, 'hir> {
fn lower_fn_header(&mut self, h: FnHeader) -> hir::FnHeader {
hir::FnHeader {
unsafety: h.unsafety,
unsafety: self.lower_unsafety(h.unsafety),
asyncness: self.lower_asyncness(h.asyncness.node),
constness: h.constness.node,
constness: self.lower_constness(h.constness),
abi: self.lower_extern(h.ext),
}
}
@ -1281,6 +1283,20 @@ impl<'hir> LoweringContext<'_, 'hir> {
}
}
fn lower_constness(&mut self, c: Const) -> hir::Constness {
match c {
Const::Yes(_) => hir::Constness::Const,
Const::No => hir::Constness::NotConst,
}
}
pub(super) fn lower_unsafety(&mut self, u: Unsafe) -> hir::Unsafety {
match u {
Unsafe::Yes(_) => hir::Unsafety::Unsafe,
Unsafe::No => hir::Unsafety::Normal,
}
}
pub(super) fn lower_generics_mut(
&mut self,
generics: &Generics,

View File

@ -1196,7 +1196,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
&NodeMap::default(),
ImplTraitContext::disallowed(),
),
unsafety: f.unsafety,
unsafety: this.lower_unsafety(f.unsafety),
abi: this.lower_extern(f.ext),
decl: this.lower_fn_decl(&f.decl, None, false, None),
param_names: this.lower_fn_params_to_names(&f.decl),

View File

@ -13,7 +13,6 @@ use rustc_parse::validate_attr;
use rustc_session::lint::builtin::PATTERNS_IN_FNS_WITHOUT_BODY;
use rustc_session::lint::LintBuffer;
use rustc_session::Session;
use rustc_span::source_map::Spanned;
use rustc_span::symbol::{kw, sym};
use rustc_span::Span;
use std::mem;
@ -234,16 +233,11 @@ impl<'a> AstValidator<'a> {
}
}
fn check_trait_fn_not_const(&self, constness: Spanned<Constness>) {
if constness.node == Constness::Const {
struct_span_err!(
self.session,
constness.span,
E0379,
"trait fns cannot be declared const"
)
.span_label(constness.span, "trait fns cannot be const")
.emit();
fn check_trait_fn_not_const(&self, constness: Const) {
if let Const::Yes(span) = constness {
struct_span_err!(self.session, span, E0379, "trait fns cannot be declared const")
.span_label(span, "trait fns cannot be const")
.emit();
}
}
@ -487,7 +481,7 @@ impl<'a> AstValidator<'a> {
(Some(FnCtxt::Foreign), _) => return,
(Some(FnCtxt::Free), Some(header)) => match header.ext {
Extern::Explicit(StrLit { symbol_unescaped: sym::C, .. }) | Extern::Implicit
if header.unsafety == Unsafety::Unsafe =>
if matches!(header.unsafety, Unsafe::Yes(_)) =>
{
return;
}
@ -514,12 +508,13 @@ impl<'a> AstValidator<'a> {
/// FIXME(const_generics): Is this really true / necessary? Discuss with @varkor.
/// At any rate, the restriction feels too syntactic. Consider moving it to e.g. typeck.
fn check_const_fn_const_generic(&self, span: Span, sig: &FnSig, generics: &Generics) {
if sig.header.constness.node == Constness::Const {
if let Const::Yes(const_span) = sig.header.constness {
// Look for const generics and error if we find any.
for param in &generics.params {
if let GenericParamKind::Const { .. } = param.kind {
self.err_handler()
.struct_span_err(span, "const parameters are not permitted in `const fn`")
.span_label(const_span, "`const fn` because of this")
.emit();
}
}
@ -754,13 +749,14 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
.help("use `auto trait Trait {}` instead")
.emit();
}
if unsafety == Unsafety::Unsafe && polarity == ImplPolarity::Negative {
if let (Unsafe::Yes(span), ImplPolarity::Negative) = (unsafety, polarity) {
struct_span_err!(
this.session,
item.span,
E0198,
"negative impls cannot be unsafe"
)
.span_label(span, "unsafe because of this")
.emit();
}
@ -782,13 +778,14 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
&item.vis,
Some("place qualifiers on individual impl items instead"),
);
if unsafety == Unsafety::Unsafe {
if let Unsafe::Yes(span) = unsafety {
struct_span_err!(
self.session,
item.span,
E0197,
"inherent impls cannot be unsafe"
)
.span_label(span, "unsafe because of this")
.emit();
}
if polarity == ImplPolarity::Negative {
@ -800,9 +797,10 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
.note("only trait implementations may be annotated with default")
.emit();
}
if constness == Constness::Const {
if let Const::Yes(span) = constness {
self.err_handler()
.struct_span_err(item.span, "inherent impls cannot be `const`")
.span_label(span, "`const` because of this")
.note("only trait implementations may be annotated with `const`")
.emit();
}

View File

@ -538,8 +538,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
match i.kind {
ast::AssocItemKind::Fn(ref sig, _) => {
let constness = sig.header.constness.node;
if let (ast::Constness::Const, AssocCtxt::Trait) = (constness, ctxt) {
if let (ast::Const::Yes(_), AssocCtxt::Trait) = (sig.header.constness, ctxt) {
gate_feature_post!(&self, const_fn, i.span, "const fn is unstable");
}
}

View File

@ -2686,7 +2686,7 @@ impl<'a> State<'a> {
crate fn print_ty_fn(
&mut self,
ext: ast::Extern,
unsafety: ast::Unsafety,
unsafety: ast::Unsafe,
decl: &ast::FnDecl,
name: Option<ast::Ident>,
generic_params: &[ast::GenericParam],
@ -2733,11 +2733,7 @@ impl<'a> State<'a> {
crate fn print_fn_header_info(&mut self, header: ast::FnHeader, vis: &ast::Visibility) {
self.s.word(visibility_qualified(vis, ""));
match header.constness.node {
ast::Constness::NotConst => {}
ast::Constness::Const => self.word_nbsp("const"),
}
self.print_constness(header.constness);
self.print_asyncness(header.asyncness.node);
self.print_unsafety(header.unsafety);
@ -2756,17 +2752,17 @@ impl<'a> State<'a> {
self.s.word("fn")
}
crate fn print_unsafety(&mut self, s: ast::Unsafety) {
crate fn print_unsafety(&mut self, s: ast::Unsafe) {
match s {
ast::Unsafety::Normal => {}
ast::Unsafety::Unsafe => self.word_nbsp("unsafe"),
ast::Unsafe::No => {}
ast::Unsafe::Yes(_) => self.word_nbsp("unsafe"),
}
}
crate fn print_constness(&mut self, s: ast::Constness) {
crate fn print_constness(&mut self, s: ast::Const) {
match s {
ast::Constness::Const => self.word_nbsp("const"),
ast::Constness::NotConst => {}
ast::Const::No => {}
ast::Const::Yes(_) => self.word_nbsp("const"),
}
}

View File

@ -700,7 +700,7 @@ impl<'a> TraitDef<'a> {
let mut a = vec![attr, unused_qual];
a.extend(self.attributes.iter().cloned());
let unsafety = if self.is_unsafe { ast::Unsafety::Unsafe } else { ast::Unsafety::Normal };
let unsafety = if self.is_unsafe { ast::Unsafe::Yes(self.span) } else { ast::Unsafe::No };
cx.item(
self.span,
@ -710,7 +710,7 @@ impl<'a> TraitDef<'a> {
unsafety,
polarity: ast::ImplPolarity::Positive,
defaultness: ast::Defaultness::Final,
constness: ast::Constness::NotConst,
constness: ast::Const::No,
generics: trait_generics,
of_trait: opt_trait_ref,
self_ty: self_type,
@ -960,7 +960,7 @@ impl<'a> MethodDef<'a> {
let fn_decl = cx.fn_decl(args, ast::FunctionRetTy::Ty(ret_type));
let body_block = cx.block_expr(body);
let unsafety = if self.is_unsafe { ast::Unsafety::Unsafe } else { ast::Unsafety::Normal };
let unsafety = if self.is_unsafe { ast::Unsafe::Yes(trait_.span) } else { ast::Unsafe::No };
let trait_lo_sp = trait_.span.shrink_to_lo();

View File

@ -157,10 +157,10 @@ fn inject_impl_of_structural_trait(
ast::Ident::invalid(),
attrs,
ItemKind::Impl {
unsafety: ast::Unsafety::Normal,
unsafety: ast::Unsafe::No,
polarity: ast::ImplPolarity::Positive,
defaultness: ast::Defaultness::Final,
constness: ast::Constness::NotConst,
constness: ast::Const::No,
generics,
of_trait: Some(trait_ref),
self_ty: self_type,

View File

@ -4,7 +4,7 @@ use rustc_expand::base::{Annotatable, ExtCtxt};
use rustc_span::symbol::{kw, sym, Symbol};
use rustc_span::Span;
use syntax::ast::{self, Attribute, Expr, FnHeader, FnSig, Generics, Ident, Param};
use syntax::ast::{ItemKind, Mutability, Stmt, Ty, TyKind, Unsafety};
use syntax::ast::{ItemKind, Mutability, Stmt, Ty, TyKind, Unsafe};
use syntax::expand::allocator::{AllocatorKind, AllocatorMethod, AllocatorTy, ALLOCATOR_METHODS};
use syntax::ptr::P;
@ -64,7 +64,7 @@ impl AllocFnFactory<'_, '_> {
let result = self.call_allocator(method.name, args);
let (output_ty, output_expr) = self.ret_ty(&method.output, result);
let decl = self.cx.fn_decl(abi_args, ast::FunctionRetTy::Ty(output_ty));
let header = FnHeader { unsafety: Unsafety::Unsafe, ..FnHeader::default() };
let header = FnHeader { unsafety: Unsafe::Yes(self.span), ..FnHeader::default() };
let sig = FnSig { decl, header };
let kind = ItemKind::Fn(sig, Generics::default(), Some(self.cx.block_expr(output_expr)));
let item = self.cx.item(

View File

@ -375,8 +375,10 @@ fn has_test_signature(cx: &ExtCtxt<'_>, i: &ast::Item) -> bool {
let has_should_panic_attr = attr::contains_name(&i.attrs, sym::should_panic);
let ref sd = cx.parse_sess.span_diagnostic;
if let ast::ItemKind::Fn(ref sig, ref generics, _) = i.kind {
if sig.header.unsafety == ast::Unsafety::Unsafe {
sd.span_err(i.span, "unsafe functions cannot be used for tests");
if let ast::Unsafe::Yes(span) = sig.header.unsafety {
sd.struct_span_err(i.span, "unsafe functions cannot be used for tests")
.span_label(span, "unsafe because of this")
.emit();
return false;
}
if sig.header.asyncness.node.is_async() {

View File

@ -19,7 +19,7 @@ use rustc_target::spec::abi::Abi;
use syntax::ast::{self, AsmDialect, CrateSugar, Ident, Name, NodeId};
use syntax::ast::{AttrVec, Attribute, FloatTy, IntTy, Label, LitKind, StrStyle, UintTy};
pub use syntax::ast::{BorrowKind, ImplPolarity, IsAuto};
pub use syntax::ast::{CaptureBy, Constness, Movability, Mutability, Unsafety};
pub use syntax::ast::{CaptureBy, Movability, Mutability};
use syntax::node_id::NodeMap;
use syntax::tokenstream::TokenStream;
use syntax::util::parser::ExprPrecedence;
@ -2109,18 +2109,8 @@ impl ImplicitSelfKind {
}
}
#[derive(
Copy,
Clone,
PartialEq,
Eq,
PartialOrd,
HashStable_Generic,
Ord,
RustcEncodable,
RustcDecodable,
Debug
)]
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, RustcEncodable, RustcDecodable, Debug)]
#[derive(HashStable_Generic)]
pub enum IsAsync {
Async,
NotAsync,
@ -2389,6 +2379,38 @@ pub struct Item<'hir> {
pub span: Span,
}
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
#[derive(RustcEncodable, RustcDecodable, HashStable_Generic)]
pub enum Unsafety {
Unsafe,
Normal,
}
impl Unsafety {
pub fn prefix_str(&self) -> &'static str {
match self {
Self::Unsafe => "unsafe ",
Self::Normal => "",
}
}
}
impl fmt::Display for Unsafety {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str(match *self {
Self::Unsafe => "unsafe",
Self::Normal => "normal",
})
}
}
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
#[derive(RustcEncodable, RustcDecodable, HashStable_Generic)]
pub enum Constness {
Const,
NotConst,
}
#[derive(Copy, Clone, RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
pub struct FnHeader {
pub unsafety: Unsafety,

View File

@ -648,7 +648,7 @@ impl<'a> State<'a> {
self.s.space();
}
if constness == ast::Constness::Const {
if let hir::Constness::Const = constness {
self.word_nbsp("const");
}

View File

@ -668,7 +668,7 @@ impl<'a, 'b> ReplaceBodyWithLoop<'a, 'b> {
}
fn is_sig_const(sig: &ast::FnSig) -> bool {
sig.header.constness.node == ast::Constness::Const
matches!(sig.header.constness, ast::Const::Yes(_))
|| ReplaceBodyWithLoop::should_ignore_fn(&sig.decl.output)
}
}

View File

@ -258,13 +258,13 @@ impl EarlyLintPass for UnsafeCode {
fn check_item(&mut self, cx: &EarlyContext<'_>, it: &ast::Item) {
match it.kind {
ast::ItemKind::Trait(_, ast::Unsafety::Unsafe, ..) => {
ast::ItemKind::Trait(_, ast::Unsafe::Yes(_), ..) => {
self.report_unsafe(cx, it.span, |lint| {
lint.build("declaration of an `unsafe` trait").emit()
})
}
ast::ItemKind::Impl { unsafety: ast::Unsafety::Unsafe, .. } => {
ast::ItemKind::Impl { unsafety: ast::Unsafe::Yes(_), .. } => {
self.report_unsafe(cx, it.span, |lint| {
lint.build("implementation of an `unsafe` trait").emit()
})
@ -278,7 +278,7 @@ impl EarlyLintPass for UnsafeCode {
if let FnKind::Fn(
ctxt,
_,
ast::FnSig { header: ast::FnHeader { unsafety: ast::Unsafety::Unsafe, .. }, .. },
ast::FnSig { header: ast::FnHeader { unsafety: ast::Unsafe::Yes(_), .. }, .. },
_,
body,
) = fk

View File

@ -32,7 +32,6 @@ use rustc_hir as hir;
use rustc_hir::def_id::DefId;
use rustc_index::vec::{Idx, IndexVec};
use rustc_span::{Span, DUMMY_SP};
use syntax::ast;
use crate::dataflow::generic::ResultsCursor;
use crate::dataflow::move_paths::MoveData;
@ -1938,7 +1937,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
tcx.mk_substs_trait(ty, &[]),
),
}),
ast::Constness::NotConst,
hir::Constness::NotConst,
),
),
&traits::SelectionError::Unimplemented,
@ -2579,7 +2578,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
self.prove_predicates(
Some(ty::Predicate::Trait(
trait_ref.to_poly_trait_ref().to_poly_trait_predicate(),
ast::Constness::NotConst,
hir::Constness::NotConst,
)),
locations,
category,

View File

@ -6,7 +6,6 @@ use rustc_hir::def_id::DefId;
use rustc_span::symbol::{sym, Symbol};
use rustc_span::Span;
use std::borrow::Cow;
use syntax::ast;
type McfResult = Result<(), (Span, Cow<'static, str>)>;
@ -35,7 +34,7 @@ pub fn is_min_const_fn(tcx: TyCtxt<'tcx>, def_id: DefId, body: &'a Body<'tcx>) -
match pred.skip_binder().self_ty().kind {
ty::Param(ref p) => {
// Allow `T: ?const Trait`
if *constness == ast::Constness::NotConst
if *constness == hir::Constness::NotConst
&& feature_allowed(tcx, def_id, sym::const_trait_bound_opt_out)
{
continue;

View File

@ -12,7 +12,7 @@ use rustc_span::BytePos;
use syntax::ast::{self, AttrKind, AttrStyle, AttrVec, Attribute, Ident, DUMMY_NODE_ID};
use syntax::ast::{AssocItem, AssocItemKind, Item, ItemKind, UseTree, UseTreeKind};
use syntax::ast::{BindingMode, Block, FnDecl, FnSig, Mac, MacArgs, MacDelimiter, Param, SelfKind};
use syntax::ast::{Constness, Defaultness, Extern, IsAsync, IsAuto, PathSegment, StrLit, Unsafety};
use syntax::ast::{Const, Defaultness, Extern, IsAsync, IsAuto, PathSegment, StrLit, Unsafe};
use syntax::ast::{EnumDef, Generics, StructField, TraitRef, Ty, TyKind, Variant, VariantData};
use syntax::ast::{FnHeader, ForeignItem, ForeignItemKind, Mutability, Visibility, VisibilityKind};
use syntax::ptr::P;
@ -107,9 +107,9 @@ impl<'a> Parser<'a> {
// EXTERN FUNCTION ITEM
let fn_span = self.prev_span;
let header = FnHeader {
unsafety: Unsafety::Normal,
unsafety: Unsafe::No,
asyncness: respan(fn_span, IsAsync::NotAsync),
constness: respan(fn_span, Constness::NotConst),
constness: Const::No,
ext: Extern::from_abi(abi),
};
return self.parse_item_fn(lo, vis, attrs, header);
@ -128,8 +128,8 @@ impl<'a> Parser<'a> {
return self.mk_item_with_info(attrs, lo, vis, info);
}
if self.eat_keyword(kw::Const) {
let const_span = self.prev_span;
let constness = self.parse_constness();
if let Const::Yes(const_span) = constness {
if [kw::Fn, kw::Unsafe, kw::Extern].iter().any(|k| self.check_keyword(*k)) {
// CONST FUNCTION ITEM
let unsafety = self.parse_unsafety();
@ -143,7 +143,7 @@ impl<'a> Parser<'a> {
let header = FnHeader {
unsafety,
asyncness: respan(const_span, IsAsync::NotAsync),
constness: respan(const_span, Constness::Const),
constness,
ext,
};
return self.parse_item_fn(lo, vis, attrs, header);
@ -175,7 +175,6 @@ impl<'a> Parser<'a> {
self.bump(); // `async`
let unsafety = self.parse_unsafety(); // `unsafe`?
self.expect_keyword(kw::Fn)?; // `fn`
let fn_span = self.prev_span;
let asyncness = respan(
async_span,
IsAsync::Async {
@ -184,20 +183,16 @@ impl<'a> Parser<'a> {
},
);
self.ban_async_in_2015(async_span);
let header = FnHeader {
unsafety,
asyncness,
constness: respan(fn_span, Constness::NotConst),
ext: Extern::None,
};
let header =
FnHeader { unsafety, asyncness, constness: Const::No, ext: Extern::None };
return self.parse_item_fn(lo, vis, attrs, header);
}
}
if self.check_keyword(kw::Unsafe) && self.is_keyword_ahead(1, &[kw::Trait, kw::Auto]) {
// UNSAFE TRAIT ITEM
self.bump(); // `unsafe`
let info = self.parse_item_trait(lo, Unsafety::Unsafe)?;
let unsafety = self.parse_unsafety();
let info = self.parse_item_trait(lo, unsafety)?;
return self.mk_item_with_info(attrs, lo, vis, info);
}
@ -218,9 +213,9 @@ impl<'a> Parser<'a> {
self.bump();
let fn_span = self.prev_span;
let header = FnHeader {
unsafety: Unsafety::Normal,
unsafety: Unsafe::No,
asyncness: respan(fn_span, IsAsync::NotAsync),
constness: respan(fn_span, Constness::NotConst),
constness: Const::No,
ext: Extern::None,
};
return self.parse_item_fn(lo, vis, attrs, header);
@ -230,16 +225,16 @@ impl<'a> Parser<'a> {
&& self.look_ahead(1, |t| *t != token::OpenDelim(token::Brace))
{
// UNSAFE FUNCTION ITEM
self.bump(); // `unsafe`
let unsafety = self.parse_unsafety();
// `{` is also expected after `unsafe`; in case of error, include it in the diagnostic.
self.check(&token::OpenDelim(token::Brace));
let ext = self.parse_extern()?;
self.expect_keyword(kw::Fn)?;
let fn_span = self.prev_span;
let header = FnHeader {
unsafety: Unsafety::Unsafe,
unsafety,
asyncness: respan(fn_span, IsAsync::NotAsync),
constness: respan(fn_span, Constness::NotConst),
constness: Const::No,
ext,
};
return self.parse_item_fn(lo, vis, attrs, header);
@ -268,7 +263,7 @@ impl<'a> Parser<'a> {
|| (self.check_keyword(kw::Auto) && self.is_keyword_ahead(1, &[kw::Trait]))
{
// TRAIT ITEM
let info = self.parse_item_trait(lo, Unsafety::Normal)?;
let info = self.parse_item_trait(lo, Unsafe::No)?;
return self.mk_item_with_info(attrs, lo, vis, info);
}
@ -547,7 +542,7 @@ impl<'a> Parser<'a> {
/// `impl` GENERICS `const`? `!`? TYPE (`where` PREDICATES)? `{` BODY `}`
fn parse_item_impl(
&mut self,
unsafety: Unsafety,
unsafety: Unsafe,
defaultness: Defaultness,
) -> PResult<'a, ItemInfo> {
// First, parse generic parameters if necessary.
@ -561,13 +556,10 @@ impl<'a> Parser<'a> {
generics
};
let constness = if self.eat_keyword(kw::Const) {
let span = self.prev_span;
let constness = self.parse_constness();
if let Const::Yes(span) = constness {
self.sess.gated_spans.gate(sym::const_trait_impl, span);
Constness::Const
} else {
Constness::NotConst
};
}
// Disambiguate `impl !Trait for Type { ... }` and `impl ! { ... }` for the never type.
let polarity = if self.check(&token::Not) && self.look_ahead(1, |t| t.can_begin_type()) {
@ -707,7 +699,7 @@ impl<'a> Parser<'a> {
}
/// Parses `auto? trait Foo { ... }` or `trait Foo = Bar;`.
fn parse_item_trait(&mut self, lo: Span, unsafety: Unsafety) -> PResult<'a, ItemInfo> {
fn parse_item_trait(&mut self, lo: Span, unsafety: Unsafe) -> PResult<'a, ItemInfo> {
// Parse optional `auto` prefix.
let is_auto = if self.eat_keyword(kw::Auto) { IsAuto::Yes } else { IsAuto::No };
@ -734,11 +726,11 @@ impl<'a> Parser<'a> {
self.expect_semi()?;
let whole_span = lo.to(self.prev_span);
if is_auto == IsAuto::Yes {
if let IsAuto::Yes = is_auto {
let msg = "trait aliases cannot be `auto`";
self.struct_span_err(whole_span, msg).span_label(whole_span, msg).emit();
}
if unsafety != Unsafety::Normal {
if let Unsafe::Yes(_) = unsafety {
let msg = "trait aliases cannot be `unsafe`";
self.struct_span_err(whole_span, msg).span_label(whole_span, msg).emit();
}
@ -1785,28 +1777,27 @@ impl<'a> Parser<'a> {
Ok(body)
}
/// Parses all the "front matter" for a `fn` declaration, up to
/// and including the `fn` keyword:
/// Parses all the "front matter" (or "qualifiers") for a `fn` declaration,
/// up to and including the `fn` keyword. The formal grammar is:
///
/// - `const fn`
/// - `unsafe fn`
/// - `const unsafe fn`
/// - `extern fn`
/// - etc.
/// ```
/// Extern = "extern" StringLit ;
/// FnQual = "const"? "async"? "unsafe"? Extern? ;
/// FnFrontMatter = FnQual? "fn" ;
/// ```
fn parse_fn_front_matter(&mut self) -> PResult<'a, FnHeader> {
let is_const_fn = self.eat_keyword(kw::Const);
let const_span = self.prev_span;
let constness = self.parse_constness();
let asyncness = self.parse_asyncness();
if let IsAsync::Async { .. } = asyncness {
self.ban_async_in_2015(self.prev_span);
}
let asyncness = respan(self.prev_span, asyncness);
let unsafety = self.parse_unsafety();
let (constness, unsafety, ext) = if is_const_fn {
(respan(const_span, Constness::Const), unsafety, Extern::None)
let (constness, unsafety, ext) = if let Const::Yes(_) = constness {
(constness, unsafety, Extern::None)
} else {
let ext = self.parse_extern()?;
(respan(self.prev_span, Constness::NotConst), unsafety, ext)
(Const::No, unsafety, ext)
};
if !self.eat_keyword(kw::Fn) {
// It is possible for `expect_one_of` to recover given the contents of

View File

@ -22,7 +22,8 @@ use rustc_session::parse::ParseSess;
use rustc_span::source_map::respan;
use rustc_span::symbol::{kw, sym, Symbol};
use rustc_span::{FileName, Span, DUMMY_SP};
use syntax::ast::{self, AttrStyle, AttrVec, CrateSugar, Extern, Ident, Unsafety, DUMMY_NODE_ID};
use syntax::ast::DUMMY_NODE_ID;
use syntax::ast::{self, AttrStyle, AttrVec, Const, CrateSugar, Extern, Ident, Unsafe};
use syntax::ast::{IsAsync, MacArgs, MacDelimiter, Mutability, StrLit, Visibility, VisibilityKind};
use syntax::ptr::P;
use syntax::token::{self, DelimToken, Token, TokenKind};
@ -962,8 +963,13 @@ impl<'a> Parser<'a> {
}
/// Parses unsafety: `unsafe` or nothing.
fn parse_unsafety(&mut self) -> Unsafety {
if self.eat_keyword(kw::Unsafe) { Unsafety::Unsafe } else { Unsafety::Normal }
fn parse_unsafety(&mut self) -> Unsafe {
if self.eat_keyword(kw::Unsafe) { Unsafe::Yes(self.prev_span) } else { Unsafe::No }
}
/// Parses constness: `const` or nothing.
fn parse_constness(&mut self) -> Const {
if self.eat_keyword(kw::Const) { Const::Yes(self.prev_span) } else { Const::No }
}
/// Parses mutability (`mut` or nothing).

View File

@ -225,7 +225,7 @@ impl Sig for ast::Ty {
text.push('>');
}
if f.unsafety == ast::Unsafety::Unsafe {
if let ast::Unsafe::Yes(_) = f.unsafety {
text.push_str("unsafe ");
}
push_extern(&mut text, f.ext);
@ -365,13 +365,13 @@ impl Sig for ast::Item {
}
ast::ItemKind::Fn(ast::FnSig { ref decl, header }, ref generics, _) => {
let mut text = String::new();
if header.constness.node == ast::Constness::Const {
if let ast::Const::Yes(_) = header.constness {
text.push_str("const ");
}
if header.asyncness.node.is_async() {
text.push_str("async ");
}
if header.unsafety == ast::Unsafety::Unsafe {
if let ast::Unsafe::Yes(_) = header.unsafety {
text.push_str("unsafe ");
}
push_extern(&mut text, header.ext);
@ -453,7 +453,7 @@ impl Sig for ast::Item {
text.push_str("auto ");
}
if unsafety == ast::Unsafety::Unsafe {
if let ast::Unsafe::Yes(_) = unsafety {
text.push_str("unsafe ");
}
text.push_str("trait ");
@ -496,11 +496,11 @@ impl Sig for ast::Item {
if let ast::Defaultness::Default = defaultness {
text.push_str("default ");
}
if unsafety == ast::Unsafety::Unsafe {
if let ast::Unsafe::Yes(_) = unsafety {
text.push_str("unsafe ");
}
text.push_str("impl");
if constness == ast::Constness::Const {
if let ast::Const::Yes(_) = constness {
text.push_str(" const");
}
@ -884,13 +884,13 @@ fn make_method_signature(
) -> Result {
// FIXME code dup with function signature
let mut text = String::new();
if m.header.constness.node == ast::Constness::Const {
if let ast::Const::Yes(_) = m.header.constness {
text.push_str("const ");
}
if m.header.asyncness.node.is_async() {
text.push_str("async ");
}
if m.header.unsafety == ast::Unsafety::Unsafe {
if let ast::Unsafe::Yes(_) = m.header.unsafety {
text.push_str("unsafe ");
}
push_extern(&mut text, m.header.ext);

View File

@ -28,12 +28,12 @@ use rustc_hir::def::{CtorOf, DefKind, Res};
use rustc_hir::def_id::DefId;
use rustc_hir::intravisit::Visitor;
use rustc_hir::print;
use rustc_hir::{ExprKind, GenericArg, GenericArgs};
use rustc_hir::{Constness, ExprKind, GenericArg, GenericArgs};
use rustc_span::symbol::sym;
use rustc_span::{MultiSpan, Span, DUMMY_SP};
use rustc_target::spec::abi;
use smallvec::SmallVec;
use syntax::ast::{self, Constness};
use syntax::ast;
use syntax::util::lev_distance::find_best_match_for_name;
use std::collections::BTreeSet;
@ -1502,7 +1502,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
.filter(|(trait_ref, _, _)| !tcx.trait_is_auto(trait_ref.def_id()));
for (base_trait_ref, span, constness) in regular_traits_refs_spans {
assert_eq!(constness, ast::Constness::NotConst);
assert_eq!(constness, Constness::NotConst);
for trait_ref in traits::elaborate_trait_ref(tcx, base_trait_ref) {
debug!(

View File

@ -2693,13 +2693,13 @@ impl<'a, 'tcx> AstConv<'tcx> for FnCtxt<'a, 'tcx> {
None
}
fn default_constness_for_trait_bounds(&self) -> ast::Constness {
fn default_constness_for_trait_bounds(&self) -> hir::Constness {
// FIXME: refactor this into a method
let node = self.tcx.hir().get(self.body_id);
if let Some(fn_like) = FnLikeNode::from_node(node) {
fn_like.constness()
} else {
ast::Constness::NotConst
hir::Constness::NotConst
}
}

View File

@ -300,11 +300,11 @@ impl AstConv<'tcx> for ItemCtxt<'tcx> {
Some(self.item_def_id)
}
fn default_constness_for_trait_bounds(&self) -> ast::Constness {
fn default_constness_for_trait_bounds(&self) -> hir::Constness {
if let Some(fn_like) = FnLikeNode::from_node(self.node()) {
fn_like.constness()
} else {
ast::Constness::NotConst
hir::Constness::NotConst
}
}
@ -2429,7 +2429,7 @@ fn explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericPredicat
match bound {
&hir::GenericBound::Trait(ref poly_trait_ref, modifier) => {
let constness = match modifier {
hir::TraitBoundModifier::MaybeConst => ast::Constness::NotConst,
hir::TraitBoundModifier::MaybeConst => hir::Constness::NotConst,
hir::TraitBoundModifier::None => constness,
hir::TraitBoundModifier::Maybe => bug!("this wasn't handled"),
};
@ -2617,13 +2617,13 @@ fn predicates_from_bound<'tcx>(
astconv: &dyn AstConv<'tcx>,
param_ty: Ty<'tcx>,
bound: &'tcx hir::GenericBound<'tcx>,
constness: ast::Constness,
constness: hir::Constness,
) -> Vec<(ty::Predicate<'tcx>, Span)> {
match *bound {
hir::GenericBound::Trait(ref tr, modifier) => {
let constness = match modifier {
hir::TraitBoundModifier::Maybe => return vec![],
hir::TraitBoundModifier::MaybeConst => ast::Constness::NotConst,
hir::TraitBoundModifier::MaybeConst => hir::Constness::NotConst,
hir::TraitBoundModifier::None => constness,
};

View File

@ -377,7 +377,7 @@ pub fn hir_trait_to_predicates<'tcx>(
&item_cx,
hir_trait,
DUMMY_SP,
syntax::ast::Constness::NotConst,
hir::Constness::NotConst,
tcx.types.err,
&mut bounds,
true,

View File

@ -203,7 +203,7 @@ pub struct Impl<'hir> {
pub unsafety: hir::Unsafety,
pub polarity: hir::ImplPolarity,
pub defaultness: hir::Defaultness,
pub constness: ast::Constness,
pub constness: hir::Constness,
pub generics: &'hir hir::Generics<'hir>,
pub trait_: &'hir Option<hir::TraitRef<'hir>>,
pub for_: &'hir hir::Ty<'hir>,

View File

@ -1863,7 +1863,7 @@ pub struct Ty {
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
pub struct BareFnTy {
pub unsafety: Unsafety,
pub unsafety: Unsafe,
pub ext: Extern,
pub generic_params: Vec<GenericParam>,
pub decl: P<FnDecl>,
@ -2101,43 +2101,11 @@ pub enum IsAuto {
No,
}
#[derive(
Copy,
Clone,
PartialEq,
Eq,
PartialOrd,
Ord,
Hash,
RustcEncodable,
RustcDecodable,
Debug,
HashStable_Generic
)]
pub enum Unsafety {
Unsafe,
Normal,
}
impl Unsafety {
pub fn prefix_str(&self) -> &'static str {
match self {
Unsafety::Unsafe => "unsafe ",
Unsafety::Normal => "",
}
}
}
impl fmt::Display for Unsafety {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Display::fmt(
match *self {
Unsafety::Normal => "normal",
Unsafety::Unsafe => "unsafe",
},
f,
)
}
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable, Debug)]
#[derive(HashStable_Generic)]
pub enum Unsafe {
Yes(Span),
No,
}
#[derive(Copy, Clone, RustcEncodable, RustcDecodable, Debug)]
@ -2162,9 +2130,9 @@ impl IsAsync {
#[derive(Copy, Clone, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable, Debug)]
#[derive(HashStable_Generic)]
pub enum Constness {
Const,
NotConst,
pub enum Const {
Yes(Span),
No,
}
/// Item defaultness.
@ -2527,9 +2495,9 @@ impl Extern {
/// included in this struct (e.g., `async unsafe fn` or `const extern "C" fn`).
#[derive(Clone, Copy, RustcEncodable, RustcDecodable, Debug)]
pub struct FnHeader {
pub unsafety: Unsafety,
pub unsafety: Unsafe,
pub asyncness: Spanned<IsAsync>,
pub constness: Spanned<Constness>,
pub constness: Const,
pub ext: Extern,
}
@ -2537,9 +2505,9 @@ impl FnHeader {
/// Does this function header have any qualifiers or is it empty?
pub fn has_qualifiers(&self) -> bool {
let Self { unsafety, asyncness, constness, ext } = self;
matches!(unsafety, Unsafety::Unsafe)
matches!(unsafety, Unsafe::Yes(_))
|| asyncness.node.is_async()
|| matches!(constness.node, Constness::Const)
|| matches!(constness, Const::Yes(_))
|| !matches!(ext, Extern::None)
}
}
@ -2547,9 +2515,9 @@ impl FnHeader {
impl Default for FnHeader {
fn default() -> FnHeader {
FnHeader {
unsafety: Unsafety::Normal,
unsafety: Unsafe::No,
asyncness: dummy_spanned(IsAsync::NotAsync),
constness: dummy_spanned(Constness::NotConst),
constness: Const::No,
ext: Extern::None,
}
}
@ -2606,7 +2574,7 @@ pub enum ItemKind {
/// A trait declaration (`trait`).
///
/// E.g., `trait Foo { .. }`, `trait Foo<T> { .. }` or `auto trait Foo {}`.
Trait(IsAuto, Unsafety, Generics, GenericBounds, Vec<P<AssocItem>>),
Trait(IsAuto, Unsafe, Generics, GenericBounds, Vec<P<AssocItem>>),
/// Trait alias
///
/// E.g., `trait Foo = Bar + Quux;`.
@ -2615,10 +2583,10 @@ pub enum ItemKind {
///
/// E.g., `impl<A> Foo<A> { .. }` or `impl<A> Trait for Foo<A> { .. }`.
Impl {
unsafety: Unsafety,
unsafety: Unsafe,
polarity: ImplPolarity,
defaultness: Defaultness,
constness: Constness,
constness: Const,
generics: Generics,
/// The trait being implemented, if any.

View File

@ -2,7 +2,9 @@ error[E0198]: negative impls cannot be unsafe
--> $DIR/coherence-negative-impls-safe.rs:7:1
|
LL | unsafe impl !Send for TestType {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| ------^^^^^^^^^^^^^^^^^^^^^^^^^^^
| |
| unsafe because of this
error: aborting due to previous error

View File

@ -1,7 +1,11 @@
error: const parameters are not permitted in `const fn`
--> $DIR/const-fn-with-const-param.rs:4:1
|
LL | / const fn const_u32_identity<const X: u32>() -> u32 {
LL | const fn const_u32_identity<const X: u32>() -> u32 {
| ^----
| |
| _`const fn` because of this
| |
LL | |
LL | | X
LL | | }

View File

@ -2,7 +2,9 @@ error[E0197]: inherent impls cannot be unsafe
--> $DIR/E0197.rs:3:1
|
LL | unsafe impl Foo { }
| ^^^^^^^^^^^^^^^^^^^
| ------^^^^^^^^^^^^^
| |
| unsafe because of this
error: aborting due to previous error

View File

@ -2,7 +2,9 @@ error[E0198]: negative impls cannot be unsafe
--> $DIR/E0198.rs:5:1
|
LL | unsafe impl !Send for Foo { }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| ------^^^^^^^^^^^^^^^^^^^^^^^
| |
| unsafe because of this
error: aborting due to previous error

View File

@ -2,7 +2,9 @@ error: const trait impls are not yet implemented
--> $DIR/feature-gate.rs:9:1
|
LL | impl const T for S {}
| ^^^^^^^^^^^^^^^^^^^^^
| ^^^^^-----^^^^^^^^^^^
| |
| const because of this
error: aborting due to previous error

View File

@ -11,7 +11,9 @@ error: const trait impls are not yet implemented
--> $DIR/feature-gate.rs:9:1
|
LL | impl const T for S {}
| ^^^^^^^^^^^^^^^^^^^^^
| ^^^^^-----^^^^^^^^^^^
| |
| const because of this
error: aborting due to 2 previous errors

View File

@ -2,7 +2,9 @@ error: inherent impls cannot be `const`
--> $DIR/inherent-impl.rs:9:1
|
LL | impl const S {}
| ^^^^^^^^^^^^^^^
| ^^^^^-----^^^^^
| |
| `const` because of this
|
= note: only trait implementations may be annotated with `const`
@ -10,7 +12,9 @@ error: inherent impls cannot be `const`
--> $DIR/inherent-impl.rs:13:1
|
LL | impl const T {}
| ^^^^^^^^^^^^^^^
| ^^^^^-----^^^^^
| |
| `const` because of this
|
= note: only trait implementations may be annotated with `const`
@ -18,13 +22,17 @@ error: const trait impls are not yet implemented
--> $DIR/inherent-impl.rs:9:1
|
LL | impl const S {}
| ^^^^^^^^^^^^^^^
| ^^^^^-----^^^^^
| |
| const because of this
error: const trait impls are not yet implemented
--> $DIR/inherent-impl.rs:13:1
|
LL | impl const T {}
| ^^^^^^^^^^^^^^^
| ^^^^^-----^^^^^
| |
| const because of this
error: aborting due to 4 previous errors

View File

@ -8,7 +8,9 @@ error[E0198]: negative impls cannot be unsafe
--> $DIR/syntax-trait-polarity.rs:12:1
|
LL | unsafe impl !Send for TestType {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| ------^^^^^^^^^^^^^^^^^^^^^^^^^^^
| |
| unsafe because of this
error: inherent impls cannot be negative
--> $DIR/syntax-trait-polarity.rs:19:1
@ -20,7 +22,9 @@ error[E0198]: negative impls cannot be unsafe
--> $DIR/syntax-trait-polarity.rs:22:1
|
LL | unsafe impl<T> !Send for TestType2<T> {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| ------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| |
| unsafe because of this
error[E0192]: negative impls are only allowed for auto traits (e.g., `Send` and `Sync`)
--> $DIR/syntax-trait-polarity.rs:14:1

View File

@ -1,7 +1,11 @@
error[E0197]: inherent impls cannot be unsafe
--> $DIR/trait-safety-inherent-impl.rs:5:1
|
LL | / unsafe impl SomeStruct {
LL | unsafe impl SomeStruct {
| ^-----
| |
| _unsafe because of this
| |
LL | | fn foo(self) { }
LL | | }
| |_^