Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit fa64cc8

Browse files
committedJan 1, 2019
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 + 1cf854f commit fa64cc8

23 files changed

+446
-66
lines changed
 

‎src/librustc/traits/object_safety.rs

Lines changed: 20 additions & 1 deletion
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

Lines changed: 52 additions & 32 deletions
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

Lines changed: 7 additions & 2 deletions
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

Lines changed: 1 addition & 1 deletion
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

Lines changed: 26 additions & 2 deletions
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

Lines changed: 1 addition & 1 deletion
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

Lines changed: 45 additions & 22 deletions
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(
Lines changed: 9 additions & 0 deletions
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];
Lines changed: 7 additions & 0 deletions
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() {}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
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+
8+
fn main() {}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
error[E0017]: references in statics may only refer to immutable values
2+
--> $DIR/static_mut_containing_mut_ref2.rs:5:46
3+
|
4+
LL | pub static mut STDERR_BUFFER: () = unsafe { *(&mut STDERR_BUFFER_SPACE) = 42; };
5+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ statics require immutable values
6+
7+
error: aborting due to previous error
8+
9+
For more information about this error, try `rustc --explain E0017`.
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
#![feature(const_let)]
2+
3+
static mut FOO: (u8, u8) = (42, 43);
4+
5+
static mut BAR: () = unsafe { FOO.0 = 99; };
6+
//~^ ERROR could not evaluate static initializer
7+
8+
fn main() {}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
error[E0080]: could not evaluate static initializer
2+
--> $DIR/static_mut_containing_mut_ref3.rs:5:31
3+
|
4+
LL | static mut BAR: () = unsafe { FOO.0 = 99; };
5+
| ^^^^^^^^^^ tried to modify a static's initial value from another static's initializer
6+
7+
error: aborting due to previous error
8+
9+
For more information about this error, try `rustc --explain E0080`.

‎src/test/ui/issues/issue-56199.rs

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
2+
enum Foo {}
3+
struct Bar {}
4+
5+
impl Foo {
6+
fn foo() {
7+
let _ = Self;
8+
//~^ ERROR the `Self` constructor can only be used with tuple or unit structs
9+
let _ = Self();
10+
//~^ ERROR the `Self` constructor can only be used with tuple or unit structs
11+
}
12+
}
13+
14+
impl Bar {
15+
fn bar() {
16+
let _ = Self;
17+
//~^ ERROR the `Self` constructor can only be used with tuple or unit structs
18+
let _ = Self();
19+
//~^ ERROR the `Self` constructor can only be used with tuple or unit structs
20+
}
21+
}
22+
23+
fn main() {}

‎src/test/ui/issues/issue-56199.stderr

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
error: the `Self` constructor can only be used with tuple or unit structs
2+
--> $DIR/issue-56199.rs:7:17
3+
|
4+
LL | let _ = Self;
5+
| ^^^^
6+
|
7+
= note: did you mean to use one of the enum's variants?
8+
9+
error: the `Self` constructor can only be used with tuple or unit structs
10+
--> $DIR/issue-56199.rs:9:17
11+
|
12+
LL | let _ = Self();
13+
| ^^^^
14+
|
15+
= note: did you mean to use one of the enum's variants?
16+
17+
error: the `Self` constructor can only be used with tuple or unit structs
18+
--> $DIR/issue-56199.rs:16:17
19+
|
20+
LL | let _ = Self;
21+
| ^^^^ did you mean `Self { /* fields */ }`?
22+
23+
error: the `Self` constructor can only be used with tuple or unit structs
24+
--> $DIR/issue-56199.rs:18:17
25+
|
26+
LL | let _ = Self();
27+
| ^^^^ did you mean `Self { /* fields */ }`?
28+
29+
error: aborting due to 4 previous errors
30+

‎src/test/ui/issues/issue-56835.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
2+
pub struct Foo {}
3+
4+
impl Foo {
5+
fn bar(Self(foo): Self) {}
6+
//~^ ERROR the `Self` constructor can only be used with tuple or unit structs
7+
//~^^ ERROR expected tuple struct/variant, found self constructor `Self` [E0164]
8+
}
9+
10+
fn main() {}

