Skip to content

Commit bab921d

Browse files
committed
Auto merge of #57236 - pietroalbini:beta-backports, r=pietroalbini
[beta] Rollup backports * #56919: Remove a wrong multiplier on relocation offset computation * #56916: Fix mutable references in `static mut` * #56863: fix trait objects with a Self-containing projection values * #56850: Fixed issue with using `Self` ctor in typedefs r? @ghost
2 parents a01b0bf + e6c5332 commit bab921d

23 files changed

+454
-66
lines changed

src/librustc/traits/object_safety.rs

+20-1
Original file line numberDiff line numberDiff line change
@@ -190,7 +190,26 @@ impl<'a, 'tcx> TyCtxt<'a, 'tcx, 'tcx> {
190190
// In the case of a trait predicate, we can skip the "self" type.
191191
data.skip_binder().input_types().skip(1).any(|t| t.has_self_ty())
192192
}
193-
ty::Predicate::Projection(..) |
193+
ty::Predicate::Projection(ref data) => {
194+
// And similarly for projections. This should be redundant with
195+
// the previous check because any projection should have a
196+
// matching `Trait` predicate with the same inputs, but we do
197+
// the check to be safe.
198+
//
199+
// Note that we *do* allow projection *outputs* to contain
200+
// `self` (i.e., `trait Foo: Bar<Output=Self::Result> { type Result; }`),
201+
// we just require the user to specify *both* outputs
202+
// in the object type (i.e., `dyn Foo<Output=(), Result=()>`).
203+
//
204+
// This is ALT2 in issue #56288, see that for discussion of the
205+
// possible alternatives.
206+
data.skip_binder()
207+
.projection_ty
208+
.trait_ref(self)
209+
.input_types()
210+
.skip(1)
211+
.any(|t| t.has_self_ty())
212+
}
194213
ty::Predicate::WellFormed(..) |
195214
ty::Predicate::ObjectSafe(..) |
196215
ty::Predicate::TypeOutlives(..) |

src/librustc/ty/mod.rs

+52-32
Original file line numberDiff line numberDiff line change
@@ -1754,17 +1754,19 @@ bitflags! {
17541754
pub struct AdtFlags: u32 {
17551755
const NO_ADT_FLAGS = 0;
17561756
const IS_ENUM = 1 << 0;
1757-
const IS_PHANTOM_DATA = 1 << 1;
1758-
const IS_FUNDAMENTAL = 1 << 2;
1759-
const IS_UNION = 1 << 3;
1760-
const IS_BOX = 1 << 4;
1757+
const IS_UNION = 1 << 1;
1758+
const IS_STRUCT = 1 << 2;
1759+
const HAS_CTOR = 1 << 3;
1760+
const IS_PHANTOM_DATA = 1 << 4;
1761+
const IS_FUNDAMENTAL = 1 << 5;
1762+
const IS_BOX = 1 << 6;
17611763
/// Indicates whether the type is an `Arc`.
1762-
const IS_ARC = 1 << 5;
1764+
const IS_ARC = 1 << 7;
17631765
/// Indicates whether the type is an `Rc`.
1764-
const IS_RC = 1 << 6;
1766+
const IS_RC = 1 << 8;
17651767
/// Indicates whether the variant list of this ADT is `#[non_exhaustive]`.
17661768
/// (i.e., this flag is never set unless this ADT is an enum).
1767-
const IS_VARIANT_LIST_NON_EXHAUSTIVE = 1 << 7;
1769+
const IS_VARIANT_LIST_NON_EXHAUSTIVE = 1 << 9;
17681770
}
17691771
}
17701772

