Skip to content

Commit

Permalink
Rollup merge of rust-lang#61896 - eddyb:correct-self-ctor, r=petroche…
Browse files Browse the repository at this point in the history
…nkov

rustc_typeck: correctly compute `Substs` for `Res::SelfCtor`.

Fixes rust-lang#61882.

r? @petrochenkov cc @varkor
  • Loading branch information
Centril authored Jun 18, 2019
2 parents 4f24715 + dedf2ed commit dcd5b20
Show file tree
Hide file tree
Showing 7 changed files with 109 additions and 53 deletions.
96 changes: 43 additions & 53 deletions src/librustc_typeck/check/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3957,52 +3957,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
Some(original_span.with_lo(original_span.hi() - BytePos(1)))
}

// Rewrite `SelfCtor` to `Ctor`
pub fn rewrite_self_ctor(
&self,
res: Res,
span: Span,
) -> Result<Res, ErrorReported> {
let tcx = self.tcx;
if let Res::SelfCtor(impl_def_id) = res {
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();
let ctor_def_id = variant.ctor_def_id.unwrap();
Ok(Res::Def(DefKind::Ctor(CtorOf::Struct, variant.ctor_kind), ctor_def_id))
}
_ => {
let mut err = 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.help("did you mean to use one of the enum's variants?");
},
AdtKind::Struct |
AdtKind::Union => {
err.span_suggestion(
span,
"use curly brackets",
String::from("Self { /* fields */ }"),
Applicability::HasPlaceholders,
);
}
}
}
err.emit();

Err(ErrorReported)
}
}
} else {
Ok(res)
}
}

// Instantiates the given path, which must refer to an item with the given
// number of type parameters and type.
pub fn instantiate_value_path(&self,
Expand All @@ -4022,12 +3976,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {

let tcx = self.tcx;

let res = match self.rewrite_self_ctor(res, span) {
Ok(res) => res,
Err(ErrorReported) => return (tcx.types.err, res),
};
let path_segs = match res {
Res::Local(_) => vec![],
Res::Local(_) | Res::SelfCtor(_) => vec![],
Res::Def(kind, def_id) =>
AstConv::def_ids_for_value_path_segments(self, segments, self_ty, kind, def_id),
_ => bug!("instantiate_value_path on {:?}", res),
Expand Down Expand Up @@ -4132,13 +4082,53 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
tcx.generics_of(*def_id).has_self
}).unwrap_or(false);

let (res, self_ctor_substs) = if let Res::SelfCtor(impl_def_id) = res {
let ty = self.impl_self_ty(span, impl_def_id).ty;
let adt_def = ty.ty_adt_def();

match ty.sty {
ty::Adt(adt_def, substs) if adt_def.has_ctor() => {
let variant = adt_def.non_enum_variant();
let ctor_def_id = variant.ctor_def_id.unwrap();
(
Res::Def(DefKind::Ctor(CtorOf::Struct, variant.ctor_kind), ctor_def_id),
Some(substs),
)
}
_ => {
let mut err = 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.help("did you mean to use one of the enum's variants?");
},
AdtKind::Struct |
AdtKind::Union => {
err.span_suggestion(
span,
"use curly brackets",
String::from("Self { /* fields */ }"),
Applicability::HasPlaceholders,
);
}
}
}
err.emit();

return (tcx.types.err, res)
}
}
} else {
(res, None)
};
let def_id = res.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 = tcx.type_of(def_id);

let substs = AstConv::create_substs_for_generic_args(
let substs = self_ctor_substs.unwrap_or_else(|| AstConv::create_substs_for_generic_args(
tcx,
def_id,
&[][..],
Expand Down Expand Up @@ -4208,7 +4198,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}
}
},
);
));
assert!(!substs.has_escaping_bound_vars());
assert!(!ty.has_escaping_bound_vars());

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ pub struct Gcm<E>(E);
impl<E> Gcm<E> {
pub fn crash(e: E) -> Self {
Self::<E>(e)
//~^ ERROR type arguments are not allowed for this type
}
}

Expand Down
9 changes: 9 additions & 0 deletions src/test/ui/issues/issue-57924.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
error[E0109]: type arguments are not allowed for this type
--> $DIR/issue-57924.rs:5:16
|
LL | Self::<E>(e)
| ^ type argument not allowed

error: aborting due to previous error

For more information about this error, try `rustc --explain E0109`.
11 changes: 11 additions & 0 deletions src/test/ui/issues/issue-61882-2.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
struct A<T>(T);

impl A<&'static u8> {
fn f() {
let x = 0;
Self(&x);
//~^ ERROR `x` does not live long enough
}
}

fn main() {}
15 changes: 15 additions & 0 deletions src/test/ui/issues/issue-61882-2.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
error[E0597]: `x` does not live long enough
--> $DIR/issue-61882-2.rs:6:14
|
LL | Self(&x);
| ^^
| |
| borrowed value does not live long enough
| requires that `x` is borrowed for `'static`
LL |
LL | }
| - `x` dropped here while still borrowed

error: aborting due to previous error

For more information about this error, try `rustc --explain E0597`.
9 changes: 9 additions & 0 deletions src/test/ui/issues/issue-61882.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
struct A<T>(T);

impl A<bool> {
const B: A<u8> = Self(0);
//~^ ERROR mismatched types
//~| ERROR mismatched types
}

fn main() {}
21 changes: 21 additions & 0 deletions src/test/ui/issues/issue-61882.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
error[E0308]: mismatched types
--> $DIR/issue-61882.rs:4:27
|
LL | const B: A<u8> = Self(0);
| ^ expected bool, found integer
|
= note: expected type `bool`
found type `{integer}`

error[E0308]: mismatched types
--> $DIR/issue-61882.rs:4:22
|
LL | const B: A<u8> = Self(0);
| ^^^^^^^ expected u8, found bool
|
= note: expected type `A<u8>`
found type `A<bool>`

error: aborting due to 2 previous errors

For more information about this error, try `rustc --explain E0308`.

0 comments on commit dcd5b20

Please sign in to comment.