Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[beta] Rollup backports #57236

Merged
merged 12 commits into from
Jan 1, 2019
21 changes: 20 additions & 1 deletion src/librustc/traits/object_safety.rs
Original file line number Diff line number Diff line change
Expand Up @@ -190,7 +190,26 @@ impl<'a, 'tcx> TyCtxt<'a, 'tcx, 'tcx> {
// In the case of a trait predicate, we can skip the "self" type.
data.skip_binder().input_types().skip(1).any(|t| t.has_self_ty())
}
ty::Predicate::Projection(..) |
ty::Predicate::Projection(ref data) => {
// And similarly for projections. This should be redundant with
// the previous check because any projection should have a
// matching `Trait` predicate with the same inputs, but we do
// the check to be safe.
//
// Note that we *do* allow projection *outputs* to contain
// `self` (i.e., `trait Foo: Bar<Output=Self::Result> { type Result; }`),
// we just require the user to specify *both* outputs
// in the object type (i.e., `dyn Foo<Output=(), Result=()>`).
//
// This is ALT2 in issue #56288, see that for discussion of the
// possible alternatives.
data.skip_binder()
.projection_ty
.trait_ref(self)
.input_types()
.skip(1)
.any(|t| t.has_self_ty())
}
ty::Predicate::WellFormed(..) |
ty::Predicate::ObjectSafe(..) |
ty::Predicate::TypeOutlives(..) |
Expand Down
84 changes: 52 additions & 32 deletions src/librustc/ty/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1754,17 +1754,19 @@ bitflags! {
pub struct AdtFlags: u32 {
const NO_ADT_FLAGS = 0;
const IS_ENUM = 1 << 0;
const IS_PHANTOM_DATA = 1 << 1;
const IS_FUNDAMENTAL = 1 << 2;
const IS_UNION = 1 << 3;
const IS_BOX = 1 << 4;
const IS_UNION = 1 << 1;
const IS_STRUCT = 1 << 2;
const HAS_CTOR = 1 << 3;
const IS_PHANTOM_DATA = 1 << 4;
const IS_FUNDAMENTAL = 1 << 5;
const IS_BOX = 1 << 6;
/// Indicates whether the type is an `Arc`.
const IS_ARC = 1 << 5;
const IS_ARC = 1 << 7;
/// Indicates whether the type is an `Rc`.
const IS_RC = 1 << 6;
const IS_RC = 1 << 8;
/// Indicates whether the variant list of this ADT is `#[non_exhaustive]`.
/// (i.e., this flag is never set unless this ADT is an enum).
const IS_VARIANT_LIST_NON_EXHAUSTIVE = 1 << 7;
const IS_VARIANT_LIST_NON_EXHAUSTIVE = 1 << 9;
}
}