@@ -2079,31 +2081,43 @@ impl<'a, 'gcx, 'tcx> AdtDef {
20792081
repr: ReprOptions) -> Self {
20802082
debug!("AdtDef::new({:?}, {:?}, {:?}, {:?})", did, kind, variants, repr);
20812083
let mut flags = AdtFlags::NO_ADT_FLAGS;
2084+
2085+
if kind == AdtKind::Enum && tcx.has_attr(did, "non_exhaustive") {
2086+
debug!("found non-exhaustive variant list for {:?}", did);
2087+
flags = flags | AdtFlags::IS_VARIANT_LIST_NON_EXHAUSTIVE;
2088+
}
2089+
flags |= match kind {
2090+
AdtKind::Enum => AdtFlags::IS_ENUM,
2091+
AdtKind::Union => AdtFlags::IS_UNION,
2092+
AdtKind::Struct => AdtFlags::IS_STRUCT,
2093+
};
2094+
2095+
if let AdtKind::Struct = kind {
2096+
let variant_def = &variants[VariantIdx::new(0)];
2097+
let def_key = tcx.def_key(variant_def.did);
2098+
match def_key.disambiguated_data.data {
2099+
DefPathData::StructCtor => flags |= AdtFlags::HAS_CTOR,
2100+
_ => (),
2101+
}
2102+
}
2103+
20822104
let attrs = tcx.get_attrs(did);
20832105
if attr::contains_name(&attrs, "fundamental") {
2084-
flags = flags | AdtFlags::IS_FUNDAMENTAL;
2106+
flags |= AdtFlags::IS_FUNDAMENTAL;
20852107
}
20862108
if Some(did) == tcx.lang_items().phantom_data() {
2087-
flags = flags | AdtFlags::IS_PHANTOM_DATA;
2109+
flags |= AdtFlags::IS_PHANTOM_DATA;
20882110
}
20892111
if Some(did) == tcx.lang_items().owned_box() {
2090-
flags = flags | AdtFlags::IS_BOX;
2112+
flags |= AdtFlags::IS_BOX;
20912113
}
20922114
if Some(did) == tcx.lang_items().arc() {
2093-
flags = flags | AdtFlags::IS_ARC;
2115+
flags |= AdtFlags::IS_ARC;
20942116
}
20952117
if Some(did) == tcx.lang_items().rc() {
2096-
flags = flags | AdtFlags::IS_RC;
2097-
}
2098-
if kind == AdtKind::Enum && tcx.has_attr(did, "non_exhaustive") {
2099-
debug!("found non-exhaustive variant list for {:?}", did);
2100-
flags = flags | AdtFlags::IS_VARIANT_LIST_NON_EXHAUSTIVE;
2101-
}
2102-
match kind {
2103-
AdtKind::Enum => flags = flags | AdtFlags::IS_ENUM,
2104-
AdtKind::Union => flags = flags | AdtFlags::IS_UNION,
2105-
AdtKind::Struct => {}
2118+
flags |= AdtFlags::IS_RC;
21062119
}
2120+
21072121
AdtDef {
21082122
did,
21092123
variants,
@@ -2114,25 +2128,25 @@ impl<'a, 'gcx, 'tcx> AdtDef {
21142128

21152129
#[inline]
21162130
pub fn is_struct(&self) -> bool {
2117-
!self.is_union() && !self.is_enum()
2131+
self.flags.contains(AdtFlags::IS_STRUCT)
21182132
}
21192133

21202134
#[inline]
21212135
pub fn is_union(&self) -> bool {
2122-
self.flags.intersects(AdtFlags::IS_UNION)
2136+
self.flags.contains(AdtFlags::IS_UNION)
21232137
}
21242138

21252139
#[inline]
21262140
pub fn is_enum(&self) -> bool {
2127-
self.flags.intersects(AdtFlags::IS_ENUM)
2141+
self.flags.contains(AdtFlags::IS_ENUM)
21282142
}
21292143

21302144
#[inline]
21312145
pub fn is_variant_list_non_exhaustive(&self) -> bool {
2132-
self.flags.intersects(AdtFlags::IS_VARIANT_LIST_NON_EXHAUSTIVE)
2146+
self.flags.contains(AdtFlags::IS_VARIANT_LIST_NON_EXHAUSTIVE)
21332147
}
21342148

2135-
/// Returns the kind of the ADT - Struct or Enum.
2149+
/// Returns the kind of the ADT.
21362150
#[inline]
21372151
pub fn adt_kind(&self) -> AdtKind {
21382152
if self.is_enum() {
@@ -2161,33 +2175,39 @@ impl<'a, 'gcx, 'tcx> AdtDef {
21612175
}
21622176
}
21632177

2164-
/// Returns whether this type is #[fundamental] for the purposes
2178+
/// If this function returns `true`, it implies that `is_struct` must return `true`.
2179+
#[inline]
2180+
pub fn has_ctor(&self) -> bool {
2181+
self.flags.contains(AdtFlags::HAS_CTOR)
2182+
}
2183+
2184+
/// Returns whether this type is `#[fundamental]` for the purposes
21652185
/// of coherence checking.
21662186
#[inline]
21672187
pub fn is_fundamental(&self) -> bool {
2168-
self.flags.intersects(AdtFlags::IS_FUNDAMENTAL)
2188+
self.flags.contains(AdtFlags::IS_FUNDAMENTAL)
21692189
}
21702190

21712191
/// Returns `true` if this is PhantomData<T>.
21722192
#[inline]
21732193
pub fn is_phantom_data(&self) -> bool {
2174-
self.flags.intersects(AdtFlags::IS_PHANTOM_DATA)
2194+
self.flags.contains(AdtFlags::IS_PHANTOM_DATA)
21752195
}
21762196

21772197
/// Returns `true` if this is `Arc<T>`.
21782198
pub fn is_arc(&self) -> bool {
2179-
self.flags.intersects(AdtFlags::IS_ARC)
2199+
self.flags.contains(AdtFlags::IS_ARC)
21802200
}
21812201

21822202
/// Returns `true` if this is `Rc<T>`.
21832203
pub fn is_rc(&self) -> bool {
2184-
self.flags.intersects(AdtFlags::IS_RC)
2204+
self.flags.contains(AdtFlags::IS_RC)
21852205
}
21862206

21872207
/// Returns `true` if this is Box<T>.
21882208
#[inline]
21892209
pub fn is_box(&self) -> bool {
2190-
self.flags.intersects(AdtFlags::IS_BOX)
2210+
self.flags.contains(AdtFlags::IS_BOX)
21912211
}
21922212

21932213
/// Returns whether this type has a destructor.

src/librustc_mir/interpret/memory.rs

+7-2
Original file line numberDiff line numberDiff line change
@@ -708,8 +708,13 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> {
708708
relocations
709709
.iter()
710710
.map(|&(offset, reloc)| {
711-
(offset + dest.offset - src.offset + (i * size * relocations.len() as u64),
712-
reloc)
711+
// compute offset for current repetition
712+
let dest_offset = dest.offset + (i * size);
713+
(
714+
// shift offsets from source allocation to destination allocation
715+
offset + dest_offset - src.offset,
716+
reloc,
717+
)
713718
})
714719
);
715720
}

src/librustc_mir/transform/qualify_consts.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -517,7 +517,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> {
517517

518518
// Only allow statics (not consts) to refer to other statics.
519519
if self.mode == Mode::Static || self.mode == Mode::StaticMut {
520-
if context.is_mutating_use() {
520+
if self.mode == Mode::Static && context.is_mutating_use() {
521521
// this is not strictly necessary as miri will also bail out
522522
// For interior mutability we can't really catch this statically as that
523523
// goes through raw pointers and intermediate temporaries, so miri has

src/librustc_typeck/astconv.rs

+26-2
Original file line numberDiff line numberDiff line change
@@ -1013,15 +1013,39 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o {
10131013
let mut associated_types = BTreeSet::default();
10141014

10151015
for tr in traits::elaborate_trait_ref(tcx, principal) {
1016+
debug!("conv_object_ty_poly_trait_ref: observing object predicate `{:?}`", tr);
10161017
match tr {
10171018
ty::Predicate::Trait(pred) => {
10181019
associated_types.extend(tcx.associated_items(pred.def_id())
10191020
.filter(|item| item.kind == ty::AssociatedKind::Type)
10201021
.map(|item| item.def_id));
10211022
}
10221023
ty::Predicate::Projection(pred) => {
1023-
// Include projections defined on supertraits.
1024-
projection_bounds.push((pred, DUMMY_SP))
1024+
// A `Self` within the original bound will be substituted with a
1025+
// `TRAIT_OBJECT_DUMMY_SELF`, so check for that.
1026+
let references_self =
1027+
pred.skip_binder().ty.walk().any(|t| t == dummy_self);
1028+
1029+
// If the projection output contains `Self`, force the user to
1030+
// elaborate it explicitly to avoid a bunch of complexity.
1031+
//
1032+
// The "classicaly useful" case is the following:
1033+
// ```
1034+
// trait MyTrait: FnMut() -> <Self as MyTrait>::MyOutput {
1035+
// type MyOutput;
1036+
// }
1037+
// ```
1038+
//
1039+
// Here, the user could theoretically write `dyn MyTrait<Output=X>`,
1040+
// but actually supporting that would "expand" to an infinitely-long type
1041+
// `fix $ τ → dyn MyTrait<MyOutput=X, Output=<τ as MyTrait>::MyOutput`.
1042+
//
1043+
// Instead, we force the user to write `dyn MyTrait<MyOutput=X, Output=X>`,
1044+
// which is uglier but works. See the discussion in #56288 for alternatives.
1045+
if !references_self {
1046+
// Include projections defined on supertraits,
1047+
projection_bounds.push((pred, DUMMY_SP))
1048+
}
10251049
}
10261050
_ => ()
10271051
}

src/librustc_typeck/check/callee.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -280,7 +280,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
280280
Def::Local(id) | Def::Upvar(id, ..) => {
281281
Some(self.tcx.hir.span(id))
282282
}
283-
_ => self.tcx.hir.span_if_local(def.def_id())
283+
_ => def.opt_def_id().and_then(|did| self.tcx.hir.span_if_local(did)),
284284
};
285285
if let Some(span) = def_span {
286286
let label = match (unit_variant, inner_callee_path) {

src/librustc_typeck/check/mod.rs

+45-22
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,8 @@ use rustc::mir::interpret::{ConstValue, GlobalId};
9898
use rustc::ty::subst::{CanonicalUserSubsts, UnpackedKind, Subst, Substs,
9999
UserSelfTy, UserSubsts};
100100
use rustc::traits::{self, ObligationCause, ObligationCauseCode, TraitEngine};
101-
use rustc::ty::{self, Ty, TyCtxt, GenericParamDefKind, Visibility, ToPredicate, RegionKind};
101+
use rustc::ty::{self, AdtKind, Ty, TyCtxt, GenericParamDefKind, Visibility, ToPredicate,
102+
RegionKind};
102103
use rustc::ty::adjustment::{Adjust, Adjustment, AllowTwoPhase, AutoBorrow, AutoBorrowMutability};
103104
use rustc::ty::fold::TypeFoldable;
104105
use rustc::ty::query::Providers;
@@ -3222,8 +3223,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
32223223
return_expr_ty);
32233224
}
32243225

3225-
// A generic function for checking the then and else in an if
3226-
// or if-else.
3226+
// A generic function for checking the 'then' and 'else' clauses in an 'if'
3227+
// or 'if-else' expression.
32273228
fn check_then_else(&self,
32283229
cond_expr: &'gcx hir::Expr,
32293230
then_expr: &'gcx hir::Expr,
@@ -3548,8 +3549,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
35483549

35493550
// we don't look at stability attributes on
35503551
// struct-like enums (yet...), but it's definitely not
3551-
// a bug to have construct one.
3552-
if adt_kind != ty::AdtKind::Enum {
3552+
// a bug to have constructed one.
3553+
if adt_kind != AdtKind::Enum {
35533554
tcx.check_stability(v_field.did, Some(expr_id), field.span);
35543555
}
35553556

@@ -5161,26 +5162,48 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
51615162
}).unwrap_or(false);
51625163

51635164
let mut new_def = def;
5164-
let (def_id, ty) = if let Def::SelfCtor(impl_def_id) = def {
5165-
let ty = self.impl_self_ty(span, impl_def_id).ty;
5166-
5167-
match ty.ty_adt_def() {
5168-
Some(adt_def) if adt_def.is_struct() => {
5169-
let variant = adt_def.non_enum_variant();
5170-
new_def = Def::StructCtor(variant.did, variant.ctor_kind);
5171-
(variant.did, self.tcx.type_of(variant.did))
5172-
}
5173-
_ => {
5174-
(impl_def_id, self.tcx.types.err)
5165+
let (def_id, ty) = match def {
5166+
Def::SelfCtor(impl_def_id) => {
5167+
let ty = self.impl_self_ty(span, impl_def_id).ty;
5168+
let adt_def = ty.ty_adt_def();
5169+
5170+
match adt_def {
5171+
Some(adt_def) if adt_def.has_ctor() => {
5172+
let variant = adt_def.non_enum_variant();
5173+
new_def = Def::StructCtor(variant.did, variant.ctor_kind);
5174+
(variant.did, self.tcx.type_of(variant.did))
5175+
}
5176+
_ => {
5177+
let mut err = self.tcx.sess.struct_span_err(span,
5178+
"the `Self` constructor can only be used with tuple or unit structs");
5179+
if let Some(adt_def) = adt_def {
5180+
match adt_def.adt_kind() {
5181+
AdtKind::Enum => {
5182+
err.note("did you mean to use one of the enum's variants?");
5183+
},
5184+
AdtKind::Struct |
5185+
AdtKind::Union => {
5186+
err.span_label(
5187+
span,
5188+
format!("did you mean `Self {{ /* fields */ }}`?"),
5189+
);
5190+
}
5191+
}
5192+
}
5193+
err.emit();
5194+
5195+
(impl_def_id, self.tcx.types.err)
5196+
}
51755197
}
51765198
}
5177-
} else {
5178-
let def_id = def.def_id();
5199+
_ => {
5200+
let def_id = def.def_id();
51795201

5180-
// The things we are substituting into the type should not contain
5181-
// escaping late-bound regions, and nor should the base type scheme.
5182-
let ty = self.tcx.type_of(def_id);
5183-
(def_id, ty)
5202+
// The things we are substituting into the type should not contain
5203+
// escaping late-bound regions, and nor should the base type scheme.
5204+
let ty = self.tcx.type_of(def_id);
5205+
(def_id, ty)
5206+
}
51845207
};
51855208

51865209
let substs = AstConv::create_substs_for_generic_args(
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
// compile-pass
2+
3+
fn main() {
4+
let _ = &[("", ""); 3];
5+
}
6+
7+
const FOO: &[(&str, &str)] = &[("", ""); 3];
8+
const BAR: &[(&str, &str); 5] = &[("", ""); 5];
9+
const BAA: &[[&str; 12]; 11] = &[[""; 12]; 11];
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
// compile-pass
2+
3+
static mut STDERR_BUFFER_SPACE: [u8; 42] = [0u8; 42];
4+
5+
pub static mut STDERR_BUFFER: *mut [u8] = unsafe { &mut STDERR_BUFFER_SPACE };
6+
7+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
#![feature(const_let)]
2+
3+
static mut STDERR_BUFFER_SPACE: u8 = 0;
4+
5+
pub static mut STDERR_BUFFER: () = unsafe { *(&mut STDERR_BUFFER_SPACE) = 42; };
6+
//~^ ERROR references in statics may only refer to immutable values
7+
//~| ERROR static contains unimplemented expression type
8+
9+
fn main() {}

0 commit comments

Comments
 (0)