diff --git a/src/liballoc/str.rs b/src/liballoc/str.rs index e5d4e1c533c7b..f66ff894ae865 100644 --- a/src/liballoc/str.rs +++ b/src/liballoc/str.rs @@ -28,7 +28,7 @@ // It's cleaner to just turn off the unused_imports warning than to fix them. #![allow(unused_imports)] -use core::borrow::Borrow; +use core::borrow::{Borrow, BorrowMut}; use core::str::pattern::{Pattern, Searcher, ReverseSearcher, DoubleEndedSearcher}; use core::mem; use core::ptr; @@ -190,6 +190,14 @@ impl Borrow for String { } } +#[stable(feature = "string_borrow_mut", since = "1.36.0")] +impl BorrowMut for String { + #[inline] + fn borrow_mut(&mut self) -> &mut str { + &mut self[..] + } +} + #[stable(feature = "rust1", since = "1.0.0")] impl ToOwned for str { type Owned = String; diff --git a/src/libprofiler_builtins/build.rs b/src/libprofiler_builtins/build.rs index ff52a03d9dd97..1df5c4a6d6de3 100644 --- a/src/libprofiler_builtins/build.rs +++ b/src/libprofiler_builtins/build.rs @@ -44,6 +44,19 @@ fn main() { cfg.define("COMPILER_RT_HAS_UNAME", Some("1")); } + // Assume that the Unixes we are building this for have fnctl() available + if env::var_os("CARGO_CFG_UNIX").is_some() { + cfg.define("COMPILER_RT_HAS_FCNTL_LCK", Some("1")); + } + + // This should be a pretty good heuristic for when to set + // COMPILER_RT_HAS_ATOMICS + if env::var_os("CARGO_CFG_TARGET_HAS_ATOMIC").map(|features| { + features.to_string_lossy().to_lower_case().contains("cas") + }).unwrap_or(false) { + cfg.define("COMPILER_RT_HAS_ATOMICS", Some("1")); + } + // The source for `compiler-rt` comes from the `compiler-builtins` crate, so // load our env var set by cargo to find the source code. let root = env::var_os("DEP_COMPILER_RT_COMPILER_RT").unwrap(); diff --git a/src/librustc/arena.rs b/src/librustc/arena.rs index 1cc6500d0384f..b48d81f2ef8f4 100644 --- a/src/librustc/arena.rs +++ b/src/librustc/arena.rs @@ -144,6 +144,14 @@ impl<'tcx> Arena<'tcx> { } } + #[inline] + pub fn alloc_slice(&self, value: &[T]) -> &mut [T] { + if value.len() == 0 { + return &mut [] + } + self.dropless.alloc_slice(value) + } + pub fn alloc_from_iter< T: ArenaAllocatable, I: IntoIterator diff --git a/src/librustc/cfg/construct.rs b/src/librustc/cfg/construct.rs index 8a4594fe0e89e..2592af7d4ad5a 100644 --- a/src/librustc/cfg/construct.rs +++ b/src/librustc/cfg/construct.rs @@ -369,7 +369,7 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> { hir::ExprKind::AddrOf(_, ref e) | hir::ExprKind::Cast(ref e, _) | hir::ExprKind::Type(ref e, _) | - hir::ExprKind::Use(ref e) | + hir::ExprKind::DropTemps(ref e) | hir::ExprKind::Unary(_, ref e) | hir::ExprKind::Field(ref e, _) | hir::ExprKind::Yield(ref e) | diff --git a/src/librustc/hir/intravisit.rs b/src/librustc/hir/intravisit.rs index 3d727f7cd9128..0c73d97394fda 100644 --- a/src/librustc/hir/intravisit.rs +++ b/src/librustc/hir/intravisit.rs @@ -1029,7 +1029,7 @@ pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr) { visitor.visit_expr(subexpression); visitor.visit_ty(typ) } - ExprKind::Use(ref subexpression) => { + ExprKind::DropTemps(ref subexpression) => { visitor.visit_expr(subexpression); } ExprKind::If(ref head_expression, ref if_block, ref optional_else) => { diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index df455a725c5ba..42597be2c6f91 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -4671,7 +4671,7 @@ impl<'a> LoweringContext<'a> { // The construct was introduced in #21984. // FIXME(60253): Is this still necessary? // Also, add the attributes to the outer returned expr node. - return self.expr_use(head_sp, match_expr, e.attrs.clone()) + return self.expr_drop_temps(head_sp, match_expr, e.attrs.clone()) } // Desugar `ExprKind::Try` @@ -5030,15 +5030,19 @@ impl<'a> LoweringContext<'a> { ) } - /// Wrap the given `expr` in `hir::ExprKind::Use`. + /// Wrap the given `expr` in a terminating scope using `hir::ExprKind::DropTemps`. /// - /// In terms of drop order, it has the same effect as - /// wrapping `expr` in `{ let _t = $expr; _t }` but - /// should provide better compile-time performance. + /// In terms of drop order, it has the same effect as wrapping `expr` in + /// `{ let _t = $expr; _t }` but should provide better compile-time performance. /// /// The drop order can be important in e.g. `if expr { .. }`. - fn expr_use(&mut self, span: Span, expr: P, attrs: ThinVec) -> hir::Expr { - self.expr(span, hir::ExprKind::Use(expr), attrs) + fn expr_drop_temps( + &mut self, + span: Span, + expr: P, + attrs: ThinVec + ) -> hir::Expr { + self.expr(span, hir::ExprKind::DropTemps(expr), attrs) } fn expr_match( diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs index 8418658ab6878..5a2807ac93d85 100644 --- a/src/librustc/hir/mod.rs +++ b/src/librustc/hir/mod.rs @@ -1366,7 +1366,7 @@ impl Expr { ExprKind::Unary(..) => ExprPrecedence::Unary, ExprKind::Lit(_) => ExprPrecedence::Lit, ExprKind::Type(..) | ExprKind::Cast(..) => ExprPrecedence::Cast, - ExprKind::Use(ref expr, ..) => expr.precedence(), + ExprKind::DropTemps(ref expr, ..) => expr.precedence(), ExprKind::If(..) => ExprPrecedence::If, ExprKind::While(..) => ExprPrecedence::While, ExprKind::Loop(..) => ExprPrecedence::Loop, @@ -1438,7 +1438,7 @@ impl Expr { ExprKind::Binary(..) | ExprKind::Yield(..) | ExprKind::Cast(..) | - ExprKind::Use(..) | + ExprKind::DropTemps(..) | ExprKind::Err => { false } @@ -1488,10 +1488,12 @@ pub enum ExprKind { Cast(P, P), /// A type reference (e.g., `Foo`). Type(P, P), - /// Semantically equivalent to `{ let _t = expr; _t }`. - /// Maps directly to `hair::ExprKind::Use`. - /// Only exists to tweak the drop order in HIR. - Use(P), + /// Wraps the expression in a terminating scope. + /// This makes it semantically equivalent to `{ let _t = expr; _t }`. + /// + /// This construct only exists to tweak the drop order in HIR lowering. + /// An example of that is the desugaring of `for` loops. + DropTemps(P), /// An `if` block, with an optional else block. /// /// I.e., `if { } else { }`. diff --git a/src/librustc/hir/print.rs b/src/librustc/hir/print.rs index 06225364f6c70..54816316f0bf5 100644 --- a/src/librustc/hir/print.rs +++ b/src/librustc/hir/print.rs @@ -1388,7 +1388,7 @@ impl<'a> State<'a> { self.word_space(":")?; self.print_type(&ty)?; } - hir::ExprKind::Use(ref init) => { + hir::ExprKind::DropTemps(ref init) => { // Print `{`: self.cbox(indent_unit)?; self.ibox(0)?; diff --git a/src/librustc/middle/expr_use_visitor.rs b/src/librustc/middle/expr_use_visitor.rs index 6900be55769e1..ebc80c272135b 100644 --- a/src/librustc/middle/expr_use_visitor.rs +++ b/src/librustc/middle/expr_use_visitor.rs @@ -520,7 +520,7 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> { self.consume_expr(&base); } - hir::ExprKind::Use(ref expr) => { + hir::ExprKind::DropTemps(ref expr) => { self.consume_expr(&expr); } diff --git a/src/librustc/middle/liveness.rs b/src/librustc/middle/liveness.rs index 966bec8381ae7..2ae53a5df3a86 100644 --- a/src/librustc/middle/liveness.rs +++ b/src/librustc/middle/liveness.rs @@ -521,7 +521,7 @@ fn visit_expr<'a, 'tcx>(ir: &mut IrMaps<'a, 'tcx>, expr: &'tcx Expr) { hir::ExprKind::Binary(..) | hir::ExprKind::AddrOf(..) | hir::ExprKind::Cast(..) | - hir::ExprKind::Use(..) | + hir::ExprKind::DropTemps(..) | hir::ExprKind::Unary(..) | hir::ExprKind::Break(..) | hir::ExprKind::Continue(_) | @@ -1222,7 +1222,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { hir::ExprKind::AddrOf(_, ref e) | hir::ExprKind::Cast(ref e, _) | hir::ExprKind::Type(ref e, _) | - hir::ExprKind::Use(ref e) | + hir::ExprKind::DropTemps(ref e) | hir::ExprKind::Unary(_, ref e) | hir::ExprKind::Yield(ref e) | hir::ExprKind::Repeat(ref e, _) => { @@ -1526,7 +1526,7 @@ fn check_expr<'a, 'tcx>(this: &mut Liveness<'a, 'tcx>, expr: &'tcx Expr) { hir::ExprKind::Match(..) | hir::ExprKind::While(..) | hir::ExprKind::Loop(..) | hir::ExprKind::Index(..) | hir::ExprKind::Field(..) | hir::ExprKind::Array(..) | hir::ExprKind::Tup(..) | hir::ExprKind::Binary(..) | - hir::ExprKind::Cast(..) | hir::ExprKind::Use(..) | hir::ExprKind::Unary(..) | + hir::ExprKind::Cast(..) | hir::ExprKind::DropTemps(..) | hir::ExprKind::Unary(..) | hir::ExprKind::Ret(..) | hir::ExprKind::Break(..) | hir::ExprKind::Continue(..) | hir::ExprKind::Lit(_) | hir::ExprKind::Block(..) | hir::ExprKind::AddrOf(..) | hir::ExprKind::Struct(..) | hir::ExprKind::Repeat(..) | diff --git a/src/librustc/middle/mem_categorization.rs b/src/librustc/middle/mem_categorization.rs index 6ca1e0ea84ac0..b6df7f2326a49 100644 --- a/src/librustc/middle/mem_categorization.rs +++ b/src/librustc/middle/mem_categorization.rs @@ -677,7 +677,7 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> { hir::ExprKind::Assign(..) | hir::ExprKind::AssignOp(..) | hir::ExprKind::Closure(..) | hir::ExprKind::Ret(..) | hir::ExprKind::Unary(..) | hir::ExprKind::Yield(..) | - hir::ExprKind::MethodCall(..) | hir::ExprKind::Cast(..) | hir::ExprKind::Use(..) | + hir::ExprKind::MethodCall(..) | hir::ExprKind::Cast(..) | hir::ExprKind::DropTemps(..) | hir::ExprKind::Array(..) | hir::ExprKind::Tup(..) | hir::ExprKind::If(..) | hir::ExprKind::Binary(..) | hir::ExprKind::While(..) | hir::ExprKind::Block(..) | hir::ExprKind::Loop(..) | hir::ExprKind::Match(..) | diff --git a/src/librustc/middle/region.rs b/src/librustc/middle/region.rs index f9491a1e8f4e6..2b88f273adce4 100644 --- a/src/librustc/middle/region.rs +++ b/src/librustc/middle/region.rs @@ -908,8 +908,8 @@ fn resolve_expr<'a, 'tcx>(visitor: &mut RegionResolutionVisitor<'a, 'tcx>, expr: visitor.cx.var_parent = visitor.cx.parent; } - hir::ExprKind::Use(ref expr) => { - // `Use(expr)` does not denote a conditional scope. + hir::ExprKind::DropTemps(ref expr) => { + // `DropTemps(expr)` does not denote a conditional scope. // Rather, we want to achieve the same behavior as `{ let _t = expr; _t }`. terminating(expr.hir_id.local_id); } diff --git a/src/librustc/query/mod.rs b/src/librustc/query/mod.rs index eaf9fd1bc7659..b96ef1b7a869b 100644 --- a/src/librustc/query/mod.rs +++ b/src/librustc/query/mod.rs @@ -245,13 +245,13 @@ rustc_queries! { /// Get a map with the variance of every item; use `item_variance` /// instead. - query crate_variances(_: CrateNum) -> Lrc { + query crate_variances(_: CrateNum) -> Lrc> { desc { "computing the variances for items in this crate" } } /// Maps from def-id of a type or region parameter to its /// (inferred) variance. - query variances_of(_: DefId) -> Lrc> {} + query variances_of(_: DefId) -> &'tcx [ty::Variance] {} } TypeChecking { diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index 69532b9b2c4ef..6b938ea2fccdc 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -332,15 +332,11 @@ pub enum Variance { /// `tcx.variances_of()` to get the variance for a *particular* /// item. #[derive(HashStable)] -pub struct CrateVariancesMap { +pub struct CrateVariancesMap<'tcx> { /// For each item with generics, maps to a vector of the variance /// of its generics. If an item has no generics, it will have no /// entry. - pub variances: FxHashMap>>, - - /// An empty vector, useful for cloning. - #[stable_hasher(ignore)] - pub empty_variance: Lrc>, + pub variances: FxHashMap, } impl Variance { diff --git a/src/librustc/ty/relate.rs b/src/librustc/ty/relate.rs index 1f5a39cbef14e..2638a1c7c8808 100644 --- a/src/librustc/ty/relate.rs +++ b/src/librustc/ty/relate.rs @@ -60,7 +60,7 @@ pub trait TypeRelation<'a, 'gcx: 'a+'tcx, 'tcx: 'a> : Sized { b_subst); let opt_variances = self.tcx().variances_of(item_def_id); - relate_substs(self, Some(&opt_variances), a_subst, b_subst) + relate_substs(self, Some(opt_variances), a_subst, b_subst) } /// Switch variance for the purpose of relating `a` and `b`. @@ -122,7 +122,7 @@ impl<'tcx> Relate<'tcx> for ty::TypeAndMut<'tcx> { } pub fn relate_substs<'a, 'gcx, 'tcx, R>(relation: &mut R, - variances: Option<&Vec>, + variances: Option<&[ty::Variance]>, a_subst: SubstsRef<'tcx>, b_subst: SubstsRef<'tcx>) -> RelateResult<'tcx, SubstsRef<'tcx>> diff --git a/src/librustc_metadata/cstore_impl.rs b/src/librustc_metadata/cstore_impl.rs index 53f06baaa9dd7..b3439e4c9708f 100644 --- a/src/librustc_metadata/cstore_impl.rs +++ b/src/librustc_metadata/cstore_impl.rs @@ -106,7 +106,7 @@ provide! { <'tcx> tcx, def_id, other, cdata, let _ = cdata; tcx.calculate_dtor(def_id, &mut |_,_| Ok(())) } - variances_of => { Lrc::new(cdata.get_item_variances(def_id.index)) } + variances_of => { tcx.arena.alloc_from_iter(cdata.get_item_variances(def_id.index)) } associated_item_def_ids => { let mut result = vec![]; cdata.each_child_of_item(def_id.index, diff --git a/src/librustc_mir/hair/cx/expr.rs b/src/librustc_mir/hair/cx/expr.rs index e54a24f4df197..07701952b3221 100644 --- a/src/librustc_mir/hair/cx/expr.rs +++ b/src/librustc_mir/hair/cx/expr.rs @@ -759,7 +759,7 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, } } } - hir::ExprKind::Use(ref source) => { + hir::ExprKind::DropTemps(ref source) => { ExprKind::Use { source: source.to_ref() } } hir::ExprKind::Box(ref value) => { diff --git a/src/librustc_passes/rvalue_promotion.rs b/src/librustc_passes/rvalue_promotion.rs index ce54035fe67db..881f63e994d59 100644 --- a/src/librustc_passes/rvalue_promotion.rs +++ b/src/librustc_passes/rvalue_promotion.rs @@ -437,7 +437,7 @@ fn check_expr_kind<'a, 'tcx>( hir::ExprKind::AddrOf(_, ref expr) | hir::ExprKind::Repeat(ref expr, _) | hir::ExprKind::Type(ref expr, _) | - hir::ExprKind::Use(ref expr) => { + hir::ExprKind::DropTemps(ref expr) => { v.check_expr(&expr) } diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index f11638478923f..f6c263b98551f 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -4538,7 +4538,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { self.check_expr_eq_type(&e, ty); ty } - ExprKind::Use(ref e) => { + ExprKind::DropTemps(ref e) => { self.check_expr_with_expectation(e, expected) } ExprKind::Array(ref args) => { diff --git a/src/librustc_typeck/coherence/builtin.rs b/src/librustc_typeck/coherence/builtin.rs index c3b08569d2f1f..1be0248727d01 100644 --- a/src/librustc_typeck/coherence/builtin.rs +++ b/src/librustc_typeck/coherence/builtin.rs @@ -223,19 +223,22 @@ fn visit_implementation_of_dispatch_from_dyn<'a, 'tcx>( let fields = &def_a.non_enum_variant().fields; let coerced_fields = fields.iter().filter_map(|field| { - if tcx.type_of(field.did).is_phantom_data() { - // ignore PhantomData fields - return None - } - let ty_a = field.ty(tcx, substs_a); let ty_b = field.ty(tcx, substs_b); + + if let Ok(layout) = tcx.layout_of(param_env.and(ty_a)) { + if layout.is_zst() && layout.details.align.abi.bytes() == 1 { + // ignore ZST fields with alignment of 1 byte + return None; + } + } + if let Ok(ok) = infcx.at(&cause, param_env).eq(ty_a, ty_b) { if ok.obligations.is_empty() { create_err( "the trait `DispatchFromDyn` may only be implemented \ for structs containing the field being coerced, \ - `PhantomData` fields, and nothing else" + ZST fields with 1 byte alignment, and nothing else" ).note( &format!( "extra field `{}` of type `{}` is not allowed", diff --git a/src/librustc_typeck/variance/mod.rs b/src/librustc_typeck/variance/mod.rs index 9b9a6bace96b1..88ee1d79f5435 100644 --- a/src/librustc_typeck/variance/mod.rs +++ b/src/librustc_typeck/variance/mod.rs @@ -36,7 +36,7 @@ pub fn provide(providers: &mut Providers<'_>) { } fn crate_variances<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, crate_num: CrateNum) - -> Lrc { + -> Lrc> { assert_eq!(crate_num, LOCAL_CRATE); let mut arena = arena::TypedArena::default(); let terms_cx = terms::determine_parameters_to_be_inferred(tcx, &mut arena); @@ -45,7 +45,7 @@ fn crate_variances<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, crate_num: CrateNum) } fn variances_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, item_def_id: DefId) - -> Lrc> { + -> &'tcx [ty::Variance] { let id = tcx.hir().as_local_hir_id(item_def_id).expect("expected local def-id"); let unsupported = || { // Variance not relevant. @@ -88,6 +88,6 @@ fn variances_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, item_def_id: DefId) let crate_map = tcx.crate_variances(LOCAL_CRATE); crate_map.variances.get(&item_def_id) - .unwrap_or(&crate_map.empty_variance) - .clone() + .map(|p| *p) + .unwrap_or(&[]) } diff --git a/src/librustc_typeck/variance/solve.rs b/src/librustc_typeck/variance/solve.rs index b783bbfad16e9..8edf3c52ccc22 100644 --- a/src/librustc_typeck/variance/solve.rs +++ b/src/librustc_typeck/variance/solve.rs @@ -8,7 +8,6 @@ use rustc::hir::def_id::DefId; use rustc::ty; use rustc_data_structures::fx::FxHashMap; -use rustc_data_structures::sync::Lrc; use super::constraints::*; use super::terms::*; @@ -23,7 +22,9 @@ struct SolveContext<'a, 'tcx: 'a> { solutions: Vec, } -pub fn solve_constraints(constraints_cx: ConstraintContext<'_, '_>) -> ty::CrateVariancesMap { +pub fn solve_constraints<'tcx>( + constraints_cx: ConstraintContext<'_, 'tcx> +) -> ty::CrateVariancesMap<'tcx> { let ConstraintContext { terms_cx, constraints, .. } = constraints_cx; let mut solutions = vec![ty::Bivariant; terms_cx.inferred_terms.len()]; @@ -41,9 +42,8 @@ pub fn solve_constraints(constraints_cx: ConstraintContext<'_, '_>) -> ty::Crate }; solutions_cx.solve(); let variances = solutions_cx.create_map(); - let empty_variance = Lrc::new(Vec::new()); - ty::CrateVariancesMap { variances, empty_variance } + ty::CrateVariancesMap { variances } } impl<'a, 'tcx> SolveContext<'a, 'tcx> { @@ -78,7 +78,23 @@ impl<'a, 'tcx> SolveContext<'a, 'tcx> { } } - fn create_map(&self) -> FxHashMap>> { + fn enforce_const_invariance(&self, generics: &ty::Generics, variances: &mut [ty::Variance]) { + let tcx = self.terms_cx.tcx; + + // Make all const parameters invariant. + for param in generics.params.iter() { + if let ty::GenericParamDefKind::Const = param.kind { + variances[param.index as usize] = ty::Invariant; + } + } + + // Make all the const parameters in the parent invariant (recursively). + if let Some(def_id) = generics.parent { + self.enforce_const_invariance(tcx.generics_of(def_id), variances); + } + } + + fn create_map(&self) -> FxHashMap { let tcx = self.terms_cx.tcx; let solutions = &self.solutions; @@ -87,26 +103,21 @@ impl<'a, 'tcx> SolveContext<'a, 'tcx> { let generics = tcx.generics_of(def_id); let count = generics.count(); - let mut variances = solutions[start..(start + count)].to_vec(); - debug!("id={} variances={:?}", id, variances); + let variances = tcx.arena.alloc_slice(&solutions[start..(start + count)]); // Const parameters are always invariant. - for (idx, param) in generics.params.iter().enumerate() { - if let ty::GenericParamDefKind::Const = param.kind { - variances[idx] = ty::Invariant; - } - } + self.enforce_const_invariance(generics, variances); // Functions are permitted to have unused generic parameters: make those invariant. if let ty::FnDef(..) = tcx.type_of(def_id).sty { - for variance in &mut variances { + for variance in variances.iter_mut() { if *variance == ty::Bivariant { *variance = ty::Invariant; } } } - (def_id, Lrc::new(variances)) + (def_id, &*variances) }).collect() } diff --git a/src/libstd/sys_common/mod.rs b/src/libstd/sys_common/mod.rs index 6260c3b77ff81..78e159942643f 100644 --- a/src/libstd/sys_common/mod.rs +++ b/src/libstd/sys_common/mod.rs @@ -30,10 +30,12 @@ macro_rules! rtassert { #[allow(unused_macros)] // not used on all platforms macro_rules! rtunwrap { - ($ok:ident, $e:expr) => (if let $ok(v) = $e { - v - } else { - rtabort!(concat!("unwrap failed: ", stringify!($e))); + ($ok:ident, $e:expr) => (match $e { + $ok(v) => v, + ref err => { + let err = err.as_ref().map(|_|()); // map Ok/Some which might not be Debug + rtabort!(concat!("unwrap failed: ", stringify!($e), " = {:?}"), err) + }, }) } diff --git a/src/test/run-pass/dispatch_from_dyn_zst.rs b/src/test/run-pass/dispatch_from_dyn_zst.rs new file mode 100644 index 0000000000000..a2181336e00f5 --- /dev/null +++ b/src/test/run-pass/dispatch_from_dyn_zst.rs @@ -0,0 +1,49 @@ +#![feature(unsize, dispatch_from_dyn, never_type)] + +#![allow(dead_code)] + +use std::{ + ops::DispatchFromDyn, + marker::{Unsize, PhantomData}, +}; + +struct Zst; +struct NestedZst(PhantomData<()>, Zst); + + +struct WithUnit(Box, ()); +impl DispatchFromDyn> for WithUnit + where T: Unsize {} + +struct WithPhantom(Box, PhantomData<()>); +impl DispatchFromDyn> for WithPhantom + where T: Unsize {} + +struct WithNever(Box, !); +impl DispatchFromDyn> for WithNever + where T: Unsize {} + +struct WithZst(Box, Zst); +impl DispatchFromDyn> for WithZst + where T: Unsize {} + +struct WithNestedZst(Box, NestedZst); +impl DispatchFromDyn> for WithNestedZst + where T: Unsize {} + + +struct Generic(Box, A); +impl DispatchFromDyn> for Generic + where T: Unsize {} +impl DispatchFromDyn>> + for Generic> + where T: Unsize {} +impl DispatchFromDyn> for Generic + where T: Unsize {} +impl DispatchFromDyn> for Generic + where T: Unsize {} +impl DispatchFromDyn> for Generic + where T: Unsize {} + + +fn main() {} diff --git a/src/test/ui/invalid_dispatch_from_dyn_impls.rs b/src/test/ui/invalid_dispatch_from_dyn_impls.rs index c4716893fbc54..b7bc766fbe020 100644 --- a/src/test/ui/invalid_dispatch_from_dyn_impls.rs +++ b/src/test/ui/invalid_dispatch_from_dyn_impls.rs @@ -39,4 +39,13 @@ where T: Unsize, {} //~^^^ ERROR [E0378] +#[repr(align(64))] +struct OverAlignedZst; +struct OverAligned(Box, OverAlignedZst); + +impl DispatchFromDyn> for OverAligned + where + T: Unsize, +{} //~^^^ ERROR [E0378] + fn main() {} diff --git a/src/test/ui/invalid_dispatch_from_dyn_impls.stderr b/src/test/ui/invalid_dispatch_from_dyn_impls.stderr index bd016466300d7..6d62d4fd0711d 100644 --- a/src/test/ui/invalid_dispatch_from_dyn_impls.stderr +++ b/src/test/ui/invalid_dispatch_from_dyn_impls.stderr @@ -1,4 +1,4 @@ -error[E0378]: the trait `DispatchFromDyn` may only be implemented for structs containing the field being coerced, `PhantomData` fields, and nothing else +error[E0378]: the trait `DispatchFromDyn` may only be implemented for structs containing the field being coerced, ZST fields with 1 byte alignment, and nothing else --> $DIR/invalid_dispatch_from_dyn_impls.rs:10:1 | LL | / impl DispatchFromDyn> for WrapperWithExtraField @@ -36,6 +36,17 @@ LL | | T: Unsize, LL | | {} | |__^ -error: aborting due to 4 previous errors +error[E0378]: the trait `DispatchFromDyn` may only be implemented for structs containing the field being coerced, ZST fields with 1 byte alignment, and nothing else + --> $DIR/invalid_dispatch_from_dyn_impls.rs:46:1 + | +LL | / impl DispatchFromDyn> for OverAligned +LL | | where +LL | | T: Unsize, +LL | | {} + | |__^ + | + = note: extra field `1` of type `OverAlignedZst` is not allowed + +error: aborting due to 5 previous errors For more information about this error, try `rustc --explain E0378`.