Expand Down Expand Up @@ -2079,31 +2081,43 @@ impl<'a, 'gcx, 'tcx> AdtDef {
repr: ReprOptions) -> Self {
debug!("AdtDef::new({:?}, {:?}, {:?}, {:?})", did, kind, variants, repr);
let mut flags = AdtFlags::NO_ADT_FLAGS;

if kind == AdtKind::Enum && tcx.has_attr(did, "non_exhaustive") {
debug!("found non-exhaustive variant list for {:?}", did);
flags = flags | AdtFlags::IS_VARIANT_LIST_NON_EXHAUSTIVE;
}
flags |= match kind {
AdtKind::Enum => AdtFlags::IS_ENUM,
AdtKind::Union => AdtFlags::IS_UNION,
AdtKind::Struct => AdtFlags::IS_STRUCT,
};

if let AdtKind::Struct = kind {
let variant_def = &variants[VariantIdx::new(0)];
let def_key = tcx.def_key(variant_def.did);
match def_key.disambiguated_data.data {
DefPathData::StructCtor => flags |= AdtFlags::HAS_CTOR,
_ => (),
}
}

let attrs = tcx.get_attrs(did);
if attr::contains_name(&attrs, "fundamental") {
flags = flags | AdtFlags::IS_FUNDAMENTAL;
flags |= AdtFlags::IS_FUNDAMENTAL;
}
if Some(did) == tcx.lang_items().phantom_data() {
flags = flags | AdtFlags::IS_PHANTOM_DATA;
flags |= AdtFlags::IS_PHANTOM_DATA;
}
if Some(did) == tcx.lang_items().owned_box() {
flags = flags | AdtFlags::IS_BOX;
flags |= AdtFlags::IS_BOX;
}
if Some(did) == tcx.lang_items().arc() {
flags = flags | AdtFlags::IS_ARC;
flags |= AdtFlags::IS_ARC;
}
if Some(did) == tcx.lang_items().rc() {
flags = flags | AdtFlags::IS_RC;
}
if kind == AdtKind::Enum && tcx.has_attr(did, "non_exhaustive") {
debug!("found non-exhaustive variant list for {:?}", did);
flags = flags | AdtFlags::IS_VARIANT_LIST_NON_EXHAUSTIVE;
}
match kind {
AdtKind::Enum => flags = flags | AdtFlags::IS_ENUM,
AdtKind::Union => flags = flags | AdtFlags::IS_UNION,
AdtKind::Struct => {}
flags |= AdtFlags::IS_RC;
}

AdtDef {
did,
variants,
Expand All @@ -2114,25 +2128,25 @@ impl<'a, 'gcx, 'tcx> AdtDef {

#[inline]
pub fn is_struct(&self) -> bool {
!self.is_union() && !self.is_enum()
self.flags.contains(AdtFlags::IS_STRUCT)
}

#[inline]
pub fn is_union(&self) -> bool {
self.flags.intersects(AdtFlags::IS_UNION)
self.flags.contains(AdtFlags::IS_UNION)
}

#[inline]
pub fn is_enum(&self) -> bool {
self.flags.intersects(AdtFlags::IS_ENUM)
self.flags.contains(AdtFlags::IS_ENUM)
}

#[inline]
pub fn is_variant_list_non_exhaustive(&self) -> bool {
self.flags.intersects(AdtFlags::IS_VARIANT_LIST_NON_EXHAUSTIVE)
self.flags.contains(AdtFlags::IS_VARIANT_LIST_NON_EXHAUSTIVE)
}

/// Returns the kind of the ADT - Struct or Enum.
/// Returns the kind of the ADT.
#[inline]
pub fn adt_kind(&self) -> AdtKind {
if self.is_enum() {
Expand Down Expand Up @@ -2161,33 +2175,39 @@ impl<'a, 'gcx, 'tcx> AdtDef {
}
}

/// Returns whether this type is #[fundamental] for the purposes
/// If this function returns `true`, it implies that `is_struct` must return `true`.
#[inline]
pub fn has_ctor(&self) -> bool {
self.flags.contains(AdtFlags::HAS_CTOR)
}

/// Returns whether this type is `#[fundamental]` for the purposes
/// of coherence checking.
#[inline]
pub fn is_fundamental(&self) -> bool {
self.flags.intersects(AdtFlags::IS_FUNDAMENTAL)
self.flags.contains(AdtFlags::IS_FUNDAMENTAL)
}

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

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

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

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

/// Returns whether this type has a destructor.
Expand Down
9 changes: 7 additions & 2 deletions src/librustc_mir/interpret/memory.rs
Original file line number Diff line number Diff line change
Expand Up @@ -708,8 +708,13 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> {
relocations
.iter()
.map(|&(offset, reloc)| {
(offset + dest.offset - src.offset + (i * size * relocations.len() as u64),
reloc)
// compute offset for current repetition
let dest_offset = dest.offset + (i * size);
(
// shift offsets from source allocation to destination allocation
offset + dest_offset - src.offset,
reloc,
)
})
);
}
Expand Down
2 changes: 1 addition & 1 deletion src/librustc_mir/transform/qualify_consts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -517,7 +517,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> {

// Only allow statics (not consts) to refer to other statics.
if self.mode == Mode::Static || self.mode == Mode::StaticMut {
if context.is_mutating_use() {
if self.mode == Mode::Static && context.is_mutating_use() {
// this is not strictly necessary as miri will also bail out
// For interior mutability we can't really catch this statically as that
// goes through raw pointers and intermediate temporaries, so miri has
Expand Down
28 changes: 26 additions & 2 deletions src/librustc_typeck/astconv.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1013,15 +1013,39 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o {
let mut associated_types = BTreeSet::default();

for tr in traits::elaborate_trait_ref(tcx, principal) {
debug!("conv_object_ty_poly_trait_ref: observing object predicate `{:?}`", tr);
match tr {
ty::Predicate::Trait(pred) => {
associated_types.extend(tcx.associated_items(pred.def_id())
.filter(|item| item.kind == ty::AssociatedKind::Type)
.map(|item| item.def_id));
}
ty::Predicate::Projection(pred) => {
// Include projections defined on supertraits.
projection_bounds.push((pred, DUMMY_SP))
// A `Self` within the original bound will be substituted with a
// `TRAIT_OBJECT_DUMMY_SELF`, so check for that.
let references_self =
pred.skip_binder().ty.walk().any(|t| t == dummy_self);

// If the projection output contains `Self`, force the user to
// elaborate it explicitly to avoid a bunch of complexity.
//
// The "classicaly useful" case is the following:
// ```
// trait MyTrait: FnMut() -> <Self as MyTrait>::MyOutput {
// type MyOutput;
// }
// ```
//
// Here, the user could theoretically write `dyn MyTrait<Output=X>`,
// but actually supporting that would "expand" to an infinitely-long type
// `fix $ τ → dyn MyTrait<MyOutput=X, Output=<τ as MyTrait>::MyOutput`.
//
// Instead, we force the user to write `dyn MyTrait<MyOutput=X, Output=X>`,
// which is uglier but works. See the discussion in #56288 for alternatives.
if !references_self {
// Include projections defined on supertraits,
projection_bounds.push((pred, DUMMY_SP))
}
}
_ => ()
}
Expand Down
2 changes: 1 addition & 1 deletion src/librustc_typeck/check/callee.rs
Original file line number Diff line number Diff line change
Expand Up @@ -280,7 +280,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
Def::Local(id) | Def::Upvar(id, ..) => {
Some(self.tcx.hir.span(id))
}
_ => self.tcx.hir.span_if_local(def.def_id())
_ => def.opt_def_id().and_then(|did| self.tcx.hir.span_if_local(did)),
};
if let Some(span) = def_span {
let label = match (unit_variant, inner_callee_path) {
Expand Down
67 changes: 45 additions & 22 deletions src/librustc_typeck/check/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,8 @@ use rustc::mir::interpret::{ConstValue, GlobalId};
use rustc::ty::subst::{CanonicalUserSubsts, UnpackedKind, Subst, Substs,
UserSelfTy, UserSubsts};
use rustc::traits::{self, ObligationCause, ObligationCauseCode, TraitEngine};
use rustc::ty::{self, Ty, TyCtxt, GenericParamDefKind, Visibility, ToPredicate, RegionKind};
use rustc::ty::{self, AdtKind, Ty, TyCtxt, GenericParamDefKind, Visibility, ToPredicate,
RegionKind};
use rustc::ty::adjustment::{Adjust, Adjustment, AllowTwoPhase, AutoBorrow, AutoBorrowMutability};
use rustc::ty::fold::TypeFoldable;
use rustc::ty::query::Providers;
Expand Down Expand Up @@ -3222,8 +3223,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
return_expr_ty);
}

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

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

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

let mut new_def = def;
let (def_id, ty) = if let Def::SelfCtor(impl_def_id) = def {
let ty = self.impl_self_ty(span, impl_def_id).ty;

match ty.ty_adt_def() {
Some(adt_def) if adt_def.is_struct() => {
let variant = adt_def.non_enum_variant();
new_def = Def::StructCtor(variant.did, variant.ctor_kind);
(variant.did, self.tcx.type_of(variant.did))
}
_ => {
(impl_def_id, self.tcx.types.err)
let (def_id, ty) = match def {
Def::SelfCtor(impl_def_id) => {
let ty = self.impl_self_ty(span, impl_def_id).ty;
let adt_def = ty.ty_adt_def();

match adt_def {
Some(adt_def) if adt_def.has_ctor() => {
let variant = adt_def.non_enum_variant();
new_def = Def::StructCtor(variant.did, variant.ctor_kind);
(variant.did, self.tcx.type_of(variant.did))
}
_ => {
let mut err = self.tcx.sess.struct_span_err(span,
"the `Self` constructor can only be used with tuple or unit structs");
if let Some(adt_def) = adt_def {
match adt_def.adt_kind() {
AdtKind::Enum => {
err.note("did you mean to use one of the enum's variants?");
},
AdtKind::Struct |
AdtKind::Union => {
err.span_label(
span,
format!("did you mean `Self {{ /* fields */ }}`?"),
);
}
}
}
err.emit();

(impl_def_id, self.tcx.types.err)
}
}
}
} else {
let def_id = def.def_id();
_ => {
let def_id = def.def_id();

// The things we are substituting into the type should not contain
// escaping late-bound regions, and nor should the base type scheme.
let ty = self.tcx.type_of(def_id);
(def_id, ty)
// The things we are substituting into the type should not contain
// escaping late-bound regions, and nor should the base type scheme.
let ty = self.tcx.type_of(def_id);
(def_id, ty)
}
};

let substs = AstConv::create_substs_for_generic_args(
Expand Down
9 changes: 9 additions & 0 deletions src/test/ui/consts/promoted_regression.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
// compile-pass

fn main() {
let _ = &[("", ""); 3];
}

const FOO: &[(&str, &str)] = &[("", ""); 3];
const BAR: &[(&str, &str); 5] = &[("", ""); 5];
const BAA: &[[&str; 12]; 11] = &[[""; 12]; 11];
7 changes: 7 additions & 0 deletions src/test/ui/consts/static_mut_containing_mut_ref.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
// compile-pass

static mut STDERR_BUFFER_SPACE: [u8; 42] = [0u8; 42];

pub static mut STDERR_BUFFER: *mut [u8] = unsafe { &mut STDERR_BUFFER_SPACE };

fn main() {}
8 changes: 8 additions & 0 deletions src/test/ui/consts/static_mut_containing_mut_ref2.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
#![feature(const_let)]

static mut STDERR_BUFFER_SPACE: u8 = 0;

pub static mut STDERR_BUFFER: () = unsafe { *(&mut STDERR_BUFFER_SPACE) = 42; };
//~^ ERROR references in statics may only refer to immutable values

fn main() {}
Loading