‎src/test/ui/issues/issue-56835.stderr

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
error: the `Self` constructor can only be used with tuple or unit structs
2+
--> $DIR/issue-56835.rs:5:12
3+
|
4+
LL | fn bar(Self(foo): Self) {}
5+
| ^^^^^^^^^ did you mean `Self { /* fields */ }`?
6+
7+
error[E0164]: expected tuple struct/variant, found self constructor `Self`
8+
--> $DIR/issue-56835.rs:5:12
9+
|
10+
LL | fn bar(Self(foo): Self) {}
11+
| ^^^^^^^^^ not a tuple variant or struct
12+
13+
error: aborting due to 2 previous errors
14+
15+
For more information about this error, try `rustc --explain E0164`.
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
// Regression test for #56288. Checks that if a supertrait defines an associated type
2+
// projection that references `Self`, then that associated type must still be explicitly
3+
// specified in the `dyn Trait` variant, since we don't know what `Self` is anymore.
4+
5+
trait Base {
6+
type Output;
7+
}
8+
9+
trait Helper: Base<Output=<Self as Helper>::Target> {
10+
type Target;
11+
}
12+
13+
impl Base for u32
14+
{
15+
type Output = i32;
16+
}
17+
18+
impl Helper for u32
19+
{
20+
type Target = i32;
21+
}
22+
23+
trait ConstI32 {
24+
type Out;
25+
}
26+
27+
impl<T: ?Sized> ConstI32 for T {
28+
type Out = i32;
29+
}
30+
31+
// Test that you still need to manually give a projection type if the Output type
32+
// is normalizable.
33+
trait NormalizableHelper:
34+
Base<Output=<Self as ConstI32>::Out>
35+
{
36+
type Target;
37+
}
38+
39+
impl NormalizableHelper for u32
40+
{
41+
type Target = i32;
42+
}
43+
44+
fn main() {
45+
let _x: Box<dyn Helper<Target=i32>> = Box::new(2u32);
46+
//~^ ERROR the value of the associated type `Output` (from the trait `Base`) must be specified
47+
48+
let _y: Box<dyn NormalizableHelper<Target=i32>> = Box::new(2u32);
49+
//~^ ERROR the value of the associated type `Output` (from the trait `Base`) must be specified
50+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
error[E0191]: the value of the associated type `Output` (from the trait `Base`) must be specified
2+
--> $DIR/trait-object-with-self-in-projection-output-bad.rs:45:17
3+
|
4+
LL | type Output;
5+
| ------------ `Output` defined here
6+
...
7+
LL | let _x: Box<dyn Helper<Target=i32>> = Box::new(2u32);
8+
| ^^^^^^^^^^^^^^^^^^^^^^ associated type `Output` must be specified
9+
10+
error[E0191]: the value of the associated type `Output` (from the trait `Base`) must be specified
11+
--> $DIR/trait-object-with-self-in-projection-output-bad.rs:48:17
12+
|
13+
LL | type Output;
14+
| ------------ `Output` defined here
15+
...
16+
LL | let _y: Box<dyn NormalizableHelper<Target=i32>> = Box::new(2u32);
17+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ associated type `Output` must be specified
18+
19+
error: aborting due to 2 previous errors
20+
21+
For more information about this error, try `rustc --explain E0191`.
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
// compile-pass
2+
3+
// Regression test related to #56288. Check that a supertrait projection (of
4+
// `Output`) that references `Self` can be ok if it is referencing a projection (of
5+
// `Self::Target`, in this case). Note that we still require the user to manually
6+
// specify both `Target` and `Output` for now.
7+
8+
trait Base {
9+
type Output;
10+
}
11+
12+
trait Helper: Base<Output=<Self as Helper>::Target> {
13+
type Target;
14+
}
15+
16+
impl Base for u32
17+
{
18+
type Output = i32;
19+
}
20+
21+
impl Helper for u32
22+
{
23+
type Target = i32;
24+
}
25+
26+
fn main() {
27+
let _x: Box<dyn Helper<Target=i32, Output=i32>> = Box::new(2u32);
28+
}
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
// compile-pass
2+
3+
// Regression test related to #56288. Check that a supertrait projection (of
4+
// `Output`) that references `Self` is ok if there is another occurence of
5+
// the same supertrait that specifies the projection explicitly, even if
6+
// the projection's associated type is not explicitly specified in the object type.
7+
//
8+
// Note that in order for this to compile, we need the `Self`-referencing projection
9+
// to normalize fairly directly to a concrete type, otherwise the trait resolver
10+
// will hate us.
11+
//
12+
// There is a test in `trait-object-with-self-in-projection-output-bad.rs` that
13+
// having a normalizing, but `Self`-containing projection does not *by itself*
14+
// allow you to avoid writing the projected type (`Output`, in this example)
15+
// explicitly.
16+
17+
trait ConstI32 {
18+
type Out;
19+
}
20+
21+
impl<T: ?Sized> ConstI32 for T {
22+
type Out = i32;
23+
}
24+
25+
trait Base {
26+
type Output;
27+
}
28+
29+
trait NormalizingHelper: Base<Output=<Self as ConstI32>::Out> + Base<Output=i32> {
30+
type Target;
31+
}
32+
33+
impl Base for u32
34+
{
35+
type Output = i32;
36+
}
37+
38+
impl NormalizingHelper for u32
39+
{
40+
type Target = i32;
41+
}
42+
43+
fn main() {
44+
// Make sure this works both with and without the associated type
45+
// being specified.
46+
let _x: Box<dyn NormalizingHelper<Target=i32>> = Box::new(2u32);
47+
let _y: Box<dyn NormalizingHelper<Target=i32, Output=i32>> = Box::new(2u32);
48+
}

‎src/test/ui/write-to-static-mut-in-static.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,10 @@
1212

1313
pub static mut A: u32 = 0;
1414
pub static mut B: () = unsafe { A = 1; };
15-
//~^ ERROR cannot mutate statics in the initializer of another static
15+
//~^ ERROR could not evaluate static initializer
1616

1717
pub static mut C: u32 = unsafe { C = 1; 0 };
18-
//~^ ERROR cannot mutate statics in the initializer of another static
18+
//~^ ERROR cycle detected
1919

2020
pub static D: u32 = D;
2121

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,28 @@
1-
error: cannot mutate statics in the initializer of another static
1+
error[E0080]: could not evaluate static initializer
22
--> $DIR/write-to-static-mut-in-static.rs:14:33
33
|
44
LL | pub static mut B: () = unsafe { A = 1; };
5-
| ^^^^^
5+
| ^^^^^ tried to modify a static's initial value from another static's initializer
66

7-
error: cannot mutate statics in the initializer of another static
7+
error[E0391]: cycle detected when const-evaluating `C`
88
--> $DIR/write-to-static-mut-in-static.rs:17:34
99
|
1010
LL | pub static mut C: u32 = unsafe { C = 1; 0 };
1111
| ^^^^^
12+
|
13+
note: ...which requires const-evaluating `C`...
14+
--> $DIR/write-to-static-mut-in-static.rs:17:1
15+
|
16+
LL | pub static mut C: u32 = unsafe { C = 1; 0 };
17+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
18+
= note: ...which again requires const-evaluating `C`, completing the cycle
19+
note: cycle used when const-evaluating + checking `C`
20+
--> $DIR/write-to-static-mut-in-static.rs:17:1
21+
|
22+
LL | pub static mut C: u32 = unsafe { C = 1; 0 };
23+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
1224

1325
error: aborting due to 2 previous errors
1426

27+
Some errors occurred: E0080, E0391.
28+
For more information about an error, try `rustc --explain E0080`.

0 commit comments

Comments
 (0)
Please sign in to comment.