Skip to content

Commit c859c4f

Browse files
committed
Auto merge of #51432 - pietroalbini:beta-backports, r=kennytm
[beta] Rollup backports Merged and accepted: * #51417: Revert #49719 * #51283: Deny #[cfg] and #[cfg_attr] on generic parameters * #51328: Do not promote union field accesses r? @ghost
2 parents eb01d0f + 6bf3078 commit c859c4f

16 files changed

+346
-127
lines changed

src/librustc_mir/transform/qualify_consts.rs

+8-2
Original file line numberDiff line numberDiff line change
@@ -556,8 +556,14 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> {
556556

557557
ProjectionElem::Field(..) |
558558
ProjectionElem::Index(_) => {
559-
if this.mode != Mode::Fn &&
560-
this.qualif.intersects(Qualif::STATIC) {
559+
if this.mode == Mode::Fn {
560+
let base_ty = proj.base.ty(this.mir, this.tcx).to_ty(this.tcx);
561+
if let Some(def) = base_ty.ty_adt_def() {
562+
if def.is_union() {
563+
this.not_const();
564+
}
565+
}
566+
} else if this.qualif.intersects(Qualif::STATIC) {
561567
span_err!(this.tcx.sess, this.span, E0494,
562568
"cannot refer to the interior of another \
563569
static, use a constant instead");

src/librustc_passes/rvalue_promotion.rs

+9-2
Original file line numberDiff line numberDiff line change
@@ -424,9 +424,16 @@ fn check_expr<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>, e: &hir::Expr, node
424424
}
425425
}
426426

427-
hir::ExprBlock(_) |
427+
hir::ExprField(ref expr, _) => {
428+
if let Some(def) = v.tables.expr_ty(expr).ty_adt_def() {
429+
if def.is_union() {
430+
v.promotable = false
431+
}
432+
}
433+
}
434+
435+
hir::ExprBlock(..) |
428436
hir::ExprIndex(..) |
429-
hir::ExprField(..) |
430437
hir::ExprArray(_) |
431438
hir::ExprType(..) |
432439
hir::ExprTup(..) => {}

src/libsyntax/attr.rs

+18-2
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ pub use self::IntType::*;
1717
use ast;
1818
use ast::{AttrId, Attribute, Name, Ident, Path, PathSegment};
1919
use ast::{MetaItem, MetaItemKind, NestedMetaItem, NestedMetaItemKind};
20-
use ast::{Lit, LitKind, Expr, ExprKind, Item, Local, Stmt, StmtKind};
20+
use ast::{Lit, LitKind, Expr, ExprKind, Item, Local, Stmt, StmtKind, GenericParam};
2121
use codemap::{BytePos, Spanned, respan, dummy_spanned};
2222
use syntax_pos::Span;
2323
use errors::Handler;
@@ -1438,6 +1438,22 @@ impl HasAttrs for Stmt {
14381438
}
14391439
}
14401440

1441+
impl HasAttrs for GenericParam {
1442+
fn attrs(&self) -> &[ast::Attribute] {
1443+
match self {
1444+
GenericParam::Lifetime(lifetime) => lifetime.attrs(),
1445+
GenericParam::Type(ty) => ty.attrs(),
1446+
}
1447+
}
1448+
1449+
fn map_attrs<F: FnOnce(Vec<Attribute>) -> Vec<Attribute>>(self, f: F) -> Self {
1450+
match self {
1451+
GenericParam::Lifetime(lifetime) => GenericParam::Lifetime(lifetime.map_attrs(f)),
1452+
GenericParam::Type(ty) => GenericParam::Type(ty.map_attrs(f)),
1453+
}
1454+
}
1455+
}
1456+
14411457
macro_rules! derive_has_attrs {
14421458
($($ty:path),*) => { $(
14431459
impl HasAttrs for $ty {
@@ -1457,5 +1473,5 @@ macro_rules! derive_has_attrs {
14571473

14581474
derive_has_attrs! {
14591475
Item, Expr, Local, ast::ForeignItem, ast::StructField, ast::ImplItem, ast::TraitItem, ast::Arm,
1460-
ast::Field, ast::FieldPat, ast::Variant_
1476+
ast::Field, ast::FieldPat, ast::Variant_, ast::LifetimeDef, ast::TyParam
14611477
}

src/libsyntax/config.rs

+16
Original file line numberDiff line numberDiff line change
@@ -278,6 +278,22 @@ impl<'a> StripUnconfigured<'a> {
278278
pattern
279279
})
280280
}
281+
282+
// deny #[cfg] on generic parameters until we decide what to do with it.
283+
// see issue #51279.
284+
pub fn disallow_cfg_on_generic_param(&mut self, param: &ast::GenericParam) {
285+
for attr in param.attrs() {
286+
let offending_attr = if attr.check_name("cfg") {
287+
"cfg"
288+
} else if attr.check_name("cfg_attr") {
289+
"cfg_attr"
290+
} else {
291+
continue;
292+
};
293+
let msg = format!("#[{}] cannot be applied on a generic parameter", offending_attr);
294+
self.sess.span_diagnostic.span_err(attr.span, &msg);
295+
}
296+
}
281297
}
282298

283299
impl<'a> fold::Folder for StripUnconfigured<'a> {

src/libsyntax/ext/expand.rs

+5
Original file line numberDiff line numberDiff line change
@@ -1350,6 +1350,11 @@ impl<'a, 'b> Folder for InvocationCollector<'a, 'b> {
13501350
}
13511351
}
13521352

1353+
fn fold_generic_param(&mut self, param: ast::GenericParam) -> ast::GenericParam {
1354+
self.cfg.disallow_cfg_on_generic_param(&param);
1355+
noop_fold_generic_param(param, self)
1356+
}
1357+
13531358
fn fold_attribute(&mut self, at: ast::Attribute) -> Option<ast::Attribute> {
13541359
// turn `#[doc(include="filename")]` attributes into `#[doc(include(file="filename",
13551360
// contents="file contents")]` attributes

src/libsyntax/ext/tt/quoted.rs

+67-22
Original file line numberDiff line numberDiff line change
@@ -386,26 +386,72 @@ where
386386
{
387387
// We basically look at two token trees here, denoted as #1 and #2 below
388388
let span = match parse_kleene_op(input, span) {
389-
// #1 is any KleeneOp (`?`)
390-
Ok(Ok(op)) if op == KleeneOp::ZeroOrOne => {
391-
if !features.macro_at_most_once_rep
392-
&& !attr::contains_name(attrs, "allow_internal_unstable")
393-
{
394-
let explain = feature_gate::EXPLAIN_MACRO_AT_MOST_ONCE_REP;
395-
emit_feature_err(
396-
sess,
397-
"macro_at_most_once_rep",
398-
span,
399-
GateIssue::Language,
400-
explain,
401-
);
389+
// #1 is a `+` or `*` KleeneOp
390+
//
391+
// `?` is ambiguous: it could be a separator or a Kleene::ZeroOrOne, so we need to look
392+
// ahead one more token to be sure.
393+
Ok(Ok(op)) if op != KleeneOp::ZeroOrOne => return (None, op),
394+
395+
// #1 is `?` token, but it could be a Kleene::ZeroOrOne without a separator or it could
396+
// be a `?` separator followed by any Kleene operator. We need to look ahead 1 token to
397+
// find out which.
398+
Ok(Ok(op)) => {
399+
assert_eq!(op, KleeneOp::ZeroOrOne);
400+
401+
// Lookahead at #2. If it is a KleenOp, then #1 is a separator.
402+
let is_1_sep = if let Some(&tokenstream::TokenTree::Token(_, ref tok2)) = input.peek() {
403+
kleene_op(tok2).is_some()
404+
} else {
405+
false
406+
};
407+
408+
if is_1_sep {
409+
// #1 is a separator and #2 should be a KleepeOp::*
410+
// (N.B. We need to advance the input iterator.)
411+
match parse_kleene_op(input, span) {
412+
// #2 is a KleeneOp (this is the only valid option) :)
413+
Ok(Ok(op)) if op == KleeneOp::ZeroOrOne => {
414+
if !features.macro_at_most_once_rep
415+
&& !attr::contains_name(attrs, "allow_internal_unstable")
416+
{
417+
let explain = feature_gate::EXPLAIN_MACRO_AT_MOST_ONCE_REP;
418+
emit_feature_err(
419+
sess,
420+
"macro_at_most_once_rep",
421+
span,
422+
GateIssue::Language,
423+
explain,
424+
);
425+
}
426+
return (Some(token::Question), op);
427+
}
428+
Ok(Ok(op)) => return (Some(token::Question), op),
429+
430+
// #2 is a random token (this is an error) :(
431+
Ok(Err((_, span))) => span,
432+
433+
// #2 is not even a token at all :(
434+
Err(span) => span,
435+
}
436+
} else {
437+
if !features.macro_at_most_once_rep
438+
&& !attr::contains_name(attrs, "allow_internal_unstable")
439+
{
440+
let explain = feature_gate::EXPLAIN_MACRO_AT_MOST_ONCE_REP;
441+
emit_feature_err(
442+
sess,
443+
"macro_at_most_once_rep",
444+
span,
445+
GateIssue::Language,
446+
explain,
447+
);
448+
}
449+
450+
// #2 is a random tree and #1 is KleeneOp::ZeroOrOne
451+
return (None, op);
402452
}
403-
return (None, op);
404453
}
405454

406-
// #1 is any KleeneOp (`+`, `*`)
407-
Ok(Ok(op)) => return (None, op),
408-
409455
// #1 is a separator followed by #2, a KleeneOp
410456
Ok(Err((tok, span))) => match parse_kleene_op(input, span) {
411457
// #2 is a KleeneOp :D
@@ -421,11 +467,8 @@ where
421467
GateIssue::Language,
422468
explain,
423469
);
424-
} else {
425-
sess.span_diagnostic
426-
.span_err(span, "`?` macro repetition does not allow a separator");
427470
}
428-
return (None, op);
471+
return (Some(tok), op);
429472
}
430473
Ok(Ok(op)) => return (Some(tok), op),
431474

@@ -440,7 +483,9 @@ where
440483
Err(span) => span,
441484
};
442485

443-
if !features.macro_at_most_once_rep && !attr::contains_name(attrs, "allow_internal_unstable") {
486+
if !features.macro_at_most_once_rep
487+
&& !attr::contains_name(attrs, "allow_internal_unstable")
488+
{
444489
sess.span_diagnostic
445490
.span_err(span, "expected one of: `*`, `+`, or `?`");
446491
} else {

src/libsyntax/feature_gate.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -586,7 +586,7 @@ declare_features! (
586586
// allow `'_` placeholder lifetimes
587587
(accepted, underscore_lifetimes, "1.26.0", Some(44524), None),
588588
// Allows attributes on lifetime/type formal parameters in generics (RFC 1327)
589-
(accepted, generic_param_attrs, "1.26.0", Some(48848), None),
589+
(accepted, generic_param_attrs, "1.27.0", Some(48848), None),
590590
// Allows cfg(target_feature = "...").
591591
(accepted, cfg_target_feature, "1.27.0", Some(29717), None),
592592
// Allows #[target_feature(...)]

src/test/run-pass/ctfe/union-ice.rs

-45
This file was deleted.

src/test/run-pass/macro-at-most-once-rep.rs

+23-6
Original file line numberDiff line numberDiff line change
@@ -32,13 +32,25 @@ macro_rules! foo {
3232
} }
3333
}
3434

35+
macro_rules! baz {
36+
($($a:ident),? ; $num:expr) => { { // comma separator is meaningless for `?`
37+
let mut x = 0;
38+
39+
$(
40+
x += $a;
41+
)?
42+
43+
assert_eq!(x, $num);
44+
} }
45+
}
46+
3547
macro_rules! barplus {
3648
($($a:ident)?+ ; $num:expr) => { {
3749
let mut x = 0;
3850

3951
$(
4052
x += $a;
41-
)?
53+
)+
4254

4355
assert_eq!(x, $num);
4456
} }
@@ -50,7 +62,7 @@ macro_rules! barstar {
5062

5163
$(
5264
x += $a;
53-
)?
65+
)*
5466

5567
assert_eq!(x, $num);
5668
} }
@@ -62,10 +74,15 @@ pub fn main() {
6274
// accept 0 or 1 repetitions
6375
foo!( ; 0);
6476
foo!(a ; 1);
77+
baz!( ; 0);
78+
baz!(a ; 1);
6579

6680
// Make sure using ? as a separator works as before
67-
barplus!(+ ; 0);
68-
barplus!(a + ; 1);
69-
barstar!(* ; 0);
70-
barstar!(a * ; 1);
81+
barplus!(a ; 1);
82+
barplus!(a?a ; 2);
83+
barplus!(a?a?a ; 3);
84+
barstar!( ; 0);
85+
barstar!(a ; 1);
86+
barstar!(a?a ; 2);
87+
barstar!(a?a?a ; 3);
7188
}

src/test/run-pass/union/union-const-eval-field.rs

+11-3
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010

1111
#![feature(const_fn)]
1212

13-
type Field1 = i32;
13+
type Field1 = (i32, u32);
1414
type Field2 = f32;
1515
type Field3 = i64;
1616

@@ -21,7 +21,7 @@ union DummyUnion {
2121
}
2222

2323
const FLOAT1_AS_I32: i32 = 1065353216;
24-
const UNION: DummyUnion = DummyUnion { field1: FLOAT1_AS_I32 };
24+
const UNION: DummyUnion = DummyUnion { field1: (FLOAT1_AS_I32, 0) };
2525

2626
const fn read_field1() -> Field1 {
2727
const FIELD1: Field1 = unsafe { UNION.field1 };
@@ -39,7 +39,15 @@ const fn read_field3() -> Field3 {
3939
}
4040

4141
fn main() {
42-
assert_eq!(read_field1(), FLOAT1_AS_I32);
42+
let foo = FLOAT1_AS_I32;
43+
assert_eq!(read_field1().0, foo);
44+
assert_eq!(read_field1().0, FLOAT1_AS_I32);
45+
46+
let foo = 1.0;
47+
assert_eq!(read_field2(), foo);
4348
assert_eq!(read_field2(), 1.0);
49+
4450
assert_eq!(read_field3(), unsafe { UNION.field3 });
51+
let foo = unsafe { UNION.field3 };
52+
assert_eq!(read_field3(), foo);
4553
}
+22
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
#![allow(const_err)]
12+
13+
union Foo {
14+
a: &'static u32,
15+
b: usize,
16+
}
17+
18+
fn main() {
19+
let x: &'static bool = &unsafe { //~ borrowed value does not live long enough
20+
Foo { a: &1 }.b == Foo { a: &2 }.b
21+
};
22+
}

0 commit comments

Comments
 (